blob: 4f1020c7ad3bafdcfce103b86e98a3b913bd5dbc [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>
Felipe Leme6f674ae2016-11-18 17:10:33 -080077#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070078#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010079#include <cutils/sockets.h>
Kevin Jeon2c02e8e2022-07-07 21:45:17 +000080#include <cutils/trace.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000081#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080082#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000083#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010084#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080085#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010086#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070087#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070088#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070089#include <private/android_filesystem_config.h>
90#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080091#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070092#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000093#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080094#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070095#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070096#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080097
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000098namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
99namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
100namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
101
Vishnu Naire97d6122018-01-18 13:58:56 -0800102using ::std::literals::chrono_literals::operator""ms;
103using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800104using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800105
Felipe Leme47e9be22016-12-21 15:37:07 -0800106// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800107using android::defaultServiceManager;
108using android::Dumpsys;
109using android::INVALID_OPERATION;
110using android::IServiceManager;
111using android::OK;
112using android::sp;
113using android::status_t;
114using android::String16;
115using android::String8;
116using android::TIMED_OUT;
117using android::UNKNOWN_ERROR;
118using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000119using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000120using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800121using android::os::dumpstate::CommandOptions;
122using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800123using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800124using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800125using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800126using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800127
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100128// Keep in sync with
129// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
130static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
131
132/* Most simple commands have 10 as timeout, so 5 is a good estimate */
133static const int32_t WEIGHT_FILE = 5;
134
135// TODO: temporary variables and functions used during C++ refactoring
136static Dumpstate& ds = Dumpstate::GetInstance();
137static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100138 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800139 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
140 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100141}
142
143// Reasonable value for max stats.
144static const int STATS_MAX_N_RUNS = 1000;
145static const long STATS_MAX_AVERAGE = 100000;
146
147CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
148
Nandana Duttd2f5f082019-01-18 17:13:52 +0000149typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
150
Colin Crossf45fa6b2012-03-26 12:38:26 -0700151/* read before root is shed */
152static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700153static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000154static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800155// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
156// it's often the case that they time out far too quickly for consent with such a hefty dialog for
157// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
158// roughly match full reports' durations.
159static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700160
Felipe Leme1d486fe2016-10-14 18:06:47 -0700161// TODO: variables and functions below should be part of dumpstate object
162
Felipe Leme635ca312016-01-05 14:23:02 -0800163static std::set<std::string> mount_points;
164void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800165
Todd Poynor2a83daa2013-11-22 15:44:22 -0800166#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700167#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700168#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800169
Felipe Lemee82a27d2016-01-05 13:35:44 -0800170#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700171#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700172#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700173#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800174#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100175#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
176#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800177#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900178#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800179#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700180#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800181#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900182#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700183#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000184#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700185#define CGROUPFS_DIR "/sys/fs/cgroup"
Mårten Kongstad60195a72022-09-20 14:14:20 +0200186#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700187
Narayan Kamath8f788292017-05-25 13:20:39 +0100188// TODO(narayan): Since this information has to be kept in sync
189// with tombstoned, we should just put it in a common header.
190//
191// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100192static const std::string TOMBSTONE_DIR = "/data/tombstones/";
193static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
194static const std::string ANR_DIR = "/data/anr/";
195static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700196
Felipe Lemee844a9d2016-09-21 15:01:39 -0700197// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000198
Nandana Dutt5c390032019-03-12 10:52:56 +0000199#define RETURN_IF_USER_DENIED_CONSENT() \
200 if (ds.IsUserConsentDenied()) { \
201 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
202 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
203 }
204
205// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
206// if consent is found to be denied.
207#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
208 RETURN_IF_USER_DENIED_CONSENT(); \
209 func_ptr(__VA_ARGS__); \
210 RETURN_IF_USER_DENIED_CONSENT();
211
Rhed Jao5377d792020-07-16 17:37:39 +0800212// Runs func_ptr, and logs a duration report after it's finished.
213#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
214 { \
215 DurationReporter duration_reporter_in_macro(log_title); \
216 func_ptr(__VA_ARGS__); \
217 }
218
219// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
220// is output after a slow function is finished.
221#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
222 RETURN_IF_USER_DENIED_CONSENT(); \
223 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
224 RETURN_IF_USER_DENIED_CONSENT();
225
Chris Morinbc223142022-02-04 14:17:11 -0800226#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800227 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800228 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800229 RETURN_IF_USER_DENIED_CONSENT();
230
Sahana Raof35ed432019-07-12 10:47:52 +0100231static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
232
Rhed Jao5377d792020-07-16 17:37:39 +0800233// Names of parallel tasks, they are used for the DumpPool to identify the dump
234// task and the log title of the duration report.
235static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800236static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
237static const std::string DUMP_HALS_TASK = "DUMP HALS";
238static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800239static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao5377d792020-07-16 17:37:39 +0800240
Nandana Dutt979388e2018-11-30 16:48:55 +0000241namespace android {
242namespace os {
243namespace {
244
245static int Open(std::string path, int flags, mode_t mode = 0) {
246 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
247 if (fd == -1) {
248 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
249 }
250 return fd;
251}
252
mhasank2d75c442020-06-11 15:05:25 -0700253static int OpenForWrite(std::string path) {
254 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
255 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
256}
Nandana Dutt979388e2018-11-30 16:48:55 +0000257
258static int OpenForRead(std::string path) {
259 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
260}
261
262bool CopyFile(int in_fd, int out_fd) {
263 char buf[4096];
264 ssize_t byte_count;
265 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
266 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
267 return false;
268 }
269 }
270 return (byte_count != -1);
271}
272
273static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000274 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000275
276 // Obtain a handle to the source file.
277 android::base::unique_fd in_fd(OpenForRead(input_file));
278 if (out_fd != -1 && in_fd.get() != -1) {
279 if (CopyFile(in_fd.get(), out_fd)) {
280 return true;
281 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000282 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000283 }
284 return false;
285}
286
Nandana Duttd2f5f082019-01-18 17:13:52 +0000287static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000288 if (file.empty()) {
289 return false;
290 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000291 if (unlink(file.c_str())) {
292 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000293 return false;
294 }
295 return true;
296}
Nandana Dutt979388e2018-11-30 16:48:55 +0000297
Nikita Ioffea325a572019-05-16 19:49:47 +0100298int64_t GetModuleMetadataVersion() {
299 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
300 if (binder == nullptr) {
301 MYLOGE("Failed to retrieve package_native service");
302 return 0L;
303 }
304 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
305 std::string package_name;
306 auto status = package_service->getModuleMetadataPackageName(&package_name);
307 if (!status.isOk()) {
308 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
309 return 0L;
310 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100311 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100312 int64_t version_code;
313 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
314 &version_code);
315 if (!status.isOk()) {
316 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
317 return 0L;
318 }
319 return version_code;
320}
321
mhasank2d75c442020-06-11 15:05:25 -0700322static bool PathExists(const std::string& path) {
323 struct stat sb;
324 return stat(path.c_str(), &sb) == 0;
325}
326
327static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
328 if (input_file == output_file) {
329 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
330 output_file.c_str());
331 return false;
332 }
333 else if (PathExists(output_file)) {
334 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
335 return false;
336 }
337
338 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
339 android::base::unique_fd out_fd(OpenForWrite(output_file));
340 return CopyFileToFd(input_file, out_fd.get());
341}
342
Nandana Dutt979388e2018-11-30 16:48:55 +0000343} // namespace
344} // namespace os
345} // namespace android
346
Felipe Leme678727a2016-09-21 17:22:11 -0700347static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800348 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800349 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
350 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
351}
352static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
353 int out_fd) {
354 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700355}
356static int DumpFile(const std::string& title, const std::string& path) {
357 return ds.DumpFile(title, path);
358}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800359
Felipe Lemee844a9d2016-09-21 15:01:39 -0700360// Relative directory (inside the zip) for all files copied as-is into the bugreport.
361static const std::string ZIP_ROOT_DIR = "FS";
362
Vishnu Naire97d6122018-01-18 13:58:56 -0800363static const std::string kProtoPath = "proto/";
364static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700365static const std::string kDumpstateBoardFiles[] = {
366 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700367 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700368};
369static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
370
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700371static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700372static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700373
Felipe Lemef0292972016-11-22 13:57:05 -0800374static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
375
Narayan Kamath8f788292017-05-25 13:20:39 +0100376/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100377 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800378 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800379 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100380 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700381static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800382 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100383 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100384
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700385 if (dump_dir == nullptr) {
386 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700387 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700388 }
389
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700390 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 struct dirent* entry = nullptr;
392 while ((entry = readdir(dump_dir.get()))) {
393 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100394 continue;
395 }
396
Narayan Kamathbd863722017-06-01 18:50:12 +0100397 const std::string base_name(entry->d_name);
398 if (base_name.find(file_prefix) != 0) {
399 continue;
400 }
401
402 const std::string abs_path = dir_path + base_name;
403 android::base::unique_fd fd(
404 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
405 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700406 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100407 break;
408 }
409
410 struct stat st = {};
411 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700412 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100413 continue;
414 }
415
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700416 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700417 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800418 if (!dump_data.empty()) {
419 std::sort(dump_data.begin(), dump_data.end(),
420 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
421 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100422
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700423 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100424}
425
Narayan Kamathbd863722017-06-01 18:50:12 +0100426static bool AddDumps(const std::vector<DumpData>::const_iterator start,
427 const std::vector<DumpData>::const_iterator end,
428 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100429 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100430 for (auto it = start; it != end; ++it) {
431 const std::string& name = it->name;
432 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100433 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100434
435 // Seek to the beginning of the file before dumping any data. A given
436 // DumpData entry might be dumped multiple times in the report.
437 //
438 // For example, the most recent ANR entry is dumped to the body of the
439 // main entry and it also shows up as a separate entry in the bugreport
440 // ZIP file.
441 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
442 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
443 strerror(errno));
444 }
445
Chris Morinc2cba7a2022-02-01 17:06:50 -0800446 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800447 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100448 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100449 }
450 } else {
451 dump_file_from_fd(type_name, name.c_str(), fd);
452 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100453 }
454
455 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700456}
457
Felipe Leme635ca312016-01-05 14:23:02 -0800458// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700459void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800460 char path[PATH_MAX];
461
462 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
463 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700464 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800465 char linkname[PATH_MAX];
466 ssize_t r = readlink(path, linkname, PATH_MAX);
467 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800468 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800469 return;
470 }
471 linkname[r] = '\0';
472
473 if (mount_points.find(linkname) == mount_points.end()) {
474 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700475 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700476 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800477 mount_points.insert(linkname);
478 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800479 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800480 }
481 }
482}
483
484void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700485 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800486 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800487 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700488 for_each_pid(do_mountinfo, nullptr);
489 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800490}
491
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700492static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
493{
494 DIR *d;
495 struct dirent *de;
496 char path[PATH_MAX];
497
498 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700499 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700500 return;
501 }
502
503 while ((de = readdir(d))) {
504 if (de->d_type != DT_LNK) {
505 continue;
506 }
507 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700508 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509 }
510
511 closedir(d);
512}
513
Mark Salyzyn326842f2015-04-30 09:49:41 -0700514static bool skip_not_stat(const char *path) {
515 static const char stat[] = "/stat";
516 size_t len = strlen(path);
517 if (path[len - 1] == '/') { /* Directory? */
518 return false;
519 }
520 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
521}
522
Felipe Leme4c2d6632016-09-28 14:32:00 -0700523static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800524 return false;
525}
526
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700527unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700528
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800529//
530// stat offsets
531// Name units description
532// ---- ----- -----------
533// read I/Os requests number of read I/Os processed
534#define __STAT_READ_IOS 0
535// read merges requests number of read I/Os merged with in-queue I/O
536#define __STAT_READ_MERGES 1
537// read sectors sectors number of sectors read
538#define __STAT_READ_SECTORS 2
539// read ticks milliseconds total wait time for read requests
540#define __STAT_READ_TICKS 3
541// write I/Os requests number of write I/Os processed
542#define __STAT_WRITE_IOS 4
543// write merges requests number of write I/Os merged with in-queue I/O
544#define __STAT_WRITE_MERGES 5
545// write sectors sectors number of sectors written
546#define __STAT_WRITE_SECTORS 6
547// write ticks milliseconds total wait time for write requests
548#define __STAT_WRITE_TICKS 7
549// in_flight requests number of I/Os currently in flight
550#define __STAT_IN_FLIGHT 8
551// io_ticks milliseconds total time this block device has been active
552#define __STAT_IO_TICKS 9
553// time_in_queue milliseconds total wait time for all requests
554#define __STAT_IN_QUEUE 10
555#define __STAT_NUMBER_FIELD 11
556//
557// read I/Os, write I/Os
558// =====================
559//
560// These values increment when an I/O request completes.
561//
562// read merges, write merges
563// =========================
564//
565// These values increment when an I/O request is merged with an
566// already-queued I/O request.
567//
568// read sectors, write sectors
569// ===========================
570//
571// These values count the number of sectors read from or written to this
572// block device. The "sectors" in question are the standard UNIX 512-byte
573// sectors, not any device- or filesystem-specific block size. The
574// counters are incremented when the I/O completes.
575#define SECTOR_SIZE 512
576//
577// read ticks, write ticks
578// =======================
579//
580// These values count the number of milliseconds that I/O requests have
581// waited on this block device. If there are multiple I/O requests waiting,
582// these values will increase at a rate greater than 1000/second; for
583// example, if 60 read requests wait for an average of 30 ms, the read_ticks
584// field will increase by 60*30 = 1800.
585//
586// in_flight
587// =========
588//
589// This value counts the number of I/O requests that have been issued to
590// the device driver but have not yet completed. It does not include I/O
591// requests that are in the queue but not yet issued to the device driver.
592//
593// io_ticks
594// ========
595//
596// This value counts the number of milliseconds during which the device has
597// had I/O requests queued.
598//
599// time_in_queue
600// =============
601//
602// This value counts the number of milliseconds that I/O requests have waited
603// on this block device. If there are multiple I/O requests waiting, this
604// value will increase as the product of the number of milliseconds times the
605// number of requests waiting (see "read ticks" above for an example).
606#define S_TO_MS 1000
607//
608
Mark Salyzyn326842f2015-04-30 09:49:41 -0700609static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800610 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700611 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700612 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700613 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700614 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700615 getline(&buffer, &i, fp);
616 fclose(fp);
617 if (!buffer) {
618 return -errno;
619 }
620 i = strlen(buffer);
621 while ((i > 0) && (buffer[i - 1] == '\n')) {
622 buffer[--i] = '\0';
623 }
624 if (!*buffer) {
625 free(buffer);
626 return 0;
627 }
628 z = true;
629 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 if (fields[i] != 0) {
632 z = false;
633 }
634 }
635 if (z) { /* never accessed */
636 free(buffer);
637 return 0;
638 }
639
Wei Wang509bb5d2017-06-09 14:42:12 -0700640 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
641 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700642 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700643
644 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
645 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
646 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700647 free(buffer);
648
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800649 if (fields[__STAT_IO_TICKS]) {
650 unsigned long read_perf = 0;
651 unsigned long read_ios = 0;
652 if (fields[__STAT_READ_TICKS]) {
653 unsigned long long divisor = fields[__STAT_READ_TICKS]
654 * fields[__STAT_IO_TICKS];
655 read_perf = ((unsigned long long)SECTOR_SIZE
656 * fields[__STAT_READ_SECTORS]
657 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
658 / divisor;
659 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
660 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
661 / divisor;
662 }
663
664 unsigned long write_perf = 0;
665 unsigned long write_ios = 0;
666 if (fields[__STAT_WRITE_TICKS]) {
667 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
668 * fields[__STAT_IO_TICKS];
669 write_perf = ((unsigned long long)SECTOR_SIZE
670 * fields[__STAT_WRITE_SECTORS]
671 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
672 / divisor;
673 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
674 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
675 / divisor;
676 }
677
678 unsigned queue = (fields[__STAT_IN_QUEUE]
679 + (fields[__STAT_IO_TICKS] >> 1))
680 / fields[__STAT_IO_TICKS];
681
682 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700683 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 -0800684 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700685 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 -0800686 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800687 }
688
689 /* bugreport timeout factor adjustment */
690 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
691 worst_write_perf = write_perf;
692 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700693 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700694 return 0;
695}
696
Yao Chenbe3bbc12018-01-17 16:31:10 -0800697static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
698
Tom Cherryf4472f32020-08-05 09:31:17 -0700699// Returns the actual readable size of the given buffer or -1 on error.
700static long logcat_buffer_readable_size(const std::string& buffer) {
701 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
702 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
703 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
704
705 return android_logger_get_log_readable_size(logger);
706}
707
708// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800709static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
710 unsigned long timeout_ms = 0;
711 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700712 long readable_size = logcat_buffer_readable_size(buffer);
713 if (readable_size > 0) {
714 // Engineering margin is ten-fold our guess.
715 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
716 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800717 }
718 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700719}
720
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800721// Opens a socket and returns its file descriptor.
722static int open_socket(const char* service);
723
Nandana Duttd2f5f082019-01-18 17:13:52 +0000724Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
725}
726
727android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
728 std::lock_guard<std::mutex> lock(lock_);
729 result_ = APPROVED;
730 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800731
732 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
733 // consent is granted.
734 if (ds.options_->is_screenshot_copied) {
735 return android::binder::Status::ok();
736 }
737
738 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
739 !ds.do_early_screenshot_) {
740 return android::binder::Status::ok();
741 }
742
743 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
744 ds.options_->screenshot_fd.get());
745 ds.options_->is_screenshot_copied = copy_succeeded;
746 if (copy_succeeded) {
747 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
748 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000749 return android::binder::Status::ok();
750}
751
752android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
753 std::lock_guard<std::mutex> lock(lock_);
754 result_ = DENIED;
755 MYLOGW("User denied consent to share bugreport\n");
756 return android::binder::Status::ok();
757}
758
759UserConsentResult Dumpstate::ConsentCallback::getResult() {
760 std::lock_guard<std::mutex> lock(lock_);
761 return result_;
762}
763
764uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800765 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000766}
767
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700768void Dumpstate::PrintHeader() const {
Mårten Kongstad60195a72022-09-20 14:14:20 +0200769 std::string build, fingerprint, radio, bootloader, network, sdkversion;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700770 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700771
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700772 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
773 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700774 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
775 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
776 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Mårten Kongstad60195a72022-09-20 14:14:20 +0200777 sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700778 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700779
Felipe Lemed8b94e52016-12-08 10:21:44 -0800780 printf("========================================================\n");
781 printf("== dumpstate: %s\n", date);
782 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700783
Felipe Lemed8b94e52016-12-08 10:21:44 -0800784 printf("\n");
785 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700786 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800787 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
788 printf("Bootloader: %s\n", bootloader.c_str());
789 printf("Radio: %s\n", radio.c_str());
790 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100791 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
792 if (module_metadata_version != 0) {
793 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
794 }
Mårten Kongstad60195a72022-09-20 14:14:20 +0200795 printf("Android SDK version: %s\n", sdkversion.c_str());
796 printf("SDK extensions: ");
797 RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
798 CommandOptions::WithTimeout(1).Always().DropRoot().Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700799
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800801 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800803 printf("Uptime: ");
804 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
805 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800807 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
808 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000809 options_->args.c_str(), options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800810 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800811}
812
Felipe Leme24b66ee2016-06-16 10:55:26 -0700813// List of file extensions that can cause a zip file attachment to be rejected by some email
814// service providers.
815static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
816 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
817 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
818 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
819};
820
Vishnu Naire97d6122018-01-18 13:58:56 -0800821status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
822 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700823 std::string valid_name = entry_name;
824
825 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700826 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700827 if (idx != std::string::npos) {
828 std::string extension = entry_name.substr(idx);
829 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
830 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
831 valid_name = entry_name + ".renamed";
832 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
833 }
834 }
835
Felipe Leme6fe9db62016-02-12 09:04:16 -0800836 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
837 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000838 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
839 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700840 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700841 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700842 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700843 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800844 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800845 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000846 bool finished_entry = false;
847 auto finish_entry = [this, &finished_entry] {
848 if (!finished_entry) {
849 // This should only be called when we're going to return an earlier error,
850 // which would've been logged. This may imply the file is already corrupt
851 // and any further logging from FinishEntry is more likely to mislead than
852 // not.
853 this->zip_writer_->FinishEntry();
854 }
855 };
856 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800857 auto start = std::chrono::steady_clock::now();
858 auto end = start + timeout;
859 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800860
Felipe Leme770410d2016-01-26 17:07:14 -0800861 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800862 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800863 if (timeout.count() > 0) {
864 // lambda to recalculate the timeout.
865 auto time_left_ms = [end]() {
866 auto now = std::chrono::steady_clock::now();
867 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
868 return std::max(diff.count(), 0LL);
869 };
870
871 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
872 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000873 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
874 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800875 return -errno;
876 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000877 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800878 entry_name.c_str(), strerror(errno), timeout.count());
879 return TIMED_OUT;
880 }
881 }
882
Zach Riggle22200402016-08-18 01:01:24 -0400883 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 if (bytes_read == 0) {
885 break;
886 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800887 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800888 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800889 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700890 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800891 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700892 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800893 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800894 }
895 }
896
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700897 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000898 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700899 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700900 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800901 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800902 }
903
Vishnu Naire97d6122018-01-18 13:58:56 -0800904 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800905}
906
Felipe Leme1d486fe2016-10-14 18:06:47 -0700907bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
908 android::base::unique_fd fd(
909 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700910 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800911 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912 return false;
913 }
914
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916}
917
918/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700919static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800920 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800921}
922
Felipe Leme1d486fe2016-10-14 18:06:47 -0700923void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700924 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800925 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700926 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800927}
928
Felipe Leme1d486fe2016-10-14 18:06:47 -0700929bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800930 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000931 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
932 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700933 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700934 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700935 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800936 return false;
937 }
938
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700939 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700940 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700941 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700942 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800943 return false;
944 }
945
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700946 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700947 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700948 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800949 return false;
950 }
951
952 return true;
953}
954
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800955static void DoKmsg() {
956 struct stat st;
957 if (!stat(PSTORE_LAST_KMSG, &st)) {
958 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
959 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
960 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
961 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
962 } else {
963 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
964 DumpFile("LAST KMSG", "/proc/last_kmsg");
965 }
966}
967
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800968static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800969 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800970 RunCommand(
971 "KERNEL LOG",
972 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
973 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
974}
975
Nandana Duttdb379fa2019-10-09 16:54:41 +0100976static void DoSystemLogcat(time_t since) {
977 char since_str[80];
978 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
979
980 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
981 RunCommand("SYSTEM LOG",
982 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
983 since_str},
984 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
985}
986
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800987static void DoRadioLogcat() {
988 unsigned long timeout_ms = logcat_timeout({"radio"});
989 RunCommand(
990 "RADIO LOG",
991 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
992 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
993}
994
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800995static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800996 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800997 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
998 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800999 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001000 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001001 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1002 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001003 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001004 RunCommand(
1005 "EVENT LOG",
1006 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001007 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001008 timeout_ms = logcat_timeout({"stats"});
1009 RunCommand(
1010 "STATS LOG",
1011 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001012 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001013 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001014
1015 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1016
1017 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001018 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1019 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001020}
1021
Mike Ma5c267872019-08-21 11:31:34 -07001022static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001023 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1024 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1025 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1026 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1027 if (fd < 0) {
1028 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1029 return;
1030 }
1031 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1032 bool empty = 0 == lseek(fd, 0, SEEK_END);
1033 if (!empty) {
1034 // Use a different name from "incident.proto"
1035 // /proto/incident.proto is reserved for incident service dump
1036 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001037 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1038 path);
1039 } else {
1040 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001041 }
Mike Ma5c267872019-08-21 11:31:34 -07001042}
1043
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001044static void MaybeAddSystemTraceToZip() {
1045 // This function copies into the .zip the system trace that was snapshotted
1046 // by the early call to MaybeSnapshotSystemTrace(), if any background
1047 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001048 if (!ds.has_system_trace_) {
1049 // No background trace was happening at the time dumpstate was invoked.
1050 return;
1051 }
1052 ds.AddZipEntry(
1053 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1054 SYSTEM_TRACE_SNAPSHOT);
1055 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1056}
1057
Sunny Goyal35949782019-11-19 15:54:36 -08001058static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001059 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1060 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1061 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1062 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1063 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1064 if (fd < 0) {
1065 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1066 return;
1067 }
1068 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1069 CommandOptions::WithTimeout(120).Build());
1070 bool empty = 0 == lseek(fd, 0, SEEK_END);
1071 if (!empty) {
1072 ds.AddZipEntry("visible_windows.zip", path);
1073 } else {
1074 MYLOGW("Failed to dump visible windows\n");
1075 }
1076 unlink(path.c_str());
1077}
1078
Jayachandran Ca94c7172017-06-10 15:08:12 -07001079static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001080 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1081 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001082 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001083 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001084 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1085 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1086 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1087 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001088}
1089
David Andersond9ba4752018-12-11 18:26:59 -08001090static void DumpDynamicPartitionInfo() {
1091 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1092 return;
1093 }
1094
1095 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001096 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001097}
1098
Chris Morin5a50d482022-02-01 17:41:18 -08001099static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001100 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1101 anr_traces_dir.c_str());
1102
1103 // If we're here, dump_traces_path will always be a temporary file
1104 // (created with mkostemp or similar) that contains dumps taken earlier
1105 // on in the process.
1106 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001107 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1108 dump_traces_path);
1109 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001110
1111 const int ret = unlink(dump_traces_path);
1112 if (ret == -1) {
1113 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1114 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001115 }
1116 }
1117
Narayan Kamathbd863722017-06-01 18:50:12 +01001118 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001119 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001120 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001121 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001122 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001123
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001124 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001125 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001126 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001127 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001128 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1129 }
1130}
1131
1132static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001133 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001134
Chris Morin5a50d482022-02-01 17:41:18 -08001135 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001136
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001137 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1138
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001139 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001140 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001141 int i = 0;
1142 while (true) {
1143 const std::string slow_trace_path =
1144 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1145 if (stat(slow_trace_path.c_str(), &st)) {
1146 // No traces file at this index, done with the files.
1147 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001148 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001149 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1150 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001151 }
1152}
1153
Wei Wang509bb5d2017-06-09 14:42:12 -07001154static void DumpBlockStatFiles() {
1155 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001156
Wei Wang1dc1ef52017-06-12 11:28:37 -07001157 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1158
1159 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001160 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1161 return;
1162 }
1163
1164 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001165 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001166 if ((d->d_name[0] == '.')
1167 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1168 || (d->d_name[1] == '\0'))) {
1169 continue;
1170 }
1171 const std::string new_path =
1172 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1173 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1174 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1175 printf("\n");
1176 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001177 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001178}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001179
1180static void DumpPacketStats() {
1181 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001182}
1183
1184static void DumpIpAddrAndRules() {
1185 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1186 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1187 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1188 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1189 RunCommand("IP RULES", {"ip", "rule", "show"});
1190 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1191}
1192
Nandana Dutt5c390032019-03-12 10:52:56 +00001193static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1194 std::chrono::milliseconds timeout,
1195 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001196 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001197 sp<android::IServiceManager> sm = defaultServiceManager();
1198 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001199 Vector<String16> args;
1200 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001201 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1202 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001203 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001204 std::string path(title);
1205 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001206 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001207 if (PropertiesHelper::IsDryRun()) {
1208 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1209 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1210 } else {
1211 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1212 if (status == OK) {
1213 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1214 std::chrono::duration<double> elapsed_seconds;
1215 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1216 service == String16("meminfo")) {
1217 // Use a longer timeout for meminfo, since 30s is not always enough.
1218 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1219 /* as_proto = */ false, elapsed_seconds,
1220 bytes_written);
1221 } else {
1222 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1223 /* as_proto = */ false, elapsed_seconds,
1224 bytes_written);
1225 }
1226 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1227 bool dump_complete = (status == OK);
1228 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001229 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001230 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001231
1232 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1233 std::chrono::steady_clock::now() - start);
1234 if (elapsed_duration > timeout) {
1235 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1236 elapsed_duration.count());
1237 break;
1238 }
1239 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001240 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001241}
1242
Vishnu Nair64afc022018-02-01 15:29:34 -08001243static void RunDumpsysText(const std::string& title, int priority,
1244 std::chrono::milliseconds timeout,
1245 std::chrono::milliseconds service_timeout) {
1246 DurationReporter duration_reporter(title);
1247 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1248 fsync(STDOUT_FILENO);
1249 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1250}
1251
1252/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001253static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1254 std::chrono::milliseconds timeout,
1255 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001256 DurationReporter duration_reporter(title);
1257 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1258 fsync(STDOUT_FILENO);
1259 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1260 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001261
1262 RETURN_IF_USER_DENIED_CONSENT();
1263
1264 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1265 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001266}
1267
Nandana Dutt5c390032019-03-12 10:52:56 +00001268static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1269 std::chrono::milliseconds timeout,
1270 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001271 sp<android::IServiceManager> sm = defaultServiceManager();
1272 Dumpsys dumpsys(sm.get());
1273 Vector<String16> args;
1274 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1275 DurationReporter duration_reporter(title);
1276
1277 auto start = std::chrono::steady_clock::now();
1278 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1279 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001280 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001281 std::string path(kProtoPath);
1282 path.append(String8(service).c_str());
1283 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1284 path.append("_CRITICAL");
1285 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1286 path.append("_HIGH");
1287 }
1288 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001289 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001290 if (status == OK) {
1291 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1292 bool dumpTerminated = (status == OK);
1293 dumpsys.stopDumpThread(dumpTerminated);
1294 }
1295 ZipWriter::FileEntry file_entry;
1296 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001297
1298 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1299 std::chrono::steady_clock::now() - start);
1300 if (elapsed_duration > timeout) {
1301 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1302 elapsed_duration.count());
1303 break;
1304 }
1305 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001306 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001307}
1308
Nandana Dutta7db6342018-11-21 14:53:34 +00001309// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001310static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001311 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1312 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001313
1314 RETURN_IF_USER_DENIED_CONSENT();
1315
1316 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1317 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001318}
1319
1320// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001321static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001322 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1323 // high priority. Reduce timeout once they are able to dump in a shorter time or
1324 // moved to a parallel task.
1325 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1326 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001327
1328 RETURN_IF_USER_DENIED_CONSENT();
1329
1330 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1331 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001332}
1333
1334// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001335static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001336 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001337
1338 RETURN_IF_USER_DENIED_CONSENT();
1339
1340 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1341 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001342}
1343
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001344/*
1345 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1346 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1347 * if it's not running in the parallel task.
1348 */
1349static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001350 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001351 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1352 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001353
Steven Moreland44cd9482018-01-04 16:24:13 -08001354 using android::hidl::manager::V1_0::IServiceManager;
1355 using android::hardware::defaultServiceManager;
1356
1357 sp<IServiceManager> sm = defaultServiceManager();
1358 if (sm == nullptr) {
1359 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1360 return;
1361 }
1362
1363 auto ret = sm->list([&](const auto& interfaces) {
1364 for (const std::string& interface : interfaces) {
1365 std::string cleanName = interface;
1366 std::replace_if(cleanName.begin(),
1367 cleanName.end(),
1368 [](char c) {
1369 return !isalnum(c) &&
1370 std::string("@-_:.").find(c) == std::string::npos;
1371 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001372 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001373
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001374 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001375 {
1376 auto fd = android::base::unique_fd(
1377 TEMP_FAILURE_RETRY(open(path.c_str(),
1378 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1379 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1380 if (fd < 0) {
1381 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1382 continue;
1383 }
1384 RunCommandToFd(fd,
1385 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001386 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001387 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1388
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001389 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001390 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001391 if (!empty) {
1392 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1393 path);
1394 } else {
1395 unlink(path.c_str());
1396 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001397 }
1398 });
1399
1400 if (!ret.isOk()) {
1401 MYLOGE("Could not list hals from hwservicemanager.\n");
1402 }
1403}
1404
Devin Moore8df81bb2022-06-08 22:47:02 +00001405// Dump all of the files that make up the vendor interface.
1406// See the files listed in dumpFileList() for the latest list of files.
1407static void DumpVintf() {
1408 const auto vintfFiles = android::vintf::details::dumpFileList();
1409 for (const auto vintfFile : vintfFiles) {
1410 struct stat st;
1411 if (stat(vintfFile.c_str(), &st) == 0) {
1412 if (S_ISDIR(st.st_mode)) {
1413 ds.AddDir(vintfFile, true /* recursive */);
1414 } else {
1415 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1416 vintfFile);
1417 }
1418 }
1419 }
1420}
1421
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001422static void DumpExternalFragmentationInfo() {
1423 struct stat st;
1424 if (stat("/proc/buddyinfo", &st) != 0) {
1425 MYLOGE("Unable to dump external fragmentation info\n");
1426 return;
1427 }
1428
1429 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1430 std::ifstream ifs("/proc/buddyinfo");
1431 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1432 for (std::string line; std::getline(ifs, line);) {
1433 std::smatch match_results;
1434 if (std::regex_match(line, match_results, unusable_index_regex)) {
1435 std::stringstream free_pages(std::string{match_results[3]});
1436 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1437 std::istream_iterator<int>());
1438
1439 int total_free_pages = 0;
1440 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1441 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1442 }
1443
1444 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1445 match_results[2].str().c_str());
1446
1447 int usable_free_pages = total_free_pages;
1448 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1449 auto unusable_index = (total_free_pages - usable_free_pages) /
1450 static_cast<double>(total_free_pages);
1451 printf(" %5.3f", unusable_index);
1452 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1453 }
1454
1455 printf("\n");
1456 }
1457 }
1458 printf("\n");
1459}
1460
mhasankd451a472020-05-26 18:02:39 -07001461static void DumpstateLimitedOnly() {
1462 // Trimmed-down version of dumpstate to only include a whitelisted
1463 // set of logs (system log, event log, and system server / system app
1464 // crashes, and networking logs). See b/136273873 and b/138459828
1465 // for context.
1466 DurationReporter duration_reporter("DUMPSTATE");
1467 unsigned long timeout_ms;
1468 // calculate timeout
1469 timeout_ms = logcat_timeout({"main", "system", "crash"});
1470 RunCommand("SYSTEM LOG",
1471 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1472 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1473 timeout_ms = logcat_timeout({"events"});
1474 RunCommand(
1475 "EVENT LOG",
1476 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1477 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1478
1479 printf("========================================================\n");
1480 printf("== Networking Service\n");
1481 printf("========================================================\n");
1482
1483 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1484 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001485 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1486 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001487
1488 printf("========================================================\n");
1489 printf("== Dropbox crashes\n");
1490 printf("========================================================\n");
1491
1492 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1493 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1494
1495 printf("========================================================\n");
1496 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1497 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1498 printf("========================================================\n");
1499 printf("== dumpstate: done (id %d)\n", ds.id_);
1500 printf("========================================================\n");
1501}
1502
Rhed Jaoe017f982020-07-21 17:58:41 +08001503/*
1504 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1505 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1506 * if it's not running in the parallel task.
1507 */
1508static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1509 dprintf(out_fd, "========================================================\n");
1510 dprintf(out_fd, "== Checkins\n");
1511 dprintf(out_fd, "========================================================\n");
1512
1513 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001514 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1515 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1516 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1517 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1518}
1519
1520/*
1521 * Runs dumpsys on activity service to dump all application activities, services
1522 * and providers in the device.
1523 *
1524 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1525 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1526 * if it's not running in the parallel task.
1527 */
1528static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1529 dprintf(out_fd, "========================================================\n");
1530 dprintf(out_fd, "== Running Application Activities\n");
1531 dprintf(out_fd, "========================================================\n");
1532
1533 // The following dumpsys internally collects output from running apps, so it can take a long
1534 // time. So let's extend the timeout.
1535
1536 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1537
1538 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1539
1540 dprintf(out_fd, "========================================================\n");
1541 dprintf(out_fd, "== Running Application Services (platform)\n");
1542 dprintf(out_fd, "========================================================\n");
1543
1544 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1545 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1546
1547 dprintf(out_fd, "========================================================\n");
1548 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1549 dprintf(out_fd, "========================================================\n");
1550
1551 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1552 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1553
1554 dprintf(out_fd, "========================================================\n");
1555 dprintf(out_fd, "== Running Application Providers (platform)\n");
1556 dprintf(out_fd, "========================================================\n");
1557
1558 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001559 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001560
1561 dprintf(out_fd, "========================================================\n");
1562 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1563 dprintf(out_fd, "========================================================\n");
1564
1565 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1566 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1567}
1568
Nandana Dutt5c390032019-03-12 10:52:56 +00001569// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1570// via the consent they are shown. Ignores other errors that occur while running various
1571// commands. The consent checking is currently done around long running tasks, which happen to
1572// be distributed fairly evenly throughout the function.
1573static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001574 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001575
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001576 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Chris Morinbc223142022-02-04 14:17:11 -08001577 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001578 if (ds.dump_pool_) {
1579 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1580 // drop root user. Restarts it with two threads for the parallel run.
1581 ds.dump_pool_->start(/* thread_counts = */2);
1582
Chris Morinbc223142022-02-04 14:17:11 -08001583 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1584 dump_incident_report = ds.dump_pool_->enqueueTask(
1585 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1586 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1587 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1588 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001589 }
1590
Nandana Dutt5c390032019-03-12 10:52:56 +00001591 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1592 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1593 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001594 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001595 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001596 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001597 DumpFile("MEMORY INFO", "/proc/meminfo");
1598 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001599 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001600
1601 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1602
Sunny Goyal35949782019-11-19 15:54:36 -08001603 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1604
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001605 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1606 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1607 DumpFile("SLAB INFO", "/proc/slabinfo");
1608 DumpFile("ZONEINFO", "/proc/zoneinfo");
1609 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1610 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001611 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001612
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001613 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001614
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001615 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001616 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001617
1618 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1619 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001620
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001621 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001622 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001623 } else {
1624 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1625 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001626
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001627 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001628 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001629 struct stat s;
1630 if (stat("/proc/modules", &s) != 0) {
1631 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1632 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001633 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001634 RunCommand("MODULES INFO",
1635 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1636 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1637 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001638 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001639
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001640 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001641 DoKernelLogcat();
1642 } else {
1643 do_dmesg();
1644 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001645
Devin Moore8df81bb2022-06-08 22:47:02 +00001646 DumpVintf();
1647
Felipe Lemef0292972016-11-22 13:57:05 -08001648 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001649
1650 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1651
Jeff Brown1dc94e32014-09-11 14:15:27 -07001652 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001653 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001654
Jack Yu5a6b2e22020-08-14 18:13:35 +08001655 /* Dump Nfc NCI logs */
1656 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001657
Paul Chang0d2aad72020-02-13 20:04:03 +08001658 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001659 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001660 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001661 }
1662
Felipe Lemee184f662016-10-27 10:04:47 -07001663 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001664
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001665 MaybeAddSystemTraceToZip();
1666
Narayan Kamath8f788292017-05-25 13:20:39 +01001667 // NOTE: tombstones are always added as separate entries in the zip archive
1668 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001669 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001670 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001671 if (!tombstones_dumped) {
1672 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001673 }
1674
Jayachandran Ca94c7172017-06-10 15:08:12 -07001675 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001676
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001677 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001678
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001679 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001680
Jayachandran Ca94c7172017-06-10 15:08:12 -07001681 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001682
1683 dump_route_tables();
1684
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001685 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1686 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1687 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001688
Nandana Dutt5c390032019-03-12 10:52:56 +00001689 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001690
Chiachang Wang668ede42021-05-17 17:14:20 +08001691 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1692 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1693 // dump with priority parameters to dump high priority information.
1694 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1695 CommandOptions::WithTimeout(10).Build());
1696
Elliott Hughes23ccc622017-02-28 10:14:22 -08001697 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001698
Jin Qianf334d662017-10-10 14:41:37 -07001699 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001700
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001701 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001702
Colin Crossf45fa6b2012-03-26 12:38:26 -07001703 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001704 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1705 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1706
1707 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1708 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1709 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1710 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1711 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001713 /* Add window and surface trace files. */
1714 if (!PropertiesHelper::IsUserBuild()) {
1715 ds.AddDir(WMTRACE_DATA_DIR, false);
1716 }
1717
Yifan Hongd90cc652020-02-08 16:52:02 -08001718 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1719
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001720 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001721 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001722 } else {
1723 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1724 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001725
Steven Moreland7440ddb2016-12-15 16:13:39 -08001726 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001727 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1728 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001729 // su does not exist on user builds, so try running without it.
1730 // This way any implementations of vril-dump that do not require
1731 // root can run on user builds.
1732 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001733 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001734 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001735 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001736 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001737 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001738 }
1739
Felipe Lemed8b94e52016-12-08 10:21:44 -08001740 printf("========================================================\n");
1741 printf("== Android Framework Services\n");
1742 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001743
Nandana Dutt5c390032019-03-12 10:52:56 +00001744 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001745
Jack He91ff2fe2021-02-18 18:23:43 -08001746 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1747 ds.AddDir("/data/misc/bluetooth/logs", true);
1748
Rhed Jaoe017f982020-07-21 17:58:41 +08001749 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001750 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001751 } else {
1752 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1753 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001754
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001755 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001756
Adrian Roos8b397ab2017-04-04 16:35:44 -07001757 printf("========================================================\n");
1758 printf("== Dropbox crashes\n");
1759 printf("========================================================\n");
1760
1761 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1762 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1763
Felipe Lemed8b94e52016-12-08 10:21:44 -08001764 printf("========================================================\n");
1765 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1766 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1767 printf("========================================================\n");
1768 printf("== dumpstate: done (id %d)\n", ds.id_);
1769 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001770
1771 printf("========================================================\n");
1772 printf("== Obtaining statsd metadata\n");
1773 printf("========================================================\n");
1774 // This differs from the usual dumpsys stats, which is the stats report data.
1775 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001776
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001777 // Add linker configuration directory
1778 ds.AddDir(LINKERCONFIG_DIR, true);
1779
Li Li830179f2022-01-04 12:53:29 -08001780 /* Dump frozen cgroupfs */
1781 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001782
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001783 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001784 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001785 } else {
1786 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1787 DumpIncidentReport);
1788 }
Mike Ma5c267872019-08-21 11:31:34 -07001789
Nandana Dutt5c390032019-03-12 10:52:56 +00001790 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001791}
1792
Nandana Dutt5c390032019-03-12 10:52:56 +00001793/*
1794 * Dumps state for the default case; drops root after it's no longer necessary.
1795 *
1796 * Returns RunStatus::OK if everything went fine.
1797 * Returns RunStatus::ERROR if there was an error.
1798 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1799 * with the caller.
1800 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001801Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001802 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1803 // buffer.
1804 DoLogcat();
1805 // Capture timestamp after first logcat to use in next logcat
1806 time_t logcat_ts = time(nullptr);
1807
Nandana Dutt4be45d12018-09-26 15:04:23 +01001808 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001809 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001810 if (dump_pool_) {
1811 RETURN_IF_USER_DENIED_CONSENT();
1812 // One thread is enough since we only need to enqueue DumpTraces here.
1813 dump_pool_->start(/* thread_counts = */1);
1814
1815 // DumpTraces takes long time, post it to the another thread in the
1816 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001817 dump_traces = dump_pool_->enqueueTask(
1818 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001819 } else {
1820 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1821 &dump_traces_path);
1822 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001823
1824 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001825 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001826 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1827 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001828 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001829
1830 ds.AddDir(RECOVERY_DIR, true);
1831 ds.AddDir(RECOVERY_DATA_DIR, true);
1832 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1833 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1834 if (!PropertiesHelper::IsUserBuild()) {
1835 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1836 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001837 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001838 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001839 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001840 add_mountinfo();
1841 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001842 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001843 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001844
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001845 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001846 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1847
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001848 // Dump IPsec stats. No keys are exposed here.
1849 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1850
Nandana Dutt4be45d12018-09-26 15:04:23 +01001851 // Run ss as root so we can see socket marks.
1852 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1853
1854 // Run iotop as root to show top 100 IO threads
1855 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1856
Erick Reyese68df822019-02-11 14:46:36 -08001857 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001858 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1859 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001860
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001861 DumpFile("PSI cpu", "/proc/pressure/cpu");
1862 DumpFile("PSI memory", "/proc/pressure/memory");
1863 DumpFile("PSI io", "/proc/pressure/io");
1864
Mårten Kongstad60195a72022-09-20 14:14:20 +02001865 RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
1866 CommandOptions::WithTimeout(10).Always().DropRoot().Build());
1867
Rhed Jao5377d792020-07-16 17:37:39 +08001868 if (dump_pool_) {
1869 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001870 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001871
Chris Morinbc223142022-02-04 14:17:11 -08001872 // Current running thread in the pool is the root user also. Delete
1873 // the pool and make a new one later to ensure none of threads in the pool are root.
1874 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001875 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001876 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001877 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001878 }
1879
Nandana Dutt5c390032019-03-12 10:52:56 +00001880 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001881 Dumpstate::RunStatus status = dumpstate();
1882 // Capture logcat since the last time we did it.
1883 DoSystemLogcat(logcat_ts);
1884 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001885}
1886
Rhed Jaob5685b32020-08-14 17:19:17 +08001887// Common states for telephony and wifi which are needed to be collected before
1888// dumpstate drop the root user.
1889static void DumpstateRadioAsRoot() {
1890 DumpIpTablesAsRoot();
1891 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1892}
1893
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001894// This method collects common dumpsys for telephony and wifi. Typically, wifi
1895// reports are fine to include all information, but telephony reports on user
1896// builds need to strip some content (see DumpstateTelephonyOnly).
1897static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001898 // We need to be picky about some stuff for telephony reports on user builds.
1899 if (!include_sensitive_info) {
1900 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1901 DoRadioLogcat();
1902 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001903 // DumpHals takes long time, post it to the another thread in the pool,
1904 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001905 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001906 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001907 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001908 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001909 // Contains various system properties and process startup info.
1910 do_dmesg();
1911 // Logs other than the radio buffer may contain package/component names and potential PII.
1912 DoLogcat();
1913 // Too broad for connectivity problems.
1914 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001915 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1916 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001917 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08001918 } else {
1919 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1920 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001921 }
1922
Jayachandran Ca94c7172017-06-10 15:08:12 -07001923 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001924 DumpIpAddrAndRules();
1925 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001926 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1927 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001928}
1929
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001930// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1931// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1932// for what can be included on user builds: all reported information MUST directly relate to
1933// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1934// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1935// names are not), and MUST NOT contain logs of user application traffic.
1936// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001937static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001938 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001939
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001940 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001941
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001942 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001943
Rhed Jaob5685b32020-08-14 17:19:17 +08001944 DumpstateRadioAsRoot();
1945 if (!DropRootUser()) {
1946 return;
1947 }
1948
1949 // Starts thread pool after the root user is dropped, and two additional threads
1950 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08001951 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08001952 if (ds.dump_pool_) {
1953 ds.dump_pool_->start(/*thread_counts =*/2);
1954
1955 // DumpstateBoard takes long time, post it to the another thread in the pool,
1956 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001957 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1958 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001959 }
1960
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001961 DumpstateRadioCommon(include_sensitive_info);
1962
1963 if (include_sensitive_info) {
1964 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1965 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1966 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1967 // way.
1968 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1969 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001970
1971 printf("========================================================\n");
1972 printf("== Android Framework Services\n");
1973 printf("========================================================\n");
1974
Vishnu Nair652cc802017-11-30 15:18:30 -08001975 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1976 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001977 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1978 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001979 if (include_sensitive_info) {
1980 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1981 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1982 SEC_TO_MSEC(10));
1983 } else {
1984 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1985 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1986 // give a higher timeout as well.
1987 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1988 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1989 }
1990 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001991 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1992 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001993 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001994 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1995 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001996 if (include_sensitive_info) {
1997 // Contains raw IP addresses, omit from reports on user builds.
1998 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1999 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2000 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2001 SEC_TO_MSEC(10));
2002 // Contains package/component names, omit from reports on user builds.
2003 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2004 SEC_TO_MSEC(10));
2005 // Contains package names, but should be relatively simple to remove them (also contains
2006 // UIDs already), omit from reports on user builds.
2007 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2008 SEC_TO_MSEC(10));
2009 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002010
2011 printf("========================================================\n");
2012 printf("== Running Application Services\n");
2013 printf("========================================================\n");
2014
2015 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2016
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002017 if (include_sensitive_info) {
2018 printf("========================================================\n");
2019 printf("== Running Application Services (non-platform)\n");
2020 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002021
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002022 // Contains package/component names and potential PII, omit from reports on user builds.
2023 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2024 // carrier_config dumpsys instead.
2025 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2026 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002027
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002028 printf("========================================================\n");
2029 printf("== Checkins\n");
2030 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002031
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002032 // Contains package/component names, omit from reports on user builds.
2033 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2034 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002035
2036 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002037 printf("== dumpstate: done (id %d)\n", ds.id_);
2038 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002039
2040 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002041 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002042 } else {
2043 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2044 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002045}
2046
mukesh agrawal253dad42018-01-23 21:59:59 -08002047// This method collects dumpsys for wifi debugging only
2048static void DumpstateWifiOnly() {
2049 DurationReporter duration_reporter("DUMPSTATE");
2050
Rhed Jaob5685b32020-08-14 17:19:17 +08002051 DumpstateRadioAsRoot();
2052 if (!DropRootUser()) {
2053 return;
2054 }
2055
2056 // Starts thread pool after the root user is dropped. Only one additional
2057 // thread is needed for DumpHals in the DumpstateRadioCommon.
2058 if (ds.dump_pool_) {
2059 ds.dump_pool_->start(/*thread_counts =*/1);
2060 }
2061
mukesh agrawal253dad42018-01-23 21:59:59 -08002062 DumpstateRadioCommon();
2063
2064 printf("========================================================\n");
2065 printf("== Android Framework Services\n");
2066 printf("========================================================\n");
2067
2068 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2069 SEC_TO_MSEC(10));
2070 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2071 SEC_TO_MSEC(10));
2072
2073 printf("========================================================\n");
2074 printf("== dumpstate: done (id %d)\n", ds.id_);
2075 printf("========================================================\n");
2076}
2077
Nandana Duttcf419a72019-03-14 10:40:17 +00002078Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002079 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002080 const size_t buf_size = temp_file_pattern.length() + 1;
2081 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2082 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2083
2084 // Create a new, empty file to receive all trace dumps.
2085 //
2086 // TODO: This can be simplified once we remove support for the old style
2087 // dumps. We can have a file descriptor passed in to dump_traces instead
2088 // of creating a file, closing it and then reopening it again.
2089 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2090 if (fd < 0) {
2091 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002092 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002093 }
2094
2095 // Nobody should have access to this temporary file except dumpstate, but we
2096 // temporarily grant 'read' to 'others' here because this file is created
2097 // when tombstoned is still running as root, but dumped after dropping. This
2098 // can go away once support for old style dumping has.
2099 const int chmod_ret = fchmod(fd, 0666);
2100 if (chmod_ret < 0) {
2101 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002102 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002103 }
2104
2105 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2106 if (proc.get() == nullptr) {
2107 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002108 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002109 }
2110
2111 // Number of times process dumping has timed out. If we encounter too many
2112 // failures, we'll give up.
2113 int timeout_failures = 0;
2114 bool dalvik_found = false;
2115
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002116 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002117
2118 struct dirent* d;
2119 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002120 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002121 int pid = atoi(d->d_name);
2122 if (pid <= 0) {
2123 continue;
2124 }
2125
2126 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2127 std::string exe;
2128 if (!android::base::Readlink(link_name, &exe)) {
2129 continue;
2130 }
2131
2132 bool is_java_process;
2133 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2134 // Don't bother dumping backtraces for the zygote.
2135 if (IsZygote(pid)) {
2136 continue;
2137 }
2138
2139 dalvik_found = true;
2140 is_java_process = true;
2141 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2142 is_java_process = false;
2143 } else {
2144 // Probably a native process we don't care about, continue.
2145 continue;
2146 }
2147
2148 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2149 if (timeout_failures == 3) {
2150 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2151 break;
2152 }
2153
2154 const uint64_t start = Nanotime();
2155 const int ret = dump_backtrace_to_file_timeout(
2156 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2157 is_java_process ? 5 : 20, fd);
2158
2159 if (ret == -1) {
2160 // For consistency, the header and footer to this message match those
2161 // dumped by debuggerd in the success case.
2162 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2163 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2164 dprintf(fd, "---- end %d ----", pid);
2165 timeout_failures++;
2166 continue;
2167 }
2168
2169 // We've successfully dumped stack traces, reset the failure count
2170 // and write a summary of the elapsed time to the file and continue with the
2171 // next process.
2172 timeout_failures = 0;
2173
2174 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2175 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2176 }
2177
2178 if (!dalvik_found) {
2179 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2180 }
2181
Nandana Duttcf419a72019-03-14 10:40:17 +00002182 *path = file_name_buf.release();
2183 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002184}
2185
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002186static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2187 const Dumpstate::BugreportMode bugreport_mode) {
2188 switch (bugreport_mode) {
2189 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2190 return dumpstate_hal_hidl::DumpstateMode::FULL;
2191 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2192 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2193 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2194 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2195 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2196 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2197 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2198 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2199 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2200 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2201 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2202 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2203 }
2204 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2205}
2206
2207static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2208 const Dumpstate::BugreportMode bugreport_mode) {
2209 switch (bugreport_mode) {
2210 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2211 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2212 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2213 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2214 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2215 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2216 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2217 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2218 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2219 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2220 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2221 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2222 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2223 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2224 }
2225 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2226}
2227
2228static void DoDumpstateBoardHidl(
2229 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2230 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2231 const Dumpstate::BugreportMode bugreport_mode,
2232 const size_t timeout_sec) {
2233
2234 using ScopedNativeHandle =
2235 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2236 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2237 [](native_handle_t* handle) {
2238 // we don't close file handle's here
2239 // via native_handle_close(handle)
2240 // instead we let dumpstate_fds close the file handles when
2241 // dumpstate_fds gets destroyed
2242 native_handle_delete(handle);
2243 });
2244 if (handle == nullptr) {
2245 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2246 return;
2247 }
2248
2249 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2250 handle.get()->data[i] = dumpstate_fds[i].get();
2251 }
2252
2253 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2254 // implement just 1.0.
2255 const char* descriptor_to_kill;
2256 using DumpstateBoardTask = std::packaged_task<bool()>;
2257 DumpstateBoardTask dumpstate_board_task;
2258 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2259 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2260 if (dumpstate_hal != nullptr) {
2261 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2262
2263 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2264 GetDumpstateHalModeHidl(bugreport_mode);
2265
2266 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2267 dumpstate_board_task =
2268 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2269 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2270 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2271 SEC_TO_MSEC(timeout_sec));
2272 if (!status.isOk()) {
2273 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2274 return false;
2275 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2276 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2277 dumpstate_hal_hidl::toString(status).c_str());
2278 return false;
2279 }
2280 return true;
2281 });
2282 } else {
2283 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2284
2285 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2286 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2287 ::android::hardware::Return<void> status =
2288 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2289 if (!status.isOk()) {
2290 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2291 return false;
2292 }
2293 return true;
2294 });
2295 }
2296 auto result = dumpstate_board_task.get_future();
2297 std::thread(std::move(dumpstate_board_task)).detach();
2298
2299 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2300 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2301 if (!android::base::SetProperty(
2302 "ctl.interface_restart",
2303 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2304 MYLOGE("Couldn't restart dumpstate HAL\n");
2305 }
2306 }
2307 // Wait some time for init to kill dumpstate vendor HAL
2308 constexpr size_t killing_timeout_sec = 10;
2309 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2310 MYLOGE(
2311 "killing dumpstateBoard timed out after %zus, continue and "
2312 "there might be racing in content\n",
2313 killing_timeout_sec);
2314 }
2315}
2316
2317static void DoDumpstateBoardAidl(
2318 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2319 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2320 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2321 MYLOGI("Using IDumpstateDevice AIDL HAL");
2322
2323 const char* descriptor_to_kill;
2324 using DumpstateBoardTask = std::packaged_task<bool()>;
2325 DumpstateBoardTask dumpstate_board_task;
2326 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2327 GetDumpstateHalModeAidl(bugreport_mode);
2328
2329 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2330 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2331 timeout_sec]() -> bool {
2332 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2333
2334 if (!status.isOk()) {
2335 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2336 return false;
2337 }
2338 return true;
2339 });
2340 auto result = dumpstate_board_task.get_future();
2341 std::thread(std::move(dumpstate_board_task)).detach();
2342
2343 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2344 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2345 if (!android::base::SetProperty(
2346 "ctl.interface_restart",
2347 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2348 MYLOGE("Couldn't restart dumpstate HAL\n");
2349 }
2350 }
2351 // Wait some time for init to kill dumpstate vendor HAL
2352 constexpr size_t killing_timeout_sec = 10;
2353 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2354 MYLOGE(
2355 "killing dumpstateBoard timed out after %zus, continue and "
2356 "there might be racing in content\n",
2357 killing_timeout_sec);
2358 }
2359}
2360
2361static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2362 const std::string aidl_instance_name =
2363 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2364
2365 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2366 return nullptr;
2367 }
2368
2369 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2370
2371 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2372}
2373
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002374void Dumpstate::DumpstateBoard(int out_fd) {
2375 dprintf(out_fd, "========================================================\n");
2376 dprintf(out_fd, "== Board\n");
2377 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002378
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002379 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002380 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002381 * set to true and unmount it after invoking dumpstateBoard_* methods.
2382 * This is to enable debug builds to not have debugfs mounted during runtime.
2383 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002384 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002385 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002386 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002387 if (mount_debugfs) {
2388 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2389 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002390 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002391 }
2392
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002393 std::vector<std::string> paths;
2394 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002395 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002396 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2397 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002398 remover.emplace_back(android::base::make_scope_guard(
2399 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002400 }
Jie Song9fbfad02017-06-20 16:29:42 -07002401
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002402 // get dumpstate HAL AIDL implementation
2403 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2404 GetDumpstateBoardAidlService());
2405 if (dumpstate_hal_handle_aidl == nullptr) {
2406 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2407 }
2408
2409 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2410 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2411 if (dumpstate_hal_handle_aidl == nullptr) {
2412 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2413 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2414 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2415 }
2416 }
2417
2418 // if neither HIDL nor AIDL implementation found, then return
2419 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2420 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002421 return;
2422 }
2423
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002424 // this is used to hold the file descriptors and when this variable goes out of scope
2425 // the file descriptors are closed
2426 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002427
Nandana Dutt5c390032019-03-12 10:52:56 +00002428 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002429 for (size_t i = 0; i < paths.size(); i++) {
2430 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2431
2432 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2433 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2434 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2435 if (fd < 0) {
2436 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2437 return;
2438 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002439
2440 dumpstate_fds.emplace_back(fd.release());
2441 // we call fd.release() here to make sure "fd" does not get closed
2442 // after "fd" goes out of scope after this block.
2443 // "fd" will be closed when "dumpstate_fds" goes out of scope
2444 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002445 }
2446
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002447 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2448 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2449 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002450 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002451
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002452 if (dumpstate_hal_handle_aidl != nullptr) {
2453 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2454 timeout_sec);
2455 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2456 // run HIDL HAL only if AIDL HAL not found
2457 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2458 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002459 }
2460
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002461 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002462 auto keep_debugfs_mounted =
2463 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2464 if (keep_debugfs_mounted.empty())
2465 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002466 }
2467
Wei Wang587eac92018-04-05 12:17:20 -07002468 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2469 for (size_t i = 0; i < paths.size(); i++) {
2470 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002471 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2472 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002473 file_sizes[i] = -1;
2474 continue;
2475 }
2476 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002477 }
2478
2479 for (size_t i = 0; i < paths.size(); i++) {
2480 if (file_sizes[i] == -1) {
2481 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002482 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002483 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002484 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002485 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002486 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002487 remover[i].Disable();
2488 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2489 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002490 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002491}
2492
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002493static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002494 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002495 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2496 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002497 " -h: display this help message\n"
2498 " -b: play sound file instead of vibrate, at beginning of job\n"
2499 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002500 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002501 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002502 " -s: write zipped file to control socket (for init)\n"
2503 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002504 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002505 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002506 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002507 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002508 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002509 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002510}
2511
Wei Liuf87959e2016-08-26 14:51:42 -07002512static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002513 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002514}
2515
Felipe Leme1d486fe2016-10-14 18:06:47 -07002516bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002517 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2518 if (zip_entry_tasks_) {
2519 zip_entry_tasks_->run(/* do_cancel = */false);
2520 }
2521
Felipe Leme9a523ae2016-10-20 15:10:33 -07002522 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002523 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002524 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002525 // Final timestamp
2526 char date[80];
2527 time_t the_real_now_please_stand_up = time(nullptr);
2528 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002529 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002530 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002531
Felipe Leme9a523ae2016-10-20 15:10:33 -07002532 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002533 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002534 return false;
2535 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002536 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002537 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002538 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002539 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002540
Felipe Leme0f3fb202016-06-10 17:10:53 -07002541 // Add log file (which contains stderr output) to zip...
2542 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002543 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002544 MYLOGE("Failed to add dumpstate log to .zip file\n");
2545 return false;
2546 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002547 // TODO: Should truncate the existing file.
2548 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002549 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2550 return false;
2551 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002552 fprintf(stderr, "\n");
2553
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002554 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002555 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002556 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002557 return false;
2558 }
2559
Felipe Leme1d486fe2016-10-14 18:06:47 -07002560 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2561 ds.zip_file.reset(nullptr);
2562
Felipe Lemee9d2c542016-11-15 11:48:26 -08002563 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002564 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002565
Felipe Leme1e9edc62015-12-21 16:02:13 -08002566 return true;
2567}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002568
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002569static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2570 // clang-format off
2571 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2572 "--receiver-foreground", "--receiver-include-background", "-a", action};
2573 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002574
2575 am.insert(am.end(), args.begin(), args.end());
2576
Felipe Leme8d2410e2017-02-08 09:46:08 -08002577 RunCommand("", am,
2578 CommandOptions::WithTimeout(20)
2579 .Log("Sending broadcast: '%s'\n")
2580 .Always()
2581 .DropRoot()
2582 .RedirectStderr()
2583 .Build());
2584}
2585
Felipe Leme35b8cf12017-02-10 15:47:29 -08002586static void Vibrate(int duration_ms) {
2587 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002588 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2589 "oneshot", std::to_string(duration_ms)};
2590 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002591 CommandOptions::WithTimeout(10)
2592 .Log("Vibrate: '%s'\n")
2593 .Always()
2594 .Build());
2595 // clang-format on
2596}
2597
Nandana Dutt979388e2018-11-30 16:48:55 +00002598static void MaybeResolveSymlink(std::string* path) {
2599 std::string resolved_path;
2600 if (android::base::Readlink(*path, &resolved_path)) {
2601 *path = resolved_path;
2602 }
2603}
2604
Nandana Dutt4be45d12018-09-26 15:04:23 +01002605/*
2606 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002608 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002609static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002610 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2611
Nandana Dutt4be45d12018-09-26 15:04:23 +01002612 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2613 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002614 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002615 char date[80];
2616 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2617 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002618
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002619 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002620 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002621 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002622 ds.base_name_ += "-wifi";
2623 }
2624
Paul Chang0d2aad72020-02-13 20:04:03 +08002625 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002626 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002627 }
2628 ds.tmp_path_ = ds.GetPath(".tmp");
2629 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2630
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002631 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002632 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002633 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002634 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002635 "Bugreport dir: [%s] "
2636 "Base name: [%s] "
2637 "Suffix: [%s] "
2638 "Log path: [%s] "
2639 "Temporary path: [%s] "
2640 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002641 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2642 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002643
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002644 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2645 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2646 create_parent_dirs(ds.path_.c_str());
2647 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2648 if (ds.zip_file == nullptr) {
2649 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2650 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002651 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002652 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2653 ds.AddTextZipEntry("version.txt", ds.version_);
2654 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002655}
2656
2657/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002658 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002659 * printing zipped file status, etc.
2660 */
2661static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002662 bool do_text_file = !ds.FinishZipFile();
2663 if (do_text_file) {
2664 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002665 }
mhasank2d75c442020-06-11 15:05:25 -07002666
2667 std::string final_path = ds.path_;
2668 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002669 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002670 android::os::CopyFileToFile(ds.path_, final_path);
2671 }
2672
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002673 if (ds.options_->stream_to_socket) {
2674 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2675 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002676 if (do_text_file) {
2677 dprintf(ds.control_socket_fd_,
2678 "FAIL:could not create zip file, check %s "
2679 "for more details\n",
2680 ds.log_path_.c_str());
2681 } else {
mhasank2d75c442020-06-11 15:05:25 -07002682 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002683 }
2684 }
2685}
2686
Nandana Dutt4be45d12018-09-26 15:04:23 +01002687
Nandana Dutt58d72e22018-11-16 10:30:48 +00002688static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2689 switch (mode) {
2690 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2691 return "BUGREPORT_FULL";
2692 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2693 return "BUGREPORT_INTERACTIVE";
2694 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2695 return "BUGREPORT_REMOTE";
2696 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2697 return "BUGREPORT_WEAR";
2698 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2699 return "BUGREPORT_TELEPHONY";
2700 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2701 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002702 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2703 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002704 }
2705}
2706
Paul Changf59c2b72020-03-10 02:08:55 +08002707static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2708 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002709 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2710 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002711 options->bugreport_mode = mode;
2712 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002713 switch (mode) {
2714 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002715 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002716 break;
2717 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002718 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002719 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002720 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002721 break;
2722 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002723 options->do_vibrate = false;
2724 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002725 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002726 break;
2727 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002728 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002729 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002730 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002731 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002732 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002733 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002734 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002735 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002736 break;
2737 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002738 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002739 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002740 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002741 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2742 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002743 }
2744}
2745
Nandana Dutt58d72e22018-11-16 10:30:48 +00002746static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002747 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002748 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002749 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002750 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002751 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002752 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002753 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002754 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002755 options.do_progress_updates, options.bugreport_fd.get(),
2756 options.bugreport_mode_string.c_str(),
2757 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002758}
2759
Nandana Dutt54dbd672019-01-11 12:58:05 +00002760void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2761 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002762 const android::base::unique_fd& screenshot_fd_in,
2763 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002764 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002765 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2766 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002767
Paul Changf59c2b72020-03-10 02:08:55 +08002768 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002769}
2770
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002771Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2772 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002773 int c;
mhasankd451a472020-05-26 18:02:39 -07002774 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002775 switch (c) {
2776 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002777 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002778 case 's': stream_to_socket = true; break;
2779 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002780 case 'v': show_header_only = true; break;
2781 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002782 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002783 case 'P': do_progress_updates = true; break;
2784 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002785 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002786 case 'V':
2787 case 'd':
2788 case 'z':
2789 // compatibility no-op
2790 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002791 case 'w':
2792 // This was already processed
2793 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002794 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002795 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002796 break;
2797 default:
2798 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002799 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002800 break;
2801 // clang-format on
2802 }
2803 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002804
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002805 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002806 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002807 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002808 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002809 }
2810 }
2811
2812 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2813 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002814
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002815 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002816}
2817
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002818bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002819 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002820 return false;
2821 }
2822
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002823 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002824 return false;
2825 }
2826
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002827 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002828 return false;
2829 }
2830 return true;
2831}
2832
Nandana Dutt197661d2018-11-16 16:40:21 +00002833void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2834 options_ = std::move(options);
2835}
2836
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002837void Dumpstate::Initialize() {
2838 /* gets the sequential id */
2839 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2840 id_ = ++last_id;
2841 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2842}
2843
Nandana Duttd2f5f082019-01-18 17:13:52 +00002844Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2845 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002846 if (listener_ != nullptr) {
2847 switch (status) {
2848 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002849 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002850 break;
2851 case Dumpstate::RunStatus::HELP:
2852 break;
2853 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002854 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002855 break;
2856 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002857 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2858 break;
2859 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2860 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2861 break;
2862 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2863 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002864 break;
2865 }
2866 }
2867 return status;
2868}
2869
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002870void Dumpstate::Cancel() {
2871 CleanupTmpFiles();
2872 android::os::UnlinkAndLogOnError(log_path_);
2873 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2874 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2875 kDumpstateBoardFiles[i]);
2876 }
2877 tombstone_data_.clear();
2878 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002879
2880 // Instead of shutdown the pool, we delete temporary files directly since
2881 // shutdown blocking the call.
2882 if (dump_pool_) {
2883 dump_pool_->deleteTempFiles();
2884 }
2885 if (zip_entry_tasks_) {
2886 zip_entry_tasks_->run(/*do_cancel =*/ true);
2887 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002888}
2889
Nandana Dutt979388e2018-11-30 16:48:55 +00002890/*
2891 * Dumps relevant information to a bugreport based on the given options.
2892 *
2893 * The bugreport can be dumped to a file or streamed to a socket.
2894 *
2895 * How dumping to file works:
2896 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2897 * stderr is redirected a log file.
2898 *
2899 * The temporary bugreport is then populated via printfs, dumping contents of files and
2900 * output of commands to stdout.
2901 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002902 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002903 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002904 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002905 *
mhasank2d75c442020-06-11 15:05:25 -07002906 * Bugreports are first generated in a local directory and later copied to the caller's fd
2907 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002908 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002909Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2910 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002911 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002912 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002913 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002914 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002915 return RunStatus::INVALID_INPUT;
2916 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002917 /* set as high priority, and protect from OOM killer */
2918 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002919
Felipe Lemed071c682016-10-20 16:48:00 -07002920 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002921 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002922 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002923 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002924 } else {
2925 /* fallback to kernels <= 2.6.35 */
2926 oom_adj = fopen("/proc/self/oom_adj", "we");
2927 if (oom_adj) {
2928 fputs("-17", oom_adj);
2929 fclose(oom_adj);
2930 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002931 }
2932
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 if (version_ == VERSION_DEFAULT) {
2934 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002935 }
2936
Chris Morin5a50d482022-02-01 17:41:18 -08002937 if (version_ != VERSION_CURRENT) {
2938 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
2939 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002940 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002941 }
2942
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002943 if (options_->show_header_only) {
2944 PrintHeader();
2945 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002946 }
2947
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002948 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2949 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002950
Felipe Leme7447d7c2016-11-03 18:12:22 -07002951 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002952 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002953 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002954 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002955
Sahana Raof35ed432019-07-12 10:47:52 +01002956 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2957 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2958 } else {
2959 // Wake lock will be released automatically on process death
2960 MYLOGD("Wake lock acquired.\n");
2961 }
2962
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002963 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002964
Felipe Lemef0292972016-11-22 13:57:05 -08002965 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002966 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2967 }
2968
Nandana Dutt235c6672019-11-14 15:22:32 +00002969 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002970 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002971
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002972 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002973
Christopher Ferrised9354f2014-10-01 17:35:01 -07002974 // If we are going to use a socket, do it as early as possible
2975 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002976 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002977 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002978 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002979 if (control_socket_fd_ == -1) {
2980 return ERROR;
2981 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002982 if (options_->progress_updates_to_socket) {
2983 options_->do_progress_updates = 1;
2984 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002985 }
2986
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002987 if (!PrepareToWriteToFile()) {
2988 return ERROR;
2989 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002990
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002991 // Interactive, wear & telephony modes are default to true.
2992 // and may enable from cli option or when using control socket
2993 if (options_->do_progress_updates) {
2994 // clang-format off
2995 std::vector<std::string> am_args = {
2996 "--receiver-permission", "android.permission.DUMP",
2997 };
2998 // clang-format on
2999 // Send STARTED broadcast for apps that listen to bugreport generation events
3000 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
3001 if (options_->progress_updates_to_socket) {
3002 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003003 }
3004 }
3005
Nick Kralevichf3599b32016-01-25 15:05:16 -08003006 /* read /proc/cmdline before dropping root */
3007 FILE *cmdline = fopen("/proc/cmdline", "re");
3008 if (cmdline) {
3009 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3010 fclose(cmdline);
3011 }
3012
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003013 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003014 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003015 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003016
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003017 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003018 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3019 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003020 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003021 }
3022 }
3023
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003024 int dup_stdout_fd;
3025 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003026 // Redirect stderr to log_path_ for debugging.
3027 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3028 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3029 return ERROR;
3030 }
3031 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3032 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3033 strerror(errno));
3034 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003035
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003036 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3037 // moved into zip file later, if zipping.
3038 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3039 // TODO: why not write to a file instead of stdout to overcome this problem?
3040 /* TODO: rather than generating a text file now and zipping it later,
3041 it would be more efficient to redirect stdout to the zip entry
3042 directly, but the libziparchive doesn't support that option yet. */
3043 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3044 return ERROR;
3045 }
3046 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3047 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3048 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003049 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003050
3051 // Don't buffer stdout
3052 setvbuf(stdout, nullptr, _IONBF, 0);
3053
Rhed Jao5377d792020-07-16 17:37:39 +08003054 // Enable the parallel run if the client requests to output to a file.
3055 EnableParallelRunIfNeeded();
3056 // Using scope guard to make sure the dump pool can be shut down correctly.
3057 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3058 ShutdownDumpPool();
3059 });
3060
Felipe Leme608385d2016-02-01 10:35:38 -08003061 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3062 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003063 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003064 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003065
Gavin Corkery6968f552020-11-22 18:09:05 +00003066 bool is_dumpstate_restricted = options_->telephony_only
3067 || options_->wifi_only
3068 || options_->limited_only;
3069 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003070 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003071 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003072 }
3073 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003074
3075 if (!is_dumpstate_restricted) {
3076 // Snapshot the system trace now (if running) to avoid that dumpstate's
3077 // own activity pushes out interesting data from the trace ring buffer.
3078 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3079 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003080
3081 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3082 // from WMTRACE_DATA_DIR.
3083 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003084 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003085 onUiIntensiveBugreportDumpsFinished(calling_uid);
3086 MaybeCheckUserConsent(calling_uid, calling_package);
3087 if (options_->telephony_only) {
3088 DumpstateTelephonyOnly(calling_package);
3089 } else if (options_->wifi_only) {
3090 DumpstateWifiOnly();
3091 } else if (options_->limited_only) {
3092 DumpstateLimitedOnly();
3093 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003094 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003095 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003096 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003097 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003098 HandleUserConsentDenied();
3099 }
3100 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003101 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003102 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003103
Felipe Leme55b42a62015-11-10 17:39:08 -08003104 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003105 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003106
Abhijeet Kaure370d682019-10-01 16:49:30 +01003107 // Zip the (now complete) .tmp file within the internal directory.
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003108 ATRACE_BEGIN("FinalizeFile");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003109 FinalizeFile();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003110 ATRACE_END();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003111
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003112 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003113 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01003114 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003115 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003116 if (status != Dumpstate::RunStatus::OK &&
3117 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3118 // Do an early return if there were errors. We make an exception for consent
3119 // timing out because it's possible the user got distracted. In this case the
3120 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003121 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003122 return status;
3123 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003124 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3125 MYLOGI(
3126 "Did not receive user consent yet."
3127 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003128 const String16 incidentcompanion("incidentcompanion");
3129 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3130 if (ics != nullptr) {
3131 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3132 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3133 consent_callback_.get());
3134 } else {
3135 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3136 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003137 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003138 }
3139
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003140 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003141 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003142 for (int i = 0; i < 3; i++) {
3143 Vibrate(75);
3144 usleep((75 + 50) * 1000);
3145 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003146 }
3147
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003148 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3149 progress_->GetInitialMax());
3150 progress_->Save();
3151 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003152
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003153 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003154
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003155 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003156 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003157 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003158 }
3159
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003160 tombstone_data_.clear();
3161 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003162
Nandana Duttd2f5f082019-01-18 17:13:52 +00003163 return (consent_callback_ != nullptr &&
3164 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3165 ? USER_CONSENT_TIMED_OUT
3166 : RunStatus::OK;
3167}
3168
Paul Chang0d2aad72020-02-13 20:04:03 +08003169void Dumpstate::MaybeTakeEarlyScreenshot() {
3170 if (!options_->do_screenshot || !do_early_screenshot_) {
3171 return;
3172 }
3173
3174 TakeScreenshot();
3175}
3176
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003177void Dumpstate::MaybeSnapshotSystemTrace() {
3178 // If a background system trace is happening and is marked as "suitable for
3179 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3180 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3181 // case that no trace is ongoing, this command is a no-op.
3182 // Note: this should not be enqueued as we need to freeze the trace before
3183 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3184 // the dumpstate's own activity which is irrelevant.
3185 int res = RunCommand(
3186 "SERIALIZE PERFETTO TRACE",
3187 {"perfetto", "--save-for-bugreport"},
3188 CommandOptions::WithTimeout(10)
3189 .DropRoot()
3190 .CloseAllFileDescriptorsOnExec()
3191 .Build());
3192 has_system_trace_ = res == 0;
3193 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3194 // file in the later stages.
3195}
3196
Yohei Yukawa95305b32021-03-09 07:54:27 -08003197void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003198 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3199 for (const auto& service : {"window", "input_method"}) {
3200 RunCommand(
3201 // Empty name because it's not intended to be classified as a bugreport section.
3202 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3203 "", {"cmd", service, "tracing", "save-for-bugreport"},
3204 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3205 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003206}
3207
Paul Changeb4b4642020-05-28 22:05:47 +08003208void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003209 if (calling_uid == AID_SHELL || !CalledByApi()) {
3210 return;
3211 }
3212 if (listener_ != nullptr) {
3213 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3214 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003215 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003216 }
3217}
3218
Jichao Lie89d9c12019-11-21 19:02:51 -08003219void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3220 if (calling_uid == AID_SHELL || !CalledByApi()) {
3221 // No need to get consent for shell triggered dumpstates, or not through
3222 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003223 return;
3224 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003225 consent_callback_ = new ConsentCallback();
3226 const String16 incidentcompanion("incidentcompanion");
3227 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003228 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003229 if (ics != nullptr) {
3230 MYLOGD("Checking user consent via incidentcompanion service\n");
3231 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003232 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003233 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003234 } else {
3235 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3236 }
3237}
3238
Nandana Dutt5c390032019-03-12 10:52:56 +00003239bool Dumpstate::IsUserConsentDenied() const {
3240 return ds.consent_callback_ != nullptr &&
3241 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3242}
3243
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003244bool Dumpstate::CalledByApi() const {
3245 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3246}
3247
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003248void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003249 android::os::UnlinkAndLogOnError(tmp_path_);
3250 android::os::UnlinkAndLogOnError(screenshot_path_);
3251 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003252 if (dump_traces_path != nullptr) {
3253 android::os::UnlinkAndLogOnError(dump_traces_path);
3254 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003255}
3256
Rhed Jao5377d792020-07-16 17:37:39 +08003257void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003258 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003259 return;
3260 }
3261 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003262 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003263}
3264
3265void Dumpstate::ShutdownDumpPool() {
3266 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003267 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003268 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003269 if (zip_entry_tasks_) {
3270 zip_entry_tasks_->run(/* do_cancel = */true);
3271 zip_entry_tasks_ = nullptr;
3272 }
3273}
3274
3275void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3276 const std::string& entry_path) {
3277 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3278 if (!task_cancelled) {
3279 AddZipEntry(entry_name, entry_path);
3280 }
3281 android::os::UnlinkAndLogOnError(entry_path);
3282 };
3283 if (zip_entry_tasks_) {
3284 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3285 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3286 } else {
3287 // Invokes AddZipEntryAndCleanup immediately
3288 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3289 }
Rhed Jao5377d792020-07-16 17:37:39 +08003290}
3291
Nandana Duttd2f5f082019-01-18 17:13:52 +00003292Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3293 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003294 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003295 return USER_CONSENT_DENIED;
3296}
3297
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003298Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003299 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003300 // user consent (unless the caller is Shell).
3301 UserConsentResult consent_result;
3302 if (calling_uid == AID_SHELL) {
3303 consent_result = UserConsentResult::APPROVED;
3304 } else {
3305 consent_result = consent_callback_->getResult();
3306 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003307 if (consent_result == UserConsentResult::UNAVAILABLE) {
3308 // User has not responded yet.
3309 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003310 // Telephony is a fast report type, particularly on user builds where information may be
3311 // more aggressively limited. To give the user time to read the consent dialog, increase the
3312 // timeout.
3313 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3314 : USER_CONSENT_TIMEOUT_MS;
3315 if (elapsed_ms < timeout_ms) {
3316 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003317 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3318 sleep(delay_seconds);
3319 }
3320 consent_result = consent_callback_->getResult();
3321 }
3322 if (consent_result == UserConsentResult::DENIED) {
3323 // User has explicitly denied sharing with the app. To be safe delete the
3324 // internal bugreport & tmp files.
3325 return HandleUserConsentDenied();
3326 }
3327 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003328 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3329 if (copy_succeeded) {
3330 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003331 if (options_->do_screenshot &&
3332 options_->screenshot_fd.get() != -1 &&
3333 !options_->is_screenshot_copied) {
3334 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3335 options_->screenshot_fd.get());
3336 options_->is_screenshot_copied = copy_succeeded;
3337 if (copy_succeeded) {
3338 android::os::UnlinkAndLogOnError(screenshot_path_);
3339 }
3340 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003341 }
3342 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3343 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3344 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3345 // Since we do not have user consent to share the bugreport it does not get
3346 // copied over to the calling app but remains in the internal directory from
3347 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003348 std::string final_path = GetPath(".zip");
3349 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3350 if (copy_succeeded) {
3351 android::os::UnlinkAndLogOnError(path_);
3352 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003353 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3354 }
3355 // Unknown result; must be a programming error.
3356 MYLOGE("Unknown user consent result:%d\n", consent_result);
3357 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003358}
3359
Nandana Duttf02564e2019-02-15 15:24:24 +00003360Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003361 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3362 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3363 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003364 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003365 // When directly running dumpstate binary, the output is not expected to be written
3366 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003367 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003368
3369 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003370 // an app; they are irrelevant here because bugreport is triggered via command line.
3371 // Update Last ID before calling Run().
3372 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003373 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003374 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003375 return status;
3376}
3377
3378/* Main entry point for dumpstate binary. */
3379int run_main(int argc, char* argv[]) {
3380 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003381
3382 switch (status) {
3383 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003384 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003385 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003386 ShowUsage();
3387 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003388 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003389 fprintf(stderr, "Invalid combination of args\n");
3390 ShowUsage();
3391 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003392 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003393 FALLTHROUGH_INTENDED;
3394 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3395 FALLTHROUGH_INTENDED;
3396 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003397 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003398 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003399}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003400
3401// TODO(111441001): Default DumpOptions to sensible values.
3402Dumpstate::Dumpstate(const std::string& version)
3403 : pid_(getpid()),
3404 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003405 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003406 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003407 now_(time(nullptr)),
3408 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003409}
3410
3411Dumpstate& Dumpstate::GetInstance() {
3412 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3413 return singleton_;
3414}
3415
Rhed Jao5377d792020-07-16 17:37:39 +08003416DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3417 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3418 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003419 if (!title_.empty()) {
3420 started_ = Nanotime();
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003421 if (title_.find("SHOW MAP") == std::string::npos) {
3422 ATRACE_ASYNC_BEGIN(title_.c_str(), 0);
3423 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003424 }
3425}
3426
3427DurationReporter::~DurationReporter() {
3428 if (!title_.empty()) {
3429 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003430 if (elapsed >= .5f || verbose_) {
3431 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003432 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003433 if (!logcat_only_) {
3434 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003435 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3436 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003437 }
Kevin Jeon2c02e8e2022-07-07 21:45:17 +00003438 if (title_.find("SHOW MAP") == std::string::npos) {
3439 ATRACE_ASYNC_END(title_.c_str(), 0);
3440 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003441 }
3442}
3443
3444const int32_t Progress::kDefaultMax = 5000;
3445
3446Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3447}
3448
3449Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3450 : Progress(initial_max, growth_factor, "") {
3451 progress_ = progress;
3452}
3453
3454Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3455 : initial_max_(initial_max),
3456 progress_(0),
3457 max_(initial_max),
3458 growth_factor_(growth_factor),
3459 n_runs_(0),
3460 average_max_(0),
3461 path_(path) {
3462 if (!path_.empty()) {
3463 Load();
3464 }
3465}
3466
3467void Progress::Load() {
3468 MYLOGD("Loading stats from %s\n", path_.c_str());
3469 std::string content;
3470 if (!android::base::ReadFileToString(path_, &content)) {
3471 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3472 return;
3473 }
3474 if (content.empty()) {
3475 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3476 return;
3477 }
3478 std::vector<std::string> lines = android::base::Split(content, "\n");
3479
3480 if (lines.size() < 1) {
3481 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3482 (int)lines.size(), max_);
3483 return;
3484 }
3485 char* ptr;
3486 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3487 average_max_ = strtol(ptr, nullptr, 10);
3488 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3489 average_max_ > STATS_MAX_AVERAGE) {
3490 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3491 initial_max_ = Progress::kDefaultMax;
3492 } else {
3493 initial_max_ = average_max_;
3494 }
3495 max_ = initial_max_;
3496
3497 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3498}
3499
3500void Progress::Save() {
3501 int32_t total = n_runs_ * average_max_ + progress_;
3502 int32_t runs = n_runs_ + 1;
3503 int32_t average = floor(((float)total) / runs);
3504 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3505 path_.c_str());
3506 if (path_.empty()) {
3507 return;
3508 }
3509
3510 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3511 if (!android::base::WriteStringToFile(content, path_)) {
3512 MYLOGE("Could not save stats on %s\n", path_.c_str());
3513 }
3514}
3515
3516int32_t Progress::Get() const {
3517 return progress_;
3518}
3519
3520bool Progress::Inc(int32_t delta_sec) {
3521 bool changed = false;
3522 if (delta_sec >= 0) {
3523 progress_ += delta_sec;
3524 if (progress_ > max_) {
3525 int32_t old_max = max_;
3526 max_ = floor((float)progress_ * growth_factor_);
3527 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3528 changed = true;
3529 }
3530 }
3531 return changed;
3532}
3533
3534int32_t Progress::GetMax() const {
3535 return max_;
3536}
3537
3538int32_t Progress::GetInitialMax() const {
3539 return initial_max_;
3540}
3541
3542void Progress::Dump(int fd, const std::string& prefix) const {
3543 const char* pr = prefix.c_str();
3544 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3545 dprintf(fd, "%smax: %d\n", pr, max_);
3546 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3547 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3548 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3549 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3550 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3551}
3552
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003553std::string Dumpstate::GetPath(const std::string& suffix) const {
3554 return GetPath(bugreport_internal_dir_, suffix);
3555}
3556
3557std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3558 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3559 name_.c_str(), suffix.c_str());
3560}
3561
3562void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3563 progress_ = std::move(progress);
3564}
3565
3566void for_each_userid(void (*func)(int), const char *header) {
3567 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3568 "for_each_userid(%s)", header);
3569 DurationReporter duration_reporter(title);
3570 if (PropertiesHelper::IsDryRun()) return;
3571
3572 DIR *d;
3573 struct dirent *de;
3574
3575 if (header) printf("\n------ %s ------\n", header);
3576 func(0);
3577
3578 if (!(d = opendir("/data/system/users"))) {
3579 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3580 return;
3581 }
3582
3583 while ((de = readdir(d))) {
3584 int userid;
3585 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3586 continue;
3587 }
3588 func(userid);
3589 }
3590
3591 closedir(d);
3592}
3593
3594static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3595 DIR *d;
3596 struct dirent *de;
3597
3598 if (!(d = opendir("/proc"))) {
3599 printf("Failed to open /proc (%s)\n", strerror(errno));
3600 return;
3601 }
3602
3603 if (header) printf("\n------ %s ------\n", header);
3604 while ((de = readdir(d))) {
3605 if (ds.IsUserConsentDenied()) {
3606 MYLOGE(
3607 "Returning early because user denied consent to share bugreport with calling app.");
3608 closedir(d);
3609 return;
3610 }
3611 int pid;
3612 int fd;
3613 char cmdpath[255];
3614 char cmdline[255];
3615
3616 if (!(pid = atoi(de->d_name))) {
3617 continue;
3618 }
3619
3620 memset(cmdline, 0, sizeof(cmdline));
3621
3622 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3623 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3624 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3625 close(fd);
3626 if (cmdline[0]) {
3627 helper(pid, cmdline, arg);
3628 continue;
3629 }
3630 }
3631
3632 // if no cmdline, a kernel thread has comm
3633 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3634 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3635 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3636 close(fd);
3637 if (cmdline[1]) {
3638 cmdline[0] = '[';
3639 size_t len = strcspn(cmdline, "\f\b\r\n");
3640 cmdline[len] = ']';
3641 cmdline[len+1] = '\0';
3642 }
3643 }
3644 if (!cmdline[0]) {
3645 strcpy(cmdline, "N/A");
3646 }
3647 helper(pid, cmdline, arg);
3648 }
3649
3650 closedir(d);
3651}
3652
3653static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3654 for_each_pid_func *func = (for_each_pid_func*) arg;
3655 func(pid, cmdline);
3656}
3657
3658void for_each_pid(for_each_pid_func func, const char *header) {
3659 std::string title = header == nullptr ? "for_each_pid"
3660 : android::base::StringPrintf("for_each_pid(%s)", header);
3661 DurationReporter duration_reporter(title);
3662 if (PropertiesHelper::IsDryRun()) return;
3663
3664 __for_each_pid(for_each_pid_helper, header, (void *) func);
3665}
3666
3667static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3668 DIR *d;
3669 struct dirent *de;
3670 char taskpath[255];
3671 for_each_tid_func *func = (for_each_tid_func *) arg;
3672
3673 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3674
3675 if (!(d = opendir(taskpath))) {
3676 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3677 return;
3678 }
3679
3680 func(pid, pid, cmdline);
3681
3682 while ((de = readdir(d))) {
3683 if (ds.IsUserConsentDenied()) {
3684 MYLOGE(
3685 "Returning early because user denied consent to share bugreport with calling app.");
3686 closedir(d);
3687 return;
3688 }
3689 int tid;
3690 int fd;
3691 char commpath[255];
3692 char comm[255];
3693
3694 if (!(tid = atoi(de->d_name))) {
3695 continue;
3696 }
3697
3698 if (tid == pid)
3699 continue;
3700
3701 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3702 memset(comm, 0, sizeof(comm));
3703 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3704 strcpy(comm, "N/A");
3705 } else {
3706 char *c;
3707 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3708 close(fd);
3709
3710 c = strrchr(comm, '\n');
3711 if (c) {
3712 *c = '\0';
3713 }
3714 }
3715 func(pid, tid, comm);
3716 }
3717
3718 closedir(d);
3719}
3720
3721void for_each_tid(for_each_tid_func func, const char *header) {
3722 std::string title = header == nullptr ? "for_each_tid"
3723 : android::base::StringPrintf("for_each_tid(%s)", header);
3724 DurationReporter duration_reporter(title);
3725
3726 if (PropertiesHelper::IsDryRun()) return;
3727
3728 __for_each_pid(for_each_tid_helper, header, (void *) func);
3729}
3730
3731void show_wchan(int pid, int tid, const char *name) {
3732 if (PropertiesHelper::IsDryRun()) return;
3733
3734 char path[255];
3735 char buffer[255];
3736 int fd, ret, save_errno;
3737 char name_buffer[255];
3738
3739 memset(buffer, 0, sizeof(buffer));
3740
3741 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3742 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3743 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3744 return;
3745 }
3746
3747 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3748 save_errno = errno;
3749 close(fd);
3750
3751 if (ret < 0) {
3752 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3753 return;
3754 }
3755
3756 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3757 pid == tid ? 0 : 3, "", name);
3758
3759 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3760
3761 return;
3762}
3763
3764// print time in centiseconds
3765static void snprcent(char *buffer, size_t len, size_t spc,
3766 unsigned long long time) {
3767 static long hz; // cache discovered hz
3768
3769 if (hz <= 0) {
3770 hz = sysconf(_SC_CLK_TCK);
3771 if (hz <= 0) {
3772 hz = 1000;
3773 }
3774 }
3775
3776 // convert to centiseconds
3777 time = (time * 100 + (hz / 2)) / hz;
3778
3779 char str[16];
3780
3781 snprintf(str, sizeof(str), " %llu.%02u",
3782 time / 100, (unsigned)(time % 100));
3783 size_t offset = strlen(buffer);
3784 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3785 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3786}
3787
3788// print permille as a percent
3789static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3790 char str[16];
3791
3792 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3793 size_t offset = strlen(buffer);
3794 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3795 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3796}
3797
3798void show_showtime(int pid, const char *name) {
3799 if (PropertiesHelper::IsDryRun()) return;
3800
3801 char path[255];
3802 char buffer[1023];
3803 int fd, ret, save_errno;
3804
3805 memset(buffer, 0, sizeof(buffer));
3806
3807 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3808 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3809 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3810 return;
3811 }
3812
3813 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3814 save_errno = errno;
3815 close(fd);
3816
3817 if (ret < 0) {
3818 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3819 return;
3820 }
3821
3822 // field 14 is utime
3823 // field 15 is stime
3824 // field 42 is iotime
3825 unsigned long long utime = 0, stime = 0, iotime = 0;
3826 if (sscanf(buffer,
3827 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3828 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3829 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3830 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3831 &utime, &stime, &iotime) != 3) {
3832 return;
3833 }
3834
3835 unsigned long long total = utime + stime;
3836 if (!total) {
3837 return;
3838 }
3839
3840 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3841 if (permille > 1000) {
3842 permille = 1000;
3843 }
3844
3845 // try to beautify and stabilize columns at <80 characters
3846 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3847 if ((name[0] != '[') || utime) {
3848 snprcent(buffer, sizeof(buffer), 57, utime);
3849 }
3850 snprcent(buffer, sizeof(buffer), 65, stime);
3851 if ((name[0] != '[') || iotime) {
3852 snprcent(buffer, sizeof(buffer), 73, iotime);
3853 }
3854 if (iotime) {
3855 snprdec(buffer, sizeof(buffer), 79, permille);
3856 }
3857 puts(buffer); // adds a trailing newline
3858
3859 return;
3860}
3861
3862void do_dmesg() {
3863 const char *title = "KERNEL LOG (dmesg)";
3864 DurationReporter duration_reporter(title);
3865 printf("------ %s ------\n", title);
3866
3867 if (PropertiesHelper::IsDryRun()) return;
3868
3869 /* Get size of kernel buffer */
3870 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3871 if (size <= 0) {
3872 printf("Unexpected klogctl return value: %d\n\n", size);
3873 return;
3874 }
3875 char *buf = (char *) malloc(size + 1);
3876 if (buf == nullptr) {
3877 printf("memory allocation failed\n\n");
3878 return;
3879 }
3880 int retval = klogctl(KLOG_READ_ALL, buf, size);
3881 if (retval < 0) {
3882 printf("klogctl failure\n\n");
3883 free(buf);
3884 return;
3885 }
3886 buf[retval] = '\0';
3887 printf("%s\n\n", buf);
3888 free(buf);
3889 return;
3890}
3891
3892void do_showmap(int pid, const char *name) {
3893 char title[255];
3894 char arg[255];
3895
3896 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3897 snprintf(arg, sizeof(arg), "%d", pid);
3898 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3899}
3900
3901int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3902 DurationReporter duration_reporter(title);
3903
3904 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3905
3906 UpdateProgress(WEIGHT_FILE);
3907
3908 return status;
3909}
3910
3911int read_file_as_long(const char *path, long int *output) {
3912 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3913 if (fd < 0) {
3914 int err = errno;
3915 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3916 return -1;
3917 }
3918 char buffer[50];
3919 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3920 if (bytes_read == -1) {
3921 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3922 return -2;
3923 }
3924 if (bytes_read == 0) {
3925 MYLOGE("File %s is empty\n", path);
3926 return -3;
3927 }
3928 *output = atoi(buffer);
3929 return 0;
3930}
3931
3932/* calls skip to gate calling dump_from_fd recursively
3933 * in the specified directory. dump_from_fd defaults to
3934 * dump_file_from_fd above when set to NULL. skip defaults
3935 * to false when set to NULL. dump_from_fd will always be
3936 * called with title NULL.
3937 */
3938int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3939 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3940 DurationReporter duration_reporter(title);
3941 DIR *dirp;
3942 struct dirent *d;
3943 char *newpath = nullptr;
3944 const char *slash = "/";
3945 int retval = 0;
3946
3947 if (!title.empty()) {
3948 printf("------ %s (%s) ------\n", title.c_str(), dir);
3949 }
3950 if (PropertiesHelper::IsDryRun()) return 0;
3951
3952 if (dir[strlen(dir) - 1] == '/') {
3953 ++slash;
3954 }
3955 dirp = opendir(dir);
3956 if (dirp == nullptr) {
3957 retval = -errno;
3958 MYLOGE("%s: %s\n", dir, strerror(errno));
3959 return retval;
3960 }
3961
3962 if (!dump_from_fd) {
3963 dump_from_fd = dump_file_from_fd;
3964 }
3965 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3966 if ((d->d_name[0] == '.')
3967 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3968 || (d->d_name[1] == '\0'))) {
3969 continue;
3970 }
3971 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3972 (d->d_type == DT_DIR) ? "/" : "");
3973 if (!newpath) {
3974 retval = -errno;
3975 continue;
3976 }
3977 if (skip && (*skip)(newpath)) {
3978 continue;
3979 }
3980 if (d->d_type == DT_DIR) {
3981 int ret = dump_files("", newpath, skip, dump_from_fd);
3982 if (ret < 0) {
3983 retval = ret;
3984 }
3985 continue;
3986 }
3987 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3988 if (fd.get() < 0) {
3989 retval = -1;
3990 printf("*** %s: %s\n", newpath, strerror(errno));
3991 continue;
3992 }
3993 (*dump_from_fd)(nullptr, newpath, fd.get());
3994 }
3995 closedir(dirp);
3996 if (!title.empty()) {
3997 printf("\n");
3998 }
3999 return retval;
4000}
4001
4002/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4003 * it's possible to avoid issues where opening the file itself can get
4004 * stuck.
4005 */
4006int dump_file_from_fd(const char *title, const char *path, int fd) {
4007 if (PropertiesHelper::IsDryRun()) return 0;
4008
4009 int flags = fcntl(fd, F_GETFL);
4010 if (flags == -1) {
4011 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4012 return -1;
4013 } else if (!(flags & O_NONBLOCK)) {
4014 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4015 return -1;
4016 }
4017 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4018}
4019
4020int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004021 const CommandOptions& options, bool verbose_duration, int out_fd) {
4022 DurationReporter duration_reporter(title, false /* logcat_only */,
4023 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004024
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004025 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004026
4027 /* TODO: for now we're simplifying the progress calculation by using the
4028 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4029 * where its weight should be much higher proportionally to its timeout.
4030 * Ideally, it should use a options.EstimatedDuration() instead...*/
4031 UpdateProgress(options.Timeout());
4032
4033 return status;
4034}
4035
4036void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004037 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004038 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4039 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4040 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004041 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004042}
4043
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004044static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004045 int s = android_get_control_socket(service);
4046 if (s < 0) {
4047 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4048 return -1;
4049 }
4050 fcntl(s, F_SETFD, FD_CLOEXEC);
4051
4052 // Set backlog to 0 to make sure that queue size will be minimum.
4053 // In Linux, because the minimum queue will be 1, connect() will be blocked
4054 // if the other clients already called connect() and the connection request was not accepted.
4055 if (listen(s, 0) < 0) {
4056 MYLOGE("listen(control socket): %s\n", strerror(errno));
4057 return -1;
4058 }
4059
4060 struct sockaddr addr;
4061 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004062 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004063
4064 // Close socket just after accept(), to make sure that connect() by client will get error
4065 // when the socket is used by the other services.
4066 // There is still a race condition possibility between accept and close, but there is no way
4067 // to close-on-accept atomically.
4068 // See detail; b/123306389#comment25
4069 close(s);
4070
4071 if (fd < 0) {
4072 MYLOGE("accept(control socket): %s\n", strerror(errno));
4073 return -1;
4074 }
4075
4076 return fd;
4077}
4078
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004079// TODO: should call is_valid_output_file and/or be merged into it.
4080void create_parent_dirs(const char *path) {
4081 char *chp = const_cast<char *> (path);
4082
4083 /* skip initial slash */
4084 if (chp[0] == '/')
4085 chp++;
4086
4087 /* create leading directories, if necessary */
4088 struct stat dir_stat;
4089 while (chp && chp[0]) {
4090 chp = strchr(chp, '/');
4091 if (chp) {
4092 *chp = 0;
4093 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4094 MYLOGI("Creating directory %s\n", path);
4095 if (mkdir(path, 0770)) { /* drwxrwx--- */
4096 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4097 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4098 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4099 }
4100 }
4101 *chp++ = '/';
4102 }
4103 }
4104}
4105
4106bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4107 create_parent_dirs(path);
4108
4109 int fd = TEMP_FAILURE_RETRY(open(path,
4110 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4111 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4112 if (fd < 0) {
4113 MYLOGE("%s: %s\n", path, strerror(errno));
4114 return false;
4115 }
4116
4117 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4118 close(fd);
4119 return true;
4120}
4121
4122bool redirect_to_file(FILE* redirect, char* path) {
4123 return _redirect_to_file(redirect, path, O_TRUNC);
4124}
4125
4126bool redirect_to_existing_file(FILE* redirect, char* path) {
4127 return _redirect_to_file(redirect, path, O_APPEND);
4128}
4129
4130void dump_route_tables() {
4131 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4132 if (PropertiesHelper::IsDryRun()) return;
4133 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4134 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4135 FILE* fp = fopen(RT_TABLES_PATH, "re");
4136 if (!fp) {
4137 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4138 return;
4139 }
4140 char table[16];
4141 // Each line has an integer (the table number), a space, and a string (the table name). We only
4142 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4143 // Add a fixed max limit so this doesn't go awry.
4144 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4145 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4146 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4147 }
4148 fclose(fp);
4149}
4150
Li Li830179f2022-01-04 12:53:29 -08004151void dump_frozen_cgroupfs(const char *dir, int level,
4152 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4153 DIR *dirp;
4154 struct dirent *d;
4155 char *newpath = nullptr;
4156
4157 dirp = opendir(dir);
4158 if (dirp == nullptr) {
4159 MYLOGE("%s: %s\n", dir, strerror(errno));
4160 return;
4161 }
4162
4163 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4164 if ((d->d_name[0] == '.')
4165 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4166 || (d->d_name[1] == '\0'))) {
4167 continue;
4168 }
4169 if (d->d_type == DT_DIR) {
4170 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4171 if (!newpath) {
4172 continue;
4173 }
4174 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4175 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4176 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4177 char *freezer = nullptr;
4178 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4179 if (freezer) {
4180 FILE* fp = fopen(freezer, "r");
4181 if (fp != NULL) {
4182 int frozen;
4183 fscanf(fp, "%d", &frozen);
4184 if (frozen > 0) {
4185 dump_files("", newpath, skip_none, dump_from_fd);
4186 }
4187 fclose(fp);
4188 }
4189 free(freezer);
4190 }
4191 }
4192 }
4193 }
4194 closedir(dirp);
4195}
4196
4197void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004198 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4199 DurationReporter duration_reporter("FROZEN CGROUPFS");
4200 if (PropertiesHelper::IsDryRun()) return;
4201 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4202}
4203
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004204void Dumpstate::UpdateProgress(int32_t delta_sec) {
4205 if (progress_ == nullptr) {
4206 MYLOGE("UpdateProgress: progress_ not set\n");
4207 return;
4208 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004209 // This function updates progress related members of the dumpstate and reports
4210 // progress percentage to the bugreport client. Since it could be called by
4211 // different dump tasks at the same time if the parallel run is enabled, a
4212 // mutex lock is necessary here to synchronize the call.
4213 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004214
4215 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004216 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004217
4218 // ...but only notifiy listeners when necessary.
4219 if (!options_->do_progress_updates) return;
4220
4221 int progress = progress_->Get();
4222 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004223 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004224
Nandana Dutt402a8392019-06-14 14:25:13 +01004225 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004226 return;
4227 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004228 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004229
4230 if (control_socket_fd_ >= 0) {
4231 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4232 fsync(control_socket_fd_);
4233 }
4234
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004235 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004236 if (percent % 10 == 0) {
4237 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004238 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004239 } else {
4240 // stderr is ignored on normal invocations, but useful when calling
4241 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004242 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004243 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004244
4245 listener_->onProgress(percent);
4246 }
4247}
4248
4249void Dumpstate::TakeScreenshot(const std::string& path) {
4250 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4251 int status =
4252 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4253 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4254 if (status == 0) {
4255 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4256 } else {
4257 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4258 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004259 if (listener_ != nullptr) {
4260 // Show a visual indication to indicate screenshot is taken via
4261 // IDumpstateListener.onScreenshotTaken()
4262 listener_->onScreenshotTaken(status == 0);
4263 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004264}
4265
4266bool is_dir(const char* pathname) {
4267 struct stat info;
4268 if (stat(pathname, &info) == -1) {
4269 return false;
4270 }
4271 return S_ISDIR(info.st_mode);
4272}
4273
4274time_t get_mtime(int fd, time_t default_mtime) {
4275 struct stat info;
4276 if (fstat(fd, &info) == -1) {
4277 return default_mtime;
4278 }
4279 return info.st_mtime;
4280}