blob: 942a17e79f8098e0a57bb5062b3d8b90a7bc0252 [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"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010022#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070024#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010025#include <math.h>
26#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070027#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -070031#include <sys/mount.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080032#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070033#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070034#include <sys/resource.h>
35#include <sys/stat.h>
36#include <sys/time.h>
37#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010038#include <signal.h>
39#include <stdarg.h>
40#include <string.h>
41#include <sys/capability.h>
42#include <sys/inotify.h>
43#include <sys/klog.h>
44#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070045#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070046
47#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070048#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000049#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070050#include <functional>
51#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010052#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070053#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010054#include <regex>
55#include <set>
56#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070057#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010058#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070059
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000060#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme96c2bbb2016-09-26 09:21:21 -070061#include <android-base/file.h>
62#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070063#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080064#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070065#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070066#include <android-base/unique_fd.h>
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000067#include <android/binder_manager.h>
68#include <android/binder_process.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010069#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080070#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080071#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
72#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080073#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000074#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010075#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080076#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070077#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010078#include <cutils/sockets.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000079#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080080#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000081#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010082#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080083#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010084#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070085#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070086#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070087#include <private/android_filesystem_config.h>
88#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080089#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070090#include <utils/StrongPointer.h>
Devin Moore8df81bb2022-06-08 22:47:02 +000091#include <vintf/VintfObject.h>
Felipe Lemef0292972016-11-22 13:57:05 -080092#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070093#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070094#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080095
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000096namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
97namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
98namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
99
Vishnu Naire97d6122018-01-18 13:58:56 -0800100using ::std::literals::chrono_literals::operator""ms;
101using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800102using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800103
Felipe Leme47e9be22016-12-21 15:37:07 -0800104// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800105using android::defaultServiceManager;
106using android::Dumpsys;
107using android::INVALID_OPERATION;
108using android::IServiceManager;
109using android::OK;
110using android::sp;
111using android::status_t;
112using android::String16;
113using android::String8;
114using android::TIMED_OUT;
115using android::UNKNOWN_ERROR;
116using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000117using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000118using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800119using android::os::dumpstate::CommandOptions;
120using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800121using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800122using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800123using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800124using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800125
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100126// Keep in sync with
127// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
128static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
129
130/* Most simple commands have 10 as timeout, so 5 is a good estimate */
131static const int32_t WEIGHT_FILE = 5;
132
133// TODO: temporary variables and functions used during C++ refactoring
134static Dumpstate& ds = Dumpstate::GetInstance();
135static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100136 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800137 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
138 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100139}
140
141// Reasonable value for max stats.
142static const int STATS_MAX_N_RUNS = 1000;
143static const long STATS_MAX_AVERAGE = 100000;
144
145CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
146
Nandana Duttd2f5f082019-01-18 17:13:52 +0000147typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
148
Colin Crossf45fa6b2012-03-26 12:38:26 -0700149/* read before root is shed */
150static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700151static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000152static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800153// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
154// it's often the case that they time out far too quickly for consent with such a hefty dialog for
155// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
156// roughly match full reports' durations.
157static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700158
Felipe Leme1d486fe2016-10-14 18:06:47 -0700159// TODO: variables and functions below should be part of dumpstate object
160
Felipe Leme635ca312016-01-05 14:23:02 -0800161static std::set<std::string> mount_points;
162void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800163
Todd Poynor2a83daa2013-11-22 15:44:22 -0800164#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700165#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700166#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800167
Felipe Lemee82a27d2016-01-05 13:35:44 -0800168#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700169#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700170#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700171#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800172#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100173#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
174#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800175#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900176#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800177#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700178#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800179#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900180#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700181#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000182#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700183#define CGROUPFS_DIR "/sys/fs/cgroup"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700184
Narayan Kamath8f788292017-05-25 13:20:39 +0100185// TODO(narayan): Since this information has to be kept in sync
186// with tombstoned, we should just put it in a common header.
187//
188// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100189static const std::string TOMBSTONE_DIR = "/data/tombstones/";
190static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
191static const std::string ANR_DIR = "/data/anr/";
192static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700193
Felipe Lemee844a9d2016-09-21 15:01:39 -0700194// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000195
Nandana Dutt5c390032019-03-12 10:52:56 +0000196#define RETURN_IF_USER_DENIED_CONSENT() \
197 if (ds.IsUserConsentDenied()) { \
198 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
199 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
200 }
201
202// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
203// if consent is found to be denied.
204#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
205 RETURN_IF_USER_DENIED_CONSENT(); \
206 func_ptr(__VA_ARGS__); \
207 RETURN_IF_USER_DENIED_CONSENT();
208
Rhed Jao5377d792020-07-16 17:37:39 +0800209// Runs func_ptr, and logs a duration report after it's finished.
210#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
211 { \
212 DurationReporter duration_reporter_in_macro(log_title); \
213 func_ptr(__VA_ARGS__); \
214 }
215
216// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
217// is output after a slow function is finished.
218#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
219 RETURN_IF_USER_DENIED_CONSENT(); \
220 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
221 RETURN_IF_USER_DENIED_CONSENT();
222
Chris Morinbc223142022-02-04 14:17:11 -0800223#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800224 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800225 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800226 RETURN_IF_USER_DENIED_CONSENT();
227
Sahana Raof35ed432019-07-12 10:47:52 +0100228static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
229
Rhed Jao5377d792020-07-16 17:37:39 +0800230// Names of parallel tasks, they are used for the DumpPool to identify the dump
231// task and the log title of the duration report.
232static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800233static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
234static const std::string DUMP_HALS_TASK = "DUMP HALS";
235static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800236static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao5377d792020-07-16 17:37:39 +0800237
Nandana Dutt979388e2018-11-30 16:48:55 +0000238namespace android {
239namespace os {
240namespace {
241
242static int Open(std::string path, int flags, mode_t mode = 0) {
243 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
244 if (fd == -1) {
245 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
246 }
247 return fd;
248}
249
mhasank2d75c442020-06-11 15:05:25 -0700250static int OpenForWrite(std::string path) {
251 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
252 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
253}
Nandana Dutt979388e2018-11-30 16:48:55 +0000254
255static int OpenForRead(std::string path) {
256 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
257}
258
259bool CopyFile(int in_fd, int out_fd) {
260 char buf[4096];
261 ssize_t byte_count;
262 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
263 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
264 return false;
265 }
266 }
267 return (byte_count != -1);
268}
269
270static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000271 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000272
273 // Obtain a handle to the source file.
274 android::base::unique_fd in_fd(OpenForRead(input_file));
275 if (out_fd != -1 && in_fd.get() != -1) {
276 if (CopyFile(in_fd.get(), out_fd)) {
277 return true;
278 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000279 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000280 }
281 return false;
282}
283
Nandana Duttd2f5f082019-01-18 17:13:52 +0000284static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000285 if (file.empty()) {
286 return false;
287 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000288 if (unlink(file.c_str())) {
289 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000290 return false;
291 }
292 return true;
293}
Nandana Dutt979388e2018-11-30 16:48:55 +0000294
Nikita Ioffea325a572019-05-16 19:49:47 +0100295int64_t GetModuleMetadataVersion() {
296 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
297 if (binder == nullptr) {
298 MYLOGE("Failed to retrieve package_native service");
299 return 0L;
300 }
301 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
302 std::string package_name;
303 auto status = package_service->getModuleMetadataPackageName(&package_name);
304 if (!status.isOk()) {
305 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
306 return 0L;
307 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100308 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100309 int64_t version_code;
310 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
311 &version_code);
312 if (!status.isOk()) {
313 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
314 return 0L;
315 }
316 return version_code;
317}
318
mhasank2d75c442020-06-11 15:05:25 -0700319static bool PathExists(const std::string& path) {
320 struct stat sb;
321 return stat(path.c_str(), &sb) == 0;
322}
323
324static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
325 if (input_file == output_file) {
326 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
327 output_file.c_str());
328 return false;
329 }
330 else if (PathExists(output_file)) {
331 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
332 return false;
333 }
334
335 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
336 android::base::unique_fd out_fd(OpenForWrite(output_file));
337 return CopyFileToFd(input_file, out_fd.get());
338}
339
Nandana Dutt979388e2018-11-30 16:48:55 +0000340} // namespace
341} // namespace os
342} // namespace android
343
Felipe Leme678727a2016-09-21 17:22:11 -0700344static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800345 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800346 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
347 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
348}
349static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
350 int out_fd) {
351 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700352}
353static int DumpFile(const std::string& title, const std::string& path) {
354 return ds.DumpFile(title, path);
355}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800356
Felipe Lemee844a9d2016-09-21 15:01:39 -0700357// Relative directory (inside the zip) for all files copied as-is into the bugreport.
358static const std::string ZIP_ROOT_DIR = "FS";
359
Vishnu Naire97d6122018-01-18 13:58:56 -0800360static const std::string kProtoPath = "proto/";
361static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700362static const std::string kDumpstateBoardFiles[] = {
363 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700364 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700365};
366static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
367
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700368static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700369static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700370
Felipe Lemef0292972016-11-22 13:57:05 -0800371static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
372
Narayan Kamath8f788292017-05-25 13:20:39 +0100373/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100374 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800375 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800376 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100377 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700378static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800379 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100380 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100381
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700382 if (dump_dir == nullptr) {
383 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700384 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700385 }
386
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700387 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100388 struct dirent* entry = nullptr;
389 while ((entry = readdir(dump_dir.get()))) {
390 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100391 continue;
392 }
393
Narayan Kamathbd863722017-06-01 18:50:12 +0100394 const std::string base_name(entry->d_name);
395 if (base_name.find(file_prefix) != 0) {
396 continue;
397 }
398
399 const std::string abs_path = dir_path + base_name;
400 android::base::unique_fd fd(
401 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
402 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700403 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100404 break;
405 }
406
407 struct stat st = {};
408 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700409 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100410 continue;
411 }
412
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700413 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700414 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800415 if (!dump_data.empty()) {
416 std::sort(dump_data.begin(), dump_data.end(),
417 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
418 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100419
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700420 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100421}
422
Narayan Kamathbd863722017-06-01 18:50:12 +0100423static bool AddDumps(const std::vector<DumpData>::const_iterator start,
424 const std::vector<DumpData>::const_iterator end,
425 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100426 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100427 for (auto it = start; it != end; ++it) {
428 const std::string& name = it->name;
429 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100430 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100431
432 // Seek to the beginning of the file before dumping any data. A given
433 // DumpData entry might be dumped multiple times in the report.
434 //
435 // For example, the most recent ANR entry is dumped to the body of the
436 // main entry and it also shows up as a separate entry in the bugreport
437 // ZIP file.
438 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
439 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
440 strerror(errno));
441 }
442
Chris Morinc2cba7a2022-02-01 17:06:50 -0800443 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800444 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100445 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100446 }
447 } else {
448 dump_file_from_fd(type_name, name.c_str(), fd);
449 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100450 }
451
452 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700453}
454
Felipe Leme635ca312016-01-05 14:23:02 -0800455// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700456void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800457 char path[PATH_MAX];
458
459 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
460 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700461 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800462 char linkname[PATH_MAX];
463 ssize_t r = readlink(path, linkname, PATH_MAX);
464 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800465 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800466 return;
467 }
468 linkname[r] = '\0';
469
470 if (mount_points.find(linkname) == mount_points.end()) {
471 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700472 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700473 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800474 mount_points.insert(linkname);
475 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800476 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800477 }
478 }
479}
480
481void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700482 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800483 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800484 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700485 for_each_pid(do_mountinfo, nullptr);
486 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800487}
488
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700489static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
490{
491 DIR *d;
492 struct dirent *de;
493 char path[PATH_MAX];
494
495 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700496 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700497 return;
498 }
499
500 while ((de = readdir(d))) {
501 if (de->d_type != DT_LNK) {
502 continue;
503 }
504 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700505 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700506 }
507
508 closedir(d);
509}
510
Mark Salyzyn326842f2015-04-30 09:49:41 -0700511static bool skip_not_stat(const char *path) {
512 static const char stat[] = "/stat";
513 size_t len = strlen(path);
514 if (path[len - 1] == '/') { /* Directory? */
515 return false;
516 }
517 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
518}
519
Felipe Leme4c2d6632016-09-28 14:32:00 -0700520static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800521 return false;
522}
523
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700524unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700525
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800526//
527// stat offsets
528// Name units description
529// ---- ----- -----------
530// read I/Os requests number of read I/Os processed
531#define __STAT_READ_IOS 0
532// read merges requests number of read I/Os merged with in-queue I/O
533#define __STAT_READ_MERGES 1
534// read sectors sectors number of sectors read
535#define __STAT_READ_SECTORS 2
536// read ticks milliseconds total wait time for read requests
537#define __STAT_READ_TICKS 3
538// write I/Os requests number of write I/Os processed
539#define __STAT_WRITE_IOS 4
540// write merges requests number of write I/Os merged with in-queue I/O
541#define __STAT_WRITE_MERGES 5
542// write sectors sectors number of sectors written
543#define __STAT_WRITE_SECTORS 6
544// write ticks milliseconds total wait time for write requests
545#define __STAT_WRITE_TICKS 7
546// in_flight requests number of I/Os currently in flight
547#define __STAT_IN_FLIGHT 8
548// io_ticks milliseconds total time this block device has been active
549#define __STAT_IO_TICKS 9
550// time_in_queue milliseconds total wait time for all requests
551#define __STAT_IN_QUEUE 10
552#define __STAT_NUMBER_FIELD 11
553//
554// read I/Os, write I/Os
555// =====================
556//
557// These values increment when an I/O request completes.
558//
559// read merges, write merges
560// =========================
561//
562// These values increment when an I/O request is merged with an
563// already-queued I/O request.
564//
565// read sectors, write sectors
566// ===========================
567//
568// These values count the number of sectors read from or written to this
569// block device. The "sectors" in question are the standard UNIX 512-byte
570// sectors, not any device- or filesystem-specific block size. The
571// counters are incremented when the I/O completes.
572#define SECTOR_SIZE 512
573//
574// read ticks, write ticks
575// =======================
576//
577// These values count the number of milliseconds that I/O requests have
578// waited on this block device. If there are multiple I/O requests waiting,
579// these values will increase at a rate greater than 1000/second; for
580// example, if 60 read requests wait for an average of 30 ms, the read_ticks
581// field will increase by 60*30 = 1800.
582//
583// in_flight
584// =========
585//
586// This value counts the number of I/O requests that have been issued to
587// the device driver but have not yet completed. It does not include I/O
588// requests that are in the queue but not yet issued to the device driver.
589//
590// io_ticks
591// ========
592//
593// This value counts the number of milliseconds during which the device has
594// had I/O requests queued.
595//
596// time_in_queue
597// =============
598//
599// This value counts the number of milliseconds that I/O requests have waited
600// on this block device. If there are multiple I/O requests waiting, this
601// value will increase as the product of the number of milliseconds times the
602// number of requests waiting (see "read ticks" above for an example).
603#define S_TO_MS 1000
604//
605
Mark Salyzyn326842f2015-04-30 09:49:41 -0700606static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800607 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700608 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700609 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700610 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700611 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700612 getline(&buffer, &i, fp);
613 fclose(fp);
614 if (!buffer) {
615 return -errno;
616 }
617 i = strlen(buffer);
618 while ((i > 0) && (buffer[i - 1] == '\n')) {
619 buffer[--i] = '\0';
620 }
621 if (!*buffer) {
622 free(buffer);
623 return 0;
624 }
625 z = true;
626 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628 if (fields[i] != 0) {
629 z = false;
630 }
631 }
632 if (z) { /* never accessed */
633 free(buffer);
634 return 0;
635 }
636
Wei Wang509bb5d2017-06-09 14:42:12 -0700637 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
638 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700639 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700640
641 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
642 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
643 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700644 free(buffer);
645
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800646 if (fields[__STAT_IO_TICKS]) {
647 unsigned long read_perf = 0;
648 unsigned long read_ios = 0;
649 if (fields[__STAT_READ_TICKS]) {
650 unsigned long long divisor = fields[__STAT_READ_TICKS]
651 * fields[__STAT_IO_TICKS];
652 read_perf = ((unsigned long long)SECTOR_SIZE
653 * fields[__STAT_READ_SECTORS]
654 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
655 / divisor;
656 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
657 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
658 / divisor;
659 }
660
661 unsigned long write_perf = 0;
662 unsigned long write_ios = 0;
663 if (fields[__STAT_WRITE_TICKS]) {
664 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
665 * fields[__STAT_IO_TICKS];
666 write_perf = ((unsigned long long)SECTOR_SIZE
667 * fields[__STAT_WRITE_SECTORS]
668 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
669 / divisor;
670 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
671 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
672 / divisor;
673 }
674
675 unsigned queue = (fields[__STAT_IN_QUEUE]
676 + (fields[__STAT_IO_TICKS] >> 1))
677 / fields[__STAT_IO_TICKS];
678
679 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700680 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 -0800681 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700682 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 -0800683 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800684 }
685
686 /* bugreport timeout factor adjustment */
687 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
688 worst_write_perf = write_perf;
689 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700690 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700691 return 0;
692}
693
Yao Chenbe3bbc12018-01-17 16:31:10 -0800694static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
695
Tom Cherryf4472f32020-08-05 09:31:17 -0700696// Returns the actual readable size of the given buffer or -1 on error.
697static long logcat_buffer_readable_size(const std::string& buffer) {
698 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
699 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
700 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
701
702 return android_logger_get_log_readable_size(logger);
703}
704
705// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800706static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
707 unsigned long timeout_ms = 0;
708 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700709 long readable_size = logcat_buffer_readable_size(buffer);
710 if (readable_size > 0) {
711 // Engineering margin is ten-fold our guess.
712 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
713 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800714 }
715 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700716}
717
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800718// Opens a socket and returns its file descriptor.
719static int open_socket(const char* service);
720
Nandana Duttd2f5f082019-01-18 17:13:52 +0000721Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
722}
723
724android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
725 std::lock_guard<std::mutex> lock(lock_);
726 result_ = APPROVED;
727 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800728
729 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
730 // consent is granted.
731 if (ds.options_->is_screenshot_copied) {
732 return android::binder::Status::ok();
733 }
734
735 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
736 !ds.do_early_screenshot_) {
737 return android::binder::Status::ok();
738 }
739
740 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
741 ds.options_->screenshot_fd.get());
742 ds.options_->is_screenshot_copied = copy_succeeded;
743 if (copy_succeeded) {
744 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
745 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000746 return android::binder::Status::ok();
747}
748
749android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
750 std::lock_guard<std::mutex> lock(lock_);
751 result_ = DENIED;
752 MYLOGW("User denied consent to share bugreport\n");
753 return android::binder::Status::ok();
754}
755
756UserConsentResult Dumpstate::ConsentCallback::getResult() {
757 std::lock_guard<std::mutex> lock(lock_);
758 return result_;
759}
760
761uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800762 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000763}
764
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700765void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700766 std::string build, fingerprint, radio, bootloader, network;
767 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700768
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700769 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
770 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700771 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
772 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
773 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700774 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700775
Felipe Lemed8b94e52016-12-08 10:21:44 -0800776 printf("========================================================\n");
777 printf("== dumpstate: %s\n", date);
778 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700779
Felipe Lemed8b94e52016-12-08 10:21:44 -0800780 printf("\n");
781 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700782 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800783 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
784 printf("Bootloader: %s\n", bootloader.c_str());
785 printf("Radio: %s\n", radio.c_str());
786 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100787 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
788 if (module_metadata_version != 0) {
789 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
790 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100791 printf("SDK extension versions [r=%s s=%s]\n",
792 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
793 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700794
Felipe Lemed8b94e52016-12-08 10:21:44 -0800795 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800796 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800797 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800798 printf("Uptime: ");
799 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
800 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800802 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
803 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000804 options_->args.c_str(), options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800806}
807
Felipe Leme24b66ee2016-06-16 10:55:26 -0700808// List of file extensions that can cause a zip file attachment to be rejected by some email
809// service providers.
810static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
811 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
812 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
813 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
814};
815
Vishnu Naire97d6122018-01-18 13:58:56 -0800816status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
817 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700818 std::string valid_name = entry_name;
819
820 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700821 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700822 if (idx != std::string::npos) {
823 std::string extension = entry_name.substr(idx);
824 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
825 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
826 valid_name = entry_name + ".renamed";
827 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
828 }
829 }
830
Felipe Leme6fe9db62016-02-12 09:04:16 -0800831 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
832 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000833 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
834 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), flags,
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700835 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700836 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700837 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700838 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800839 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800840 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000841 bool finished_entry = false;
842 auto finish_entry = [this, &finished_entry] {
843 if (!finished_entry) {
844 // This should only be called when we're going to return an earlier error,
845 // which would've been logged. This may imply the file is already corrupt
846 // and any further logging from FinishEntry is more likely to mislead than
847 // not.
848 this->zip_writer_->FinishEntry();
849 }
850 };
851 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800852 auto start = std::chrono::steady_clock::now();
853 auto end = start + timeout;
854 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800855
Felipe Leme770410d2016-01-26 17:07:14 -0800856 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800857 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800858 if (timeout.count() > 0) {
859 // lambda to recalculate the timeout.
860 auto time_left_ms = [end]() {
861 auto now = std::chrono::steady_clock::now();
862 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
863 return std::max(diff.count(), 0LL);
864 };
865
866 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
867 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000868 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
869 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 return -errno;
871 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000872 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800873 entry_name.c_str(), strerror(errno), timeout.count());
874 return TIMED_OUT;
875 }
876 }
877
Zach Riggle22200402016-08-18 01:01:24 -0400878 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800879 if (bytes_read == 0) {
880 break;
881 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800882 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800883 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700885 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800886 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700887 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800888 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800889 }
890 }
891
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700892 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000893 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700894 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700895 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800896 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800897 }
898
Vishnu Naire97d6122018-01-18 13:58:56 -0800899 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800900}
901
Felipe Leme1d486fe2016-10-14 18:06:47 -0700902bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
903 android::base::unique_fd fd(
904 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700905 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800906 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907 return false;
908 }
909
Vishnu Naire97d6122018-01-18 13:58:56 -0800910 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911}
912
913/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700914static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800915 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916}
917
Felipe Leme1d486fe2016-10-14 18:06:47 -0700918void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700919 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800920 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700921 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800922}
923
Felipe Leme1d486fe2016-10-14 18:06:47 -0700924bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800925 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Kevin Jeon9bbe0ac2022-05-05 22:05:43 +0000926 size_t flags = ZipWriter::kCompress | ZipWriter::kDefaultCompression;
927 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), flags, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700928 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700929 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800931 return false;
932 }
933
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700934 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700935 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700936 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700937 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800938 return false;
939 }
940
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700941 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700942 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700943 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800944 return false;
945 }
946
947 return true;
948}
949
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800950static void DoKmsg() {
951 struct stat st;
952 if (!stat(PSTORE_LAST_KMSG, &st)) {
953 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
954 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
955 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
956 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
957 } else {
958 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
959 DumpFile("LAST KMSG", "/proc/last_kmsg");
960 }
961}
962
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800963static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800964 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800965 RunCommand(
966 "KERNEL LOG",
967 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
968 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
969}
970
Nandana Duttdb379fa2019-10-09 16:54:41 +0100971static void DoSystemLogcat(time_t since) {
972 char since_str[80];
973 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
974
975 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
976 RunCommand("SYSTEM LOG",
977 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
978 since_str},
979 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
980}
981
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800982static void DoRadioLogcat() {
983 unsigned long timeout_ms = logcat_timeout({"radio"});
984 RunCommand(
985 "RADIO LOG",
986 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
987 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
988}
989
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800990static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800991 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800992 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
993 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800994 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100995 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800996 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
997 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800998 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800999 RunCommand(
1000 "EVENT LOG",
1001 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001002 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001003 timeout_ms = logcat_timeout({"stats"});
1004 RunCommand(
1005 "STATS LOG",
1006 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001007 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001008 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001009
1010 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1011
1012 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001013 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1014 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001015}
1016
Mike Ma5c267872019-08-21 11:31:34 -07001017static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001018 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1019 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1020 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1021 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1022 if (fd < 0) {
1023 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1024 return;
1025 }
1026 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1027 bool empty = 0 == lseek(fd, 0, SEEK_END);
1028 if (!empty) {
1029 // Use a different name from "incident.proto"
1030 // /proto/incident.proto is reserved for incident service dump
1031 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001032 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1033 path);
1034 } else {
1035 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001036 }
Mike Ma5c267872019-08-21 11:31:34 -07001037}
1038
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001039static void MaybeAddSystemTraceToZip() {
1040 // This function copies into the .zip the system trace that was snapshotted
1041 // by the early call to MaybeSnapshotSystemTrace(), if any background
1042 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001043 if (!ds.has_system_trace_) {
1044 // No background trace was happening at the time dumpstate was invoked.
1045 return;
1046 }
1047 ds.AddZipEntry(
1048 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1049 SYSTEM_TRACE_SNAPSHOT);
1050 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1051}
1052
Sunny Goyal35949782019-11-19 15:54:36 -08001053static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001054 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1055 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1056 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1057 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1058 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1059 if (fd < 0) {
1060 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1061 return;
1062 }
1063 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1064 CommandOptions::WithTimeout(120).Build());
1065 bool empty = 0 == lseek(fd, 0, SEEK_END);
1066 if (!empty) {
1067 ds.AddZipEntry("visible_windows.zip", path);
1068 } else {
1069 MYLOGW("Failed to dump visible windows\n");
1070 }
1071 unlink(path.c_str());
1072}
1073
Jayachandran Ca94c7172017-06-10 15:08:12 -07001074static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001075 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1076 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001077 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001078 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001079 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1080 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1081 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1082 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001083}
1084
David Andersond9ba4752018-12-11 18:26:59 -08001085static void DumpDynamicPartitionInfo() {
1086 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1087 return;
1088 }
1089
1090 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001091 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001092}
1093
Chris Morin5a50d482022-02-01 17:41:18 -08001094static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001095 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1096 anr_traces_dir.c_str());
1097
1098 // If we're here, dump_traces_path will always be a temporary file
1099 // (created with mkostemp or similar) that contains dumps taken earlier
1100 // on in the process.
1101 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001102 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1103 dump_traces_path);
1104 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001105
1106 const int ret = unlink(dump_traces_path);
1107 if (ret == -1) {
1108 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1109 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001110 }
1111 }
1112
Narayan Kamathbd863722017-06-01 18:50:12 +01001113 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001114 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001115 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001116 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001117 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001118
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001119 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001120 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001121 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001122 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001123 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1124 }
1125}
1126
1127static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001128 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001129
Chris Morin5a50d482022-02-01 17:41:18 -08001130 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001131
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001132 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1133
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001134 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001135 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001136 int i = 0;
1137 while (true) {
1138 const std::string slow_trace_path =
1139 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1140 if (stat(slow_trace_path.c_str(), &st)) {
1141 // No traces file at this index, done with the files.
1142 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001143 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001144 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1145 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001146 }
1147}
1148
Wei Wang509bb5d2017-06-09 14:42:12 -07001149static void DumpBlockStatFiles() {
1150 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001151
Wei Wang1dc1ef52017-06-12 11:28:37 -07001152 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1153
1154 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001155 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1156 return;
1157 }
1158
1159 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001160 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001161 if ((d->d_name[0] == '.')
1162 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1163 || (d->d_name[1] == '\0'))) {
1164 continue;
1165 }
1166 const std::string new_path =
1167 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1168 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1169 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1170 printf("\n");
1171 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001172 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001173}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001174
1175static void DumpPacketStats() {
1176 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001177}
1178
1179static void DumpIpAddrAndRules() {
1180 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1181 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1182 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1183 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1184 RunCommand("IP RULES", {"ip", "rule", "show"});
1185 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1186}
1187
Nandana Dutt5c390032019-03-12 10:52:56 +00001188static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1189 std::chrono::milliseconds timeout,
1190 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001191 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001192 sp<android::IServiceManager> sm = defaultServiceManager();
1193 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001194 Vector<String16> args;
1195 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001196 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1197 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001198 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001199 std::string path(title);
1200 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001201 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001202 if (PropertiesHelper::IsDryRun()) {
1203 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1204 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1205 } else {
1206 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1207 if (status == OK) {
1208 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1209 std::chrono::duration<double> elapsed_seconds;
1210 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1211 service == String16("meminfo")) {
1212 // Use a longer timeout for meminfo, since 30s is not always enough.
1213 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1214 /* as_proto = */ false, elapsed_seconds,
1215 bytes_written);
1216 } else {
1217 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1218 /* as_proto = */ false, elapsed_seconds,
1219 bytes_written);
1220 }
1221 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1222 bool dump_complete = (status == OK);
1223 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001224 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001225 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001226
1227 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1228 std::chrono::steady_clock::now() - start);
1229 if (elapsed_duration > timeout) {
1230 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1231 elapsed_duration.count());
1232 break;
1233 }
1234 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001235 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001236}
1237
Vishnu Nair64afc022018-02-01 15:29:34 -08001238static void RunDumpsysText(const std::string& title, int priority,
1239 std::chrono::milliseconds timeout,
1240 std::chrono::milliseconds service_timeout) {
1241 DurationReporter duration_reporter(title);
1242 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1243 fsync(STDOUT_FILENO);
1244 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1245}
1246
1247/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001248static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1249 std::chrono::milliseconds timeout,
1250 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001251 DurationReporter duration_reporter(title);
1252 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1253 fsync(STDOUT_FILENO);
1254 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1255 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001256
1257 RETURN_IF_USER_DENIED_CONSENT();
1258
1259 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1260 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001261}
1262
Nandana Dutt5c390032019-03-12 10:52:56 +00001263static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1264 std::chrono::milliseconds timeout,
1265 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 sp<android::IServiceManager> sm = defaultServiceManager();
1267 Dumpsys dumpsys(sm.get());
1268 Vector<String16> args;
1269 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1270 DurationReporter duration_reporter(title);
1271
1272 auto start = std::chrono::steady_clock::now();
1273 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1274 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001275 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001276 std::string path(kProtoPath);
1277 path.append(String8(service).c_str());
1278 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1279 path.append("_CRITICAL");
1280 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1281 path.append("_HIGH");
1282 }
1283 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001284 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001285 if (status == OK) {
1286 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1287 bool dumpTerminated = (status == OK);
1288 dumpsys.stopDumpThread(dumpTerminated);
1289 }
1290 ZipWriter::FileEntry file_entry;
1291 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001292
1293 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1294 std::chrono::steady_clock::now() - start);
1295 if (elapsed_duration > timeout) {
1296 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1297 elapsed_duration.count());
1298 break;
1299 }
1300 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001301 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001302}
1303
Nandana Dutta7db6342018-11-21 14:53:34 +00001304// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001305static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001306 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1307 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001308
1309 RETURN_IF_USER_DENIED_CONSENT();
1310
1311 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1312 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001313}
1314
1315// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001316static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001317 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1318 // high priority. Reduce timeout once they are able to dump in a shorter time or
1319 // moved to a parallel task.
1320 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1321 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001322
1323 RETURN_IF_USER_DENIED_CONSENT();
1324
1325 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1326 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001327}
1328
1329// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001330static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001331 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001332
1333 RETURN_IF_USER_DENIED_CONSENT();
1334
1335 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1336 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001337}
1338
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001339/*
1340 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1341 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1342 * if it's not running in the parallel task.
1343 */
1344static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001345 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001346 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1347 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001348
Steven Moreland44cd9482018-01-04 16:24:13 -08001349 using android::hidl::manager::V1_0::IServiceManager;
1350 using android::hardware::defaultServiceManager;
1351
1352 sp<IServiceManager> sm = defaultServiceManager();
1353 if (sm == nullptr) {
1354 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1355 return;
1356 }
1357
1358 auto ret = sm->list([&](const auto& interfaces) {
1359 for (const std::string& interface : interfaces) {
1360 std::string cleanName = interface;
1361 std::replace_if(cleanName.begin(),
1362 cleanName.end(),
1363 [](char c) {
1364 return !isalnum(c) &&
1365 std::string("@-_:.").find(c) == std::string::npos;
1366 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001367 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001368
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001369 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001370 {
1371 auto fd = android::base::unique_fd(
1372 TEMP_FAILURE_RETRY(open(path.c_str(),
1373 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1374 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1375 if (fd < 0) {
1376 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1377 continue;
1378 }
1379 RunCommandToFd(fd,
1380 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001381 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001382 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1383
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001384 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001385 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001386 if (!empty) {
1387 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1388 path);
1389 } else {
1390 unlink(path.c_str());
1391 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001392 }
1393 });
1394
1395 if (!ret.isOk()) {
1396 MYLOGE("Could not list hals from hwservicemanager.\n");
1397 }
1398}
1399
Devin Moore8df81bb2022-06-08 22:47:02 +00001400// Dump all of the files that make up the vendor interface.
1401// See the files listed in dumpFileList() for the latest list of files.
1402static void DumpVintf() {
1403 const auto vintfFiles = android::vintf::details::dumpFileList();
1404 for (const auto vintfFile : vintfFiles) {
1405 struct stat st;
1406 if (stat(vintfFile.c_str(), &st) == 0) {
1407 if (S_ISDIR(st.st_mode)) {
1408 ds.AddDir(vintfFile, true /* recursive */);
1409 } else {
1410 ds.EnqueueAddZipEntryAndCleanupIfNeeded(ZIP_ROOT_DIR + vintfFile,
1411 vintfFile);
1412 }
1413 }
1414 }
1415}
1416
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001417static void DumpExternalFragmentationInfo() {
1418 struct stat st;
1419 if (stat("/proc/buddyinfo", &st) != 0) {
1420 MYLOGE("Unable to dump external fragmentation info\n");
1421 return;
1422 }
1423
1424 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1425 std::ifstream ifs("/proc/buddyinfo");
1426 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1427 for (std::string line; std::getline(ifs, line);) {
1428 std::smatch match_results;
1429 if (std::regex_match(line, match_results, unusable_index_regex)) {
1430 std::stringstream free_pages(std::string{match_results[3]});
1431 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1432 std::istream_iterator<int>());
1433
1434 int total_free_pages = 0;
1435 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1436 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1437 }
1438
1439 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1440 match_results[2].str().c_str());
1441
1442 int usable_free_pages = total_free_pages;
1443 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1444 auto unusable_index = (total_free_pages - usable_free_pages) /
1445 static_cast<double>(total_free_pages);
1446 printf(" %5.3f", unusable_index);
1447 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1448 }
1449
1450 printf("\n");
1451 }
1452 }
1453 printf("\n");
1454}
1455
mhasankd451a472020-05-26 18:02:39 -07001456static void DumpstateLimitedOnly() {
1457 // Trimmed-down version of dumpstate to only include a whitelisted
1458 // set of logs (system log, event log, and system server / system app
1459 // crashes, and networking logs). See b/136273873 and b/138459828
1460 // for context.
1461 DurationReporter duration_reporter("DUMPSTATE");
1462 unsigned long timeout_ms;
1463 // calculate timeout
1464 timeout_ms = logcat_timeout({"main", "system", "crash"});
1465 RunCommand("SYSTEM LOG",
1466 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1467 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1468 timeout_ms = logcat_timeout({"events"});
1469 RunCommand(
1470 "EVENT LOG",
1471 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1472 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1473
1474 printf("========================================================\n");
1475 printf("== Networking Service\n");
1476 printf("========================================================\n");
1477
1478 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1479 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001480 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1481 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001482
1483 printf("========================================================\n");
1484 printf("== Dropbox crashes\n");
1485 printf("========================================================\n");
1486
1487 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1488 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1489
1490 printf("========================================================\n");
1491 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1492 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1493 printf("========================================================\n");
1494 printf("== dumpstate: done (id %d)\n", ds.id_);
1495 printf("========================================================\n");
1496}
1497
Rhed Jaoe017f982020-07-21 17:58:41 +08001498/*
1499 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1500 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1501 * if it's not running in the parallel task.
1502 */
1503static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1504 dprintf(out_fd, "========================================================\n");
1505 dprintf(out_fd, "== Checkins\n");
1506 dprintf(out_fd, "========================================================\n");
1507
1508 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1509 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1510 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1511 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1512 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1513 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1514}
1515
1516/*
1517 * Runs dumpsys on activity service to dump all application activities, services
1518 * and providers in the device.
1519 *
1520 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1521 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1522 * if it's not running in the parallel task.
1523 */
1524static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1525 dprintf(out_fd, "========================================================\n");
1526 dprintf(out_fd, "== Running Application Activities\n");
1527 dprintf(out_fd, "========================================================\n");
1528
1529 // The following dumpsys internally collects output from running apps, so it can take a long
1530 // time. So let's extend the timeout.
1531
1532 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1533
1534 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1535
1536 dprintf(out_fd, "========================================================\n");
1537 dprintf(out_fd, "== Running Application Services (platform)\n");
1538 dprintf(out_fd, "========================================================\n");
1539
1540 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1541 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1542
1543 dprintf(out_fd, "========================================================\n");
1544 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1545 dprintf(out_fd, "========================================================\n");
1546
1547 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1548 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1549
1550 dprintf(out_fd, "========================================================\n");
1551 dprintf(out_fd, "== Running Application Providers (platform)\n");
1552 dprintf(out_fd, "========================================================\n");
1553
1554 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001555 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001556
1557 dprintf(out_fd, "========================================================\n");
1558 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1559 dprintf(out_fd, "========================================================\n");
1560
1561 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1562 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1563}
1564
Nandana Dutt5c390032019-03-12 10:52:56 +00001565// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1566// via the consent they are shown. Ignores other errors that occur while running various
1567// commands. The consent checking is currently done around long running tasks, which happen to
1568// be distributed fairly evenly throughout the function.
1569static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001570 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001571
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001572 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Chris Morinbc223142022-02-04 14:17:11 -08001573 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001574 if (ds.dump_pool_) {
1575 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1576 // drop root user. Restarts it with two threads for the parallel run.
1577 ds.dump_pool_->start(/* thread_counts = */2);
1578
Chris Morinbc223142022-02-04 14:17:11 -08001579 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1580 dump_incident_report = ds.dump_pool_->enqueueTask(
1581 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1582 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1583 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1584 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001585 }
1586
Nandana Dutt5c390032019-03-12 10:52:56 +00001587 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1588 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1589 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001590 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001591 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001592 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001593 DumpFile("MEMORY INFO", "/proc/meminfo");
1594 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001595 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001596
1597 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1598
Sunny Goyal35949782019-11-19 15:54:36 -08001599 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1600
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001601 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1602 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1603 DumpFile("SLAB INFO", "/proc/slabinfo");
1604 DumpFile("ZONEINFO", "/proc/zoneinfo");
1605 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1606 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001607 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001608
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001609 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001610
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001611 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001612 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001613
1614 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1615 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001616
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001617 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001618 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001619 } else {
1620 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1621 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001622
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001623 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001624 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001625 struct stat s;
1626 if (stat("/proc/modules", &s) != 0) {
1627 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1628 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001629 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001630 RunCommand("MODULES INFO",
1631 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1632 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1633 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001634 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001635
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001636 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001637 DoKernelLogcat();
1638 } else {
1639 do_dmesg();
1640 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001641
Devin Moore8df81bb2022-06-08 22:47:02 +00001642 DumpVintf();
1643
Felipe Lemef0292972016-11-22 13:57:05 -08001644 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001645
1646 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1647
Jeff Brown1dc94e32014-09-11 14:15:27 -07001648 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001649 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001650
Jack Yu5a6b2e22020-08-14 18:13:35 +08001651 /* Dump Nfc NCI logs */
1652 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001653
Paul Chang0d2aad72020-02-13 20:04:03 +08001654 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001655 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001656 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001657 }
1658
Felipe Lemee184f662016-10-27 10:04:47 -07001659 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001660
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001661 MaybeAddSystemTraceToZip();
1662
Narayan Kamath8f788292017-05-25 13:20:39 +01001663 // NOTE: tombstones are always added as separate entries in the zip archive
1664 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001665 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001666 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001667 if (!tombstones_dumped) {
1668 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001669 }
1670
Jayachandran Ca94c7172017-06-10 15:08:12 -07001671 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001672
Lorenzo Colitti807f2dd2022-05-27 12:48:37 +09001673 RunDumpsys("EBPF MAP STATS", {"connectivity", "trafficcontroller"});
Chenbo Feng276a3b62018-08-07 11:44:49 -07001674
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001675 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001676
Jayachandran Ca94c7172017-06-10 15:08:12 -07001677 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001678
1679 dump_route_tables();
1680
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001681 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1682 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1683 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001684
Nandana Dutt5c390032019-03-12 10:52:56 +00001685 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001686
Chiachang Wang668ede42021-05-17 17:14:20 +08001687 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1688 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1689 // dump with priority parameters to dump high priority information.
1690 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1691 CommandOptions::WithTimeout(10).Build());
1692
Elliott Hughes23ccc622017-02-28 10:14:22 -08001693 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001694
Jin Qianf334d662017-10-10 14:41:37 -07001695 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001696
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001697 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001698
Colin Crossf45fa6b2012-03-26 12:38:26 -07001699 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001700 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1701 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1702
1703 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1704 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1705 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1706 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1707 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001708
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001709 /* Add window and surface trace files. */
1710 if (!PropertiesHelper::IsUserBuild()) {
1711 ds.AddDir(WMTRACE_DATA_DIR, false);
1712 }
1713
Yifan Hongd90cc652020-02-08 16:52:02 -08001714 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1715
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001716 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001717 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001718 } else {
1719 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1720 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001721
Steven Moreland7440ddb2016-12-15 16:13:39 -08001722 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001723 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1724 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001725 // su does not exist on user builds, so try running without it.
1726 // This way any implementations of vril-dump that do not require
1727 // root can run on user builds.
1728 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001729 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001730 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001731 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001732 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001733 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001734 }
1735
Felipe Lemed8b94e52016-12-08 10:21:44 -08001736 printf("========================================================\n");
1737 printf("== Android Framework Services\n");
1738 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001739
Nandana Dutt5c390032019-03-12 10:52:56 +00001740 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741
Jack He91ff2fe2021-02-18 18:23:43 -08001742 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1743 ds.AddDir("/data/misc/bluetooth/logs", true);
1744
Rhed Jaoe017f982020-07-21 17:58:41 +08001745 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001746 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001747 } else {
1748 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1749 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001750
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001751 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001752
Adrian Roos8b397ab2017-04-04 16:35:44 -07001753 printf("========================================================\n");
1754 printf("== Dropbox crashes\n");
1755 printf("========================================================\n");
1756
1757 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1758 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1759
Felipe Lemed8b94e52016-12-08 10:21:44 -08001760 printf("========================================================\n");
1761 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1762 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1763 printf("========================================================\n");
1764 printf("== dumpstate: done (id %d)\n", ds.id_);
1765 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001766
1767 printf("========================================================\n");
1768 printf("== Obtaining statsd metadata\n");
1769 printf("========================================================\n");
1770 // This differs from the usual dumpsys stats, which is the stats report data.
1771 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001772
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001773 // Add linker configuration directory
1774 ds.AddDir(LINKERCONFIG_DIR, true);
1775
Li Li830179f2022-01-04 12:53:29 -08001776 /* Dump frozen cgroupfs */
1777 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001778
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001779 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001780 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001781 } else {
1782 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1783 DumpIncidentReport);
1784 }
Mike Ma5c267872019-08-21 11:31:34 -07001785
Nandana Dutt5c390032019-03-12 10:52:56 +00001786 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787}
1788
Nandana Dutt5c390032019-03-12 10:52:56 +00001789/*
1790 * Dumps state for the default case; drops root after it's no longer necessary.
1791 *
1792 * Returns RunStatus::OK if everything went fine.
1793 * Returns RunStatus::ERROR if there was an error.
1794 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1795 * with the caller.
1796 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001797Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001798 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1799 // buffer.
1800 DoLogcat();
1801 // Capture timestamp after first logcat to use in next logcat
1802 time_t logcat_ts = time(nullptr);
1803
Nandana Dutt4be45d12018-09-26 15:04:23 +01001804 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001805 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001806 if (dump_pool_) {
1807 RETURN_IF_USER_DENIED_CONSENT();
1808 // One thread is enough since we only need to enqueue DumpTraces here.
1809 dump_pool_->start(/* thread_counts = */1);
1810
1811 // DumpTraces takes long time, post it to the another thread in the
1812 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001813 dump_traces = dump_pool_->enqueueTask(
1814 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001815 } else {
1816 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1817 &dump_traces_path);
1818 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001819
1820 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001821 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001822 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1823 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001824 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001825
1826 ds.AddDir(RECOVERY_DIR, true);
1827 ds.AddDir(RECOVERY_DATA_DIR, true);
1828 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1829 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1830 if (!PropertiesHelper::IsUserBuild()) {
1831 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1832 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001833 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001834 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001835 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001836 add_mountinfo();
1837 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001838 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001839 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001840
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001841 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001842 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1843
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001844 // Dump IPsec stats. No keys are exposed here.
1845 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1846
Nandana Dutt4be45d12018-09-26 15:04:23 +01001847 // Run ss as root so we can see socket marks.
1848 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1849
1850 // Run iotop as root to show top 100 IO threads
1851 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1852
Erick Reyese68df822019-02-11 14:46:36 -08001853 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001854 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1855 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001856
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001857 DumpFile("PSI cpu", "/proc/pressure/cpu");
1858 DumpFile("PSI memory", "/proc/pressure/memory");
1859 DumpFile("PSI io", "/proc/pressure/io");
1860
Rhed Jao5377d792020-07-16 17:37:39 +08001861 if (dump_pool_) {
1862 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001863 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001864
Chris Morinbc223142022-02-04 14:17:11 -08001865 // Current running thread in the pool is the root user also. Delete
1866 // the pool and make a new one later to ensure none of threads in the pool are root.
1867 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001868 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001869 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001870 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001871 }
1872
Nandana Dutt5c390032019-03-12 10:52:56 +00001873 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001874 Dumpstate::RunStatus status = dumpstate();
1875 // Capture logcat since the last time we did it.
1876 DoSystemLogcat(logcat_ts);
1877 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001878}
1879
Rhed Jaob5685b32020-08-14 17:19:17 +08001880// Common states for telephony and wifi which are needed to be collected before
1881// dumpstate drop the root user.
1882static void DumpstateRadioAsRoot() {
1883 DumpIpTablesAsRoot();
1884 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1885}
1886
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001887// This method collects common dumpsys for telephony and wifi. Typically, wifi
1888// reports are fine to include all information, but telephony reports on user
1889// builds need to strip some content (see DumpstateTelephonyOnly).
1890static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001891 // We need to be picky about some stuff for telephony reports on user builds.
1892 if (!include_sensitive_info) {
1893 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1894 DoRadioLogcat();
1895 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001896 // DumpHals takes long time, post it to the another thread in the pool,
1897 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001898 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001899 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001900 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001901 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001902 // Contains various system properties and process startup info.
1903 do_dmesg();
1904 // Logs other than the radio buffer may contain package/component names and potential PII.
1905 DoLogcat();
1906 // Too broad for connectivity problems.
1907 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001908 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1909 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001910 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08001911 } else {
1912 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1913 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001914 }
1915
Jayachandran Ca94c7172017-06-10 15:08:12 -07001916 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001917 DumpIpAddrAndRules();
1918 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001919 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1920 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001921}
1922
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001923// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1924// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1925// for what can be included on user builds: all reported information MUST directly relate to
1926// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1927// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1928// names are not), and MUST NOT contain logs of user application traffic.
1929// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001930static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001931 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001932
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001933 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001934
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001935 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001936
Rhed Jaob5685b32020-08-14 17:19:17 +08001937 DumpstateRadioAsRoot();
1938 if (!DropRootUser()) {
1939 return;
1940 }
1941
1942 // Starts thread pool after the root user is dropped, and two additional threads
1943 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08001944 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08001945 if (ds.dump_pool_) {
1946 ds.dump_pool_->start(/*thread_counts =*/2);
1947
1948 // DumpstateBoard takes long time, post it to the another thread in the pool,
1949 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001950 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1951 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001952 }
1953
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001954 DumpstateRadioCommon(include_sensitive_info);
1955
1956 if (include_sensitive_info) {
1957 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1958 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1959 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1960 // way.
1961 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1962 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001963
1964 printf("========================================================\n");
1965 printf("== Android Framework Services\n");
1966 printf("========================================================\n");
1967
Vishnu Nair652cc802017-11-30 15:18:30 -08001968 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1969 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001970 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1971 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001972 if (include_sensitive_info) {
1973 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1974 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1975 SEC_TO_MSEC(10));
1976 } else {
1977 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1978 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1979 // give a higher timeout as well.
1980 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1981 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1982 }
1983 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001984 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1985 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001986 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001987 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1988 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001989 if (include_sensitive_info) {
1990 // Contains raw IP addresses, omit from reports on user builds.
1991 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1992 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1993 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1994 SEC_TO_MSEC(10));
1995 // Contains package/component names, omit from reports on user builds.
1996 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1997 SEC_TO_MSEC(10));
1998 // Contains package names, but should be relatively simple to remove them (also contains
1999 // UIDs already), omit from reports on user builds.
2000 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2001 SEC_TO_MSEC(10));
2002 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002003
2004 printf("========================================================\n");
2005 printf("== Running Application Services\n");
2006 printf("========================================================\n");
2007
2008 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2009
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002010 if (include_sensitive_info) {
2011 printf("========================================================\n");
2012 printf("== Running Application Services (non-platform)\n");
2013 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002014
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002015 // Contains package/component names and potential PII, omit from reports on user builds.
2016 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2017 // carrier_config dumpsys instead.
2018 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2019 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002020
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002021 printf("========================================================\n");
2022 printf("== Checkins\n");
2023 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002024
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002025 // Contains package/component names, omit from reports on user builds.
2026 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2027 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002028
2029 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002030 printf("== dumpstate: done (id %d)\n", ds.id_);
2031 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002032
2033 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002034 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002035 } else {
2036 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2037 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002038}
2039
mukesh agrawal253dad42018-01-23 21:59:59 -08002040// This method collects dumpsys for wifi debugging only
2041static void DumpstateWifiOnly() {
2042 DurationReporter duration_reporter("DUMPSTATE");
2043
Rhed Jaob5685b32020-08-14 17:19:17 +08002044 DumpstateRadioAsRoot();
2045 if (!DropRootUser()) {
2046 return;
2047 }
2048
2049 // Starts thread pool after the root user is dropped. Only one additional
2050 // thread is needed for DumpHals in the DumpstateRadioCommon.
2051 if (ds.dump_pool_) {
2052 ds.dump_pool_->start(/*thread_counts =*/1);
2053 }
2054
mukesh agrawal253dad42018-01-23 21:59:59 -08002055 DumpstateRadioCommon();
2056
2057 printf("========================================================\n");
2058 printf("== Android Framework Services\n");
2059 printf("========================================================\n");
2060
2061 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2062 SEC_TO_MSEC(10));
2063 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2064 SEC_TO_MSEC(10));
2065
2066 printf("========================================================\n");
2067 printf("== dumpstate: done (id %d)\n", ds.id_);
2068 printf("========================================================\n");
2069}
2070
Nandana Duttcf419a72019-03-14 10:40:17 +00002071Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002072 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002073 const size_t buf_size = temp_file_pattern.length() + 1;
2074 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2075 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2076
2077 // Create a new, empty file to receive all trace dumps.
2078 //
2079 // TODO: This can be simplified once we remove support for the old style
2080 // dumps. We can have a file descriptor passed in to dump_traces instead
2081 // of creating a file, closing it and then reopening it again.
2082 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2083 if (fd < 0) {
2084 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002085 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002086 }
2087
2088 // Nobody should have access to this temporary file except dumpstate, but we
2089 // temporarily grant 'read' to 'others' here because this file is created
2090 // when tombstoned is still running as root, but dumped after dropping. This
2091 // can go away once support for old style dumping has.
2092 const int chmod_ret = fchmod(fd, 0666);
2093 if (chmod_ret < 0) {
2094 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002095 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002096 }
2097
2098 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2099 if (proc.get() == nullptr) {
2100 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002101 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002102 }
2103
2104 // Number of times process dumping has timed out. If we encounter too many
2105 // failures, we'll give up.
2106 int timeout_failures = 0;
2107 bool dalvik_found = false;
2108
Jayant Chowdharya0a8eb22022-05-20 03:30:09 +00002109 const std::set<int> hal_pids = get_interesting_pids();
Nandana Duttfaafd522019-03-11 09:23:09 +00002110
2111 struct dirent* d;
2112 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002113 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002114 int pid = atoi(d->d_name);
2115 if (pid <= 0) {
2116 continue;
2117 }
2118
2119 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2120 std::string exe;
2121 if (!android::base::Readlink(link_name, &exe)) {
2122 continue;
2123 }
2124
2125 bool is_java_process;
2126 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2127 // Don't bother dumping backtraces for the zygote.
2128 if (IsZygote(pid)) {
2129 continue;
2130 }
2131
2132 dalvik_found = true;
2133 is_java_process = true;
2134 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2135 is_java_process = false;
2136 } else {
2137 // Probably a native process we don't care about, continue.
2138 continue;
2139 }
2140
2141 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2142 if (timeout_failures == 3) {
2143 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2144 break;
2145 }
2146
2147 const uint64_t start = Nanotime();
2148 const int ret = dump_backtrace_to_file_timeout(
2149 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2150 is_java_process ? 5 : 20, fd);
2151
2152 if (ret == -1) {
2153 // For consistency, the header and footer to this message match those
2154 // dumped by debuggerd in the success case.
2155 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2156 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2157 dprintf(fd, "---- end %d ----", pid);
2158 timeout_failures++;
2159 continue;
2160 }
2161
2162 // We've successfully dumped stack traces, reset the failure count
2163 // and write a summary of the elapsed time to the file and continue with the
2164 // next process.
2165 timeout_failures = 0;
2166
2167 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2168 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2169 }
2170
2171 if (!dalvik_found) {
2172 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2173 }
2174
Nandana Duttcf419a72019-03-14 10:40:17 +00002175 *path = file_name_buf.release();
2176 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002177}
2178
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002179static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2180 const Dumpstate::BugreportMode bugreport_mode) {
2181 switch (bugreport_mode) {
2182 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2183 return dumpstate_hal_hidl::DumpstateMode::FULL;
2184 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2185 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2186 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2187 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2188 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2189 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2190 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2191 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2192 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2193 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2194 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2195 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2196 }
2197 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2198}
2199
2200static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2201 const Dumpstate::BugreportMode bugreport_mode) {
2202 switch (bugreport_mode) {
2203 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2204 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2205 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2206 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2207 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2208 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2209 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2210 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2211 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2212 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2213 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2214 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2215 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2216 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2217 }
2218 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2219}
2220
2221static void DoDumpstateBoardHidl(
2222 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2223 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2224 const Dumpstate::BugreportMode bugreport_mode,
2225 const size_t timeout_sec) {
2226
2227 using ScopedNativeHandle =
2228 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2229 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2230 [](native_handle_t* handle) {
2231 // we don't close file handle's here
2232 // via native_handle_close(handle)
2233 // instead we let dumpstate_fds close the file handles when
2234 // dumpstate_fds gets destroyed
2235 native_handle_delete(handle);
2236 });
2237 if (handle == nullptr) {
2238 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2239 return;
2240 }
2241
2242 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2243 handle.get()->data[i] = dumpstate_fds[i].get();
2244 }
2245
2246 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2247 // implement just 1.0.
2248 const char* descriptor_to_kill;
2249 using DumpstateBoardTask = std::packaged_task<bool()>;
2250 DumpstateBoardTask dumpstate_board_task;
2251 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2252 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2253 if (dumpstate_hal != nullptr) {
2254 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2255
2256 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2257 GetDumpstateHalModeHidl(bugreport_mode);
2258
2259 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2260 dumpstate_board_task =
2261 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2262 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2263 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2264 SEC_TO_MSEC(timeout_sec));
2265 if (!status.isOk()) {
2266 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2267 return false;
2268 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2269 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2270 dumpstate_hal_hidl::toString(status).c_str());
2271 return false;
2272 }
2273 return true;
2274 });
2275 } else {
2276 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2277
2278 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2279 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2280 ::android::hardware::Return<void> status =
2281 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2282 if (!status.isOk()) {
2283 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2284 return false;
2285 }
2286 return true;
2287 });
2288 }
2289 auto result = dumpstate_board_task.get_future();
2290 std::thread(std::move(dumpstate_board_task)).detach();
2291
2292 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2293 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2294 if (!android::base::SetProperty(
2295 "ctl.interface_restart",
2296 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2297 MYLOGE("Couldn't restart dumpstate HAL\n");
2298 }
2299 }
2300 // Wait some time for init to kill dumpstate vendor HAL
2301 constexpr size_t killing_timeout_sec = 10;
2302 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2303 MYLOGE(
2304 "killing dumpstateBoard timed out after %zus, continue and "
2305 "there might be racing in content\n",
2306 killing_timeout_sec);
2307 }
2308}
2309
2310static void DoDumpstateBoardAidl(
2311 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2312 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2313 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2314 MYLOGI("Using IDumpstateDevice AIDL HAL");
2315
2316 const char* descriptor_to_kill;
2317 using DumpstateBoardTask = std::packaged_task<bool()>;
2318 DumpstateBoardTask dumpstate_board_task;
2319 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2320 GetDumpstateHalModeAidl(bugreport_mode);
2321
2322 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2323 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2324 timeout_sec]() -> bool {
2325 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2326
2327 if (!status.isOk()) {
2328 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2329 return false;
2330 }
2331 return true;
2332 });
2333 auto result = dumpstate_board_task.get_future();
2334 std::thread(std::move(dumpstate_board_task)).detach();
2335
2336 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2337 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2338 if (!android::base::SetProperty(
2339 "ctl.interface_restart",
2340 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2341 MYLOGE("Couldn't restart dumpstate HAL\n");
2342 }
2343 }
2344 // Wait some time for init to kill dumpstate vendor HAL
2345 constexpr size_t killing_timeout_sec = 10;
2346 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2347 MYLOGE(
2348 "killing dumpstateBoard timed out after %zus, continue and "
2349 "there might be racing in content\n",
2350 killing_timeout_sec);
2351 }
2352}
2353
2354static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2355 const std::string aidl_instance_name =
2356 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2357
2358 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2359 return nullptr;
2360 }
2361
2362 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2363
2364 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2365}
2366
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002367void Dumpstate::DumpstateBoard(int out_fd) {
2368 dprintf(out_fd, "========================================================\n");
2369 dprintf(out_fd, "== Board\n");
2370 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002371
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002372 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002373 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002374 * set to true and unmount it after invoking dumpstateBoard_* methods.
2375 * This is to enable debug builds to not have debugfs mounted during runtime.
2376 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002377 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002378 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002379 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002380 if (mount_debugfs) {
2381 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2382 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002383 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002384 }
2385
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002386 std::vector<std::string> paths;
2387 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002388 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002389 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2390 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002391 remover.emplace_back(android::base::make_scope_guard(
2392 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002393 }
Jie Song9fbfad02017-06-20 16:29:42 -07002394
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002395 // get dumpstate HAL AIDL implementation
2396 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2397 GetDumpstateBoardAidlService());
2398 if (dumpstate_hal_handle_aidl == nullptr) {
2399 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2400 }
2401
2402 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2403 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2404 if (dumpstate_hal_handle_aidl == nullptr) {
2405 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2406 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2407 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2408 }
2409 }
2410
2411 // if neither HIDL nor AIDL implementation found, then return
2412 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2413 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002414 return;
2415 }
2416
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002417 // this is used to hold the file descriptors and when this variable goes out of scope
2418 // the file descriptors are closed
2419 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002420
Nandana Dutt5c390032019-03-12 10:52:56 +00002421 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002422 for (size_t i = 0; i < paths.size(); i++) {
2423 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2424
2425 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2426 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2427 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2428 if (fd < 0) {
2429 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2430 return;
2431 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002432
2433 dumpstate_fds.emplace_back(fd.release());
2434 // we call fd.release() here to make sure "fd" does not get closed
2435 // after "fd" goes out of scope after this block.
2436 // "fd" will be closed when "dumpstate_fds" goes out of scope
2437 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002438 }
2439
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002440 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2441 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2442 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002443 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002444
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002445 if (dumpstate_hal_handle_aidl != nullptr) {
2446 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2447 timeout_sec);
2448 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2449 // run HIDL HAL only if AIDL HAL not found
2450 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2451 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002452 }
2453
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002454 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002455 auto keep_debugfs_mounted =
2456 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2457 if (keep_debugfs_mounted.empty())
2458 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002459 }
2460
Wei Wang587eac92018-04-05 12:17:20 -07002461 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2462 for (size_t i = 0; i < paths.size(); i++) {
2463 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002464 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2465 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002466 file_sizes[i] = -1;
2467 continue;
2468 }
2469 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002470 }
2471
2472 for (size_t i = 0; i < paths.size(); i++) {
2473 if (file_sizes[i] == -1) {
2474 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002475 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002476 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002477 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002478 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002479 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002480 remover[i].Disable();
2481 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2482 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002483 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002484}
2485
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002486static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002487 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002488 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2489 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002490 " -h: display this help message\n"
2491 " -b: play sound file instead of vibrate, at beginning of job\n"
2492 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002493 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002494 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002495 " -s: write zipped file to control socket (for init)\n"
2496 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002497 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002498 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002499 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002500 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002501 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002502 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002503}
2504
Wei Liuf87959e2016-08-26 14:51:42 -07002505static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002506 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002507}
2508
Felipe Leme1d486fe2016-10-14 18:06:47 -07002509bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002510 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2511 if (zip_entry_tasks_) {
2512 zip_entry_tasks_->run(/* do_cancel = */false);
2513 }
2514
Felipe Leme9a523ae2016-10-20 15:10:33 -07002515 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002516 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002517 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002518 // Final timestamp
2519 char date[80];
2520 time_t the_real_now_please_stand_up = time(nullptr);
2521 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002522 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002523 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002524
Felipe Leme9a523ae2016-10-20 15:10:33 -07002525 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002526 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002527 return false;
2528 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002529 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002530 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002531 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002532 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002533
Felipe Leme0f3fb202016-06-10 17:10:53 -07002534 // Add log file (which contains stderr output) to zip...
2535 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002536 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002537 MYLOGE("Failed to add dumpstate log to .zip file\n");
2538 return false;
2539 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002540 // TODO: Should truncate the existing file.
2541 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002542 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2543 return false;
2544 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002545 fprintf(stderr, "\n");
2546
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002547 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002548 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002549 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002550 return false;
2551 }
2552
Felipe Leme1d486fe2016-10-14 18:06:47 -07002553 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2554 ds.zip_file.reset(nullptr);
2555
Felipe Lemee9d2c542016-11-15 11:48:26 -08002556 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002557 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002558
Felipe Leme1e9edc62015-12-21 16:02:13 -08002559 return true;
2560}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002561
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002562static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2563 // clang-format off
2564 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2565 "--receiver-foreground", "--receiver-include-background", "-a", action};
2566 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002567
2568 am.insert(am.end(), args.begin(), args.end());
2569
Felipe Leme8d2410e2017-02-08 09:46:08 -08002570 RunCommand("", am,
2571 CommandOptions::WithTimeout(20)
2572 .Log("Sending broadcast: '%s'\n")
2573 .Always()
2574 .DropRoot()
2575 .RedirectStderr()
2576 .Build());
2577}
2578
Felipe Leme35b8cf12017-02-10 15:47:29 -08002579static void Vibrate(int duration_ms) {
2580 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002581 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2582 "oneshot", std::to_string(duration_ms)};
2583 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002584 CommandOptions::WithTimeout(10)
2585 .Log("Vibrate: '%s'\n")
2586 .Always()
2587 .Build());
2588 // clang-format on
2589}
2590
Nandana Dutt979388e2018-11-30 16:48:55 +00002591static void MaybeResolveSymlink(std::string* path) {
2592 std::string resolved_path;
2593 if (android::base::Readlink(*path, &resolved_path)) {
2594 *path = resolved_path;
2595 }
2596}
2597
Nandana Dutt4be45d12018-09-26 15:04:23 +01002598/*
2599 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002600 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002601 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002602static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002603 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2604
Nandana Dutt4be45d12018-09-26 15:04:23 +01002605 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2606 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002607 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002608 char date[80];
2609 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2610 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002611
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002612 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002613 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002614 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002615 ds.base_name_ += "-wifi";
2616 }
2617
Paul Chang0d2aad72020-02-13 20:04:03 +08002618 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002619 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002620 }
2621 ds.tmp_path_ = ds.GetPath(".tmp");
2622 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2623
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002624 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002625 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002626 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002627 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002628 "Bugreport dir: [%s] "
2629 "Base name: [%s] "
2630 "Suffix: [%s] "
2631 "Log path: [%s] "
2632 "Temporary path: [%s] "
2633 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002634 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2635 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002636
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002637 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2638 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2639 create_parent_dirs(ds.path_.c_str());
2640 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2641 if (ds.zip_file == nullptr) {
2642 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2643 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002644 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002645 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2646 ds.AddTextZipEntry("version.txt", ds.version_);
2647 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002648}
2649
2650/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002651 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002652 * printing zipped file status, etc.
2653 */
2654static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002655 bool do_text_file = !ds.FinishZipFile();
2656 if (do_text_file) {
2657 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002658 }
mhasank2d75c442020-06-11 15:05:25 -07002659
2660 std::string final_path = ds.path_;
2661 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002662 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002663 android::os::CopyFileToFile(ds.path_, final_path);
2664 }
2665
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002666 if (ds.options_->stream_to_socket) {
2667 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2668 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002669 if (do_text_file) {
2670 dprintf(ds.control_socket_fd_,
2671 "FAIL:could not create zip file, check %s "
2672 "for more details\n",
2673 ds.log_path_.c_str());
2674 } else {
mhasank2d75c442020-06-11 15:05:25 -07002675 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002676 }
2677 }
2678}
2679
Nandana Dutt4be45d12018-09-26 15:04:23 +01002680
Nandana Dutt58d72e22018-11-16 10:30:48 +00002681static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2682 switch (mode) {
2683 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2684 return "BUGREPORT_FULL";
2685 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2686 return "BUGREPORT_INTERACTIVE";
2687 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2688 return "BUGREPORT_REMOTE";
2689 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2690 return "BUGREPORT_WEAR";
2691 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2692 return "BUGREPORT_TELEPHONY";
2693 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2694 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002695 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2696 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002697 }
2698}
2699
Paul Changf59c2b72020-03-10 02:08:55 +08002700static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2701 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002702 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2703 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002704 options->bugreport_mode = mode;
2705 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002706 switch (mode) {
2707 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002708 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002709 break;
2710 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002711 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002712 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002713 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002714 break;
2715 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002716 options->do_vibrate = false;
2717 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002718 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002719 break;
2720 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002721 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002722 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002723 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002724 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002725 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002726 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002727 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002728 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002729 break;
2730 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002731 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002732 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002733 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002734 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2735 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002736 }
2737}
2738
Nandana Dutt58d72e22018-11-16 10:30:48 +00002739static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002740 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002741 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002742 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002743 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002744 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002745 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002746 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002747 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002748 options.do_progress_updates, options.bugreport_fd.get(),
2749 options.bugreport_mode_string.c_str(),
2750 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002751}
2752
Nandana Dutt54dbd672019-01-11 12:58:05 +00002753void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2754 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002755 const android::base::unique_fd& screenshot_fd_in,
2756 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002757 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002758 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2759 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002760
Paul Changf59c2b72020-03-10 02:08:55 +08002761 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002762}
2763
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002764Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2765 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002766 int c;
mhasankd451a472020-05-26 18:02:39 -07002767 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002768 switch (c) {
2769 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002770 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002771 case 's': stream_to_socket = true; break;
2772 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002773 case 'v': show_header_only = true; break;
2774 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002775 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002776 case 'P': do_progress_updates = true; break;
2777 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002778 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002779 case 'V':
2780 case 'd':
2781 case 'z':
2782 // compatibility no-op
2783 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002784 case 'w':
2785 // This was already processed
2786 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002787 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002788 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002789 break;
2790 default:
2791 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002792 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002793 break;
2794 // clang-format on
2795 }
2796 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002797
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002798 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002799 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002800 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002801 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002802 }
2803 }
2804
2805 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2806 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002807
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002808 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002809}
2810
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002811bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002812 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002813 return false;
2814 }
2815
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002816 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002817 return false;
2818 }
2819
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002820 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002821 return false;
2822 }
2823 return true;
2824}
2825
Nandana Dutt197661d2018-11-16 16:40:21 +00002826void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2827 options_ = std::move(options);
2828}
2829
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002830void Dumpstate::Initialize() {
2831 /* gets the sequential id */
2832 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2833 id_ = ++last_id;
2834 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2835}
2836
Nandana Duttd2f5f082019-01-18 17:13:52 +00002837Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2838 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002839 if (listener_ != nullptr) {
2840 switch (status) {
2841 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002842 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002843 break;
2844 case Dumpstate::RunStatus::HELP:
2845 break;
2846 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002847 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002848 break;
2849 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002850 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2851 break;
2852 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2853 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2854 break;
2855 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2856 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002857 break;
2858 }
2859 }
2860 return status;
2861}
2862
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002863void Dumpstate::Cancel() {
2864 CleanupTmpFiles();
2865 android::os::UnlinkAndLogOnError(log_path_);
2866 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2867 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2868 kDumpstateBoardFiles[i]);
2869 }
2870 tombstone_data_.clear();
2871 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002872
2873 // Instead of shutdown the pool, we delete temporary files directly since
2874 // shutdown blocking the call.
2875 if (dump_pool_) {
2876 dump_pool_->deleteTempFiles();
2877 }
2878 if (zip_entry_tasks_) {
2879 zip_entry_tasks_->run(/*do_cancel =*/ true);
2880 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002881}
2882
Nandana Dutt979388e2018-11-30 16:48:55 +00002883/*
2884 * Dumps relevant information to a bugreport based on the given options.
2885 *
2886 * The bugreport can be dumped to a file or streamed to a socket.
2887 *
2888 * How dumping to file works:
2889 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2890 * stderr is redirected a log file.
2891 *
2892 * The temporary bugreport is then populated via printfs, dumping contents of files and
2893 * output of commands to stdout.
2894 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002895 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002896 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002897 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002898 *
mhasank2d75c442020-06-11 15:05:25 -07002899 * Bugreports are first generated in a local directory and later copied to the caller's fd
2900 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002901 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002902Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2903 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002904 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002905 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002906 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002907 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002908 return RunStatus::INVALID_INPUT;
2909 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002910 /* set as high priority, and protect from OOM killer */
2911 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002912
Felipe Lemed071c682016-10-20 16:48:00 -07002913 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002914 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002915 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002916 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002917 } else {
2918 /* fallback to kernels <= 2.6.35 */
2919 oom_adj = fopen("/proc/self/oom_adj", "we");
2920 if (oom_adj) {
2921 fputs("-17", oom_adj);
2922 fclose(oom_adj);
2923 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002924 }
2925
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002926 if (version_ == VERSION_DEFAULT) {
2927 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002928 }
2929
Chris Morin5a50d482022-02-01 17:41:18 -08002930 if (version_ != VERSION_CURRENT) {
2931 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
2932 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002934 }
2935
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 if (options_->show_header_only) {
2937 PrintHeader();
2938 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002939 }
2940
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002941 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2942 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002943
Felipe Leme7447d7c2016-11-03 18:12:22 -07002944 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002945 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002946 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002947 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002948
Sahana Raof35ed432019-07-12 10:47:52 +01002949 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2950 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2951 } else {
2952 // Wake lock will be released automatically on process death
2953 MYLOGD("Wake lock acquired.\n");
2954 }
2955
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002956 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002957
Felipe Lemef0292972016-11-22 13:57:05 -08002958 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002959 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2960 }
2961
Nandana Dutt235c6672019-11-14 15:22:32 +00002962 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002963 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002964
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002965 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002966
Christopher Ferrised9354f2014-10-01 17:35:01 -07002967 // If we are going to use a socket, do it as early as possible
2968 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002969 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002970 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002971 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002972 if (control_socket_fd_ == -1) {
2973 return ERROR;
2974 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002975 if (options_->progress_updates_to_socket) {
2976 options_->do_progress_updates = 1;
2977 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002978 }
2979
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002980 if (!PrepareToWriteToFile()) {
2981 return ERROR;
2982 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002983
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002984 // Interactive, wear & telephony modes are default to true.
2985 // and may enable from cli option or when using control socket
2986 if (options_->do_progress_updates) {
2987 // clang-format off
2988 std::vector<std::string> am_args = {
2989 "--receiver-permission", "android.permission.DUMP",
2990 };
2991 // clang-format on
2992 // Send STARTED broadcast for apps that listen to bugreport generation events
2993 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2994 if (options_->progress_updates_to_socket) {
2995 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002996 }
2997 }
2998
Nick Kralevichf3599b32016-01-25 15:05:16 -08002999 /* read /proc/cmdline before dropping root */
3000 FILE *cmdline = fopen("/proc/cmdline", "re");
3001 if (cmdline) {
3002 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3003 fclose(cmdline);
3004 }
3005
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003006 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003007 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003008 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003009
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003010 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003011 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3012 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003013 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003014 }
3015 }
3016
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003017 int dup_stdout_fd;
3018 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003019 // Redirect stderr to log_path_ for debugging.
3020 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3021 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3022 return ERROR;
3023 }
3024 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3025 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3026 strerror(errno));
3027 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003028
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003029 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3030 // moved into zip file later, if zipping.
3031 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3032 // TODO: why not write to a file instead of stdout to overcome this problem?
3033 /* TODO: rather than generating a text file now and zipping it later,
3034 it would be more efficient to redirect stdout to the zip entry
3035 directly, but the libziparchive doesn't support that option yet. */
3036 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3037 return ERROR;
3038 }
3039 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3040 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3041 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003042 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003043
3044 // Don't buffer stdout
3045 setvbuf(stdout, nullptr, _IONBF, 0);
3046
Rhed Jao5377d792020-07-16 17:37:39 +08003047 // Enable the parallel run if the client requests to output to a file.
3048 EnableParallelRunIfNeeded();
3049 // Using scope guard to make sure the dump pool can be shut down correctly.
3050 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3051 ShutdownDumpPool();
3052 });
3053
Felipe Leme608385d2016-02-01 10:35:38 -08003054 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3055 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003056 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003057 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003058
Gavin Corkery6968f552020-11-22 18:09:05 +00003059 bool is_dumpstate_restricted = options_->telephony_only
3060 || options_->wifi_only
3061 || options_->limited_only;
3062 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003063 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003064 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003065 }
3066 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003067
3068 if (!is_dumpstate_restricted) {
3069 // Snapshot the system trace now (if running) to avoid that dumpstate's
3070 // own activity pushes out interesting data from the trace ring buffer.
3071 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3072 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003073
3074 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3075 // from WMTRACE_DATA_DIR.
3076 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003077 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003078 onUiIntensiveBugreportDumpsFinished(calling_uid);
3079 MaybeCheckUserConsent(calling_uid, calling_package);
3080 if (options_->telephony_only) {
3081 DumpstateTelephonyOnly(calling_package);
3082 } else if (options_->wifi_only) {
3083 DumpstateWifiOnly();
3084 } else if (options_->limited_only) {
3085 DumpstateLimitedOnly();
3086 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003087 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003088 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003089 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003090 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003091 HandleUserConsentDenied();
3092 }
3093 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003094 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003095 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003096
Felipe Leme55b42a62015-11-10 17:39:08 -08003097 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003098 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003099
Abhijeet Kaure370d682019-10-01 16:49:30 +01003100 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003101 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003102
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003103 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003104 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01003105 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003106 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003107 if (status != Dumpstate::RunStatus::OK &&
3108 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3109 // Do an early return if there were errors. We make an exception for consent
3110 // timing out because it's possible the user got distracted. In this case the
3111 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003112 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003113 return status;
3114 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003115 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3116 MYLOGI(
3117 "Did not receive user consent yet."
3118 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003119 const String16 incidentcompanion("incidentcompanion");
3120 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3121 if (ics != nullptr) {
3122 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3123 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3124 consent_callback_.get());
3125 } else {
3126 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3127 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003128 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003129 }
3130
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003131 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003132 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003133 for (int i = 0; i < 3; i++) {
3134 Vibrate(75);
3135 usleep((75 + 50) * 1000);
3136 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003137 }
3138
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003139 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3140 progress_->GetInitialMax());
3141 progress_->Save();
3142 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003143
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003144 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003145
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003146 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003147 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003148 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003149 }
3150
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003151 tombstone_data_.clear();
3152 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003153
Nandana Duttd2f5f082019-01-18 17:13:52 +00003154 return (consent_callback_ != nullptr &&
3155 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3156 ? USER_CONSENT_TIMED_OUT
3157 : RunStatus::OK;
3158}
3159
Paul Chang0d2aad72020-02-13 20:04:03 +08003160void Dumpstate::MaybeTakeEarlyScreenshot() {
3161 if (!options_->do_screenshot || !do_early_screenshot_) {
3162 return;
3163 }
3164
3165 TakeScreenshot();
3166}
3167
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003168void Dumpstate::MaybeSnapshotSystemTrace() {
3169 // If a background system trace is happening and is marked as "suitable for
3170 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3171 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3172 // case that no trace is ongoing, this command is a no-op.
3173 // Note: this should not be enqueued as we need to freeze the trace before
3174 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3175 // the dumpstate's own activity which is irrelevant.
3176 int res = RunCommand(
3177 "SERIALIZE PERFETTO TRACE",
3178 {"perfetto", "--save-for-bugreport"},
3179 CommandOptions::WithTimeout(10)
3180 .DropRoot()
3181 .CloseAllFileDescriptorsOnExec()
3182 .Build());
3183 has_system_trace_ = res == 0;
3184 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3185 // file in the later stages.
3186}
3187
Yohei Yukawa95305b32021-03-09 07:54:27 -08003188void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003189 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3190 for (const auto& service : {"window", "input_method"}) {
3191 RunCommand(
3192 // Empty name because it's not intended to be classified as a bugreport section.
3193 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3194 "", {"cmd", service, "tracing", "save-for-bugreport"},
3195 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3196 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003197}
3198
Paul Changeb4b4642020-05-28 22:05:47 +08003199void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003200 if (calling_uid == AID_SHELL || !CalledByApi()) {
3201 return;
3202 }
3203 if (listener_ != nullptr) {
3204 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3205 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003206 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003207 }
3208}
3209
Jichao Lie89d9c12019-11-21 19:02:51 -08003210void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3211 if (calling_uid == AID_SHELL || !CalledByApi()) {
3212 // No need to get consent for shell triggered dumpstates, or not through
3213 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003214 return;
3215 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003216 consent_callback_ = new ConsentCallback();
3217 const String16 incidentcompanion("incidentcompanion");
3218 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003219 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003220 if (ics != nullptr) {
3221 MYLOGD("Checking user consent via incidentcompanion service\n");
3222 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003223 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003224 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003225 } else {
3226 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3227 }
3228}
3229
Nandana Dutt5c390032019-03-12 10:52:56 +00003230bool Dumpstate::IsUserConsentDenied() const {
3231 return ds.consent_callback_ != nullptr &&
3232 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3233}
3234
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003235bool Dumpstate::CalledByApi() const {
3236 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3237}
3238
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003239void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003240 android::os::UnlinkAndLogOnError(tmp_path_);
3241 android::os::UnlinkAndLogOnError(screenshot_path_);
3242 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003243 if (dump_traces_path != nullptr) {
3244 android::os::UnlinkAndLogOnError(dump_traces_path);
3245 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003246}
3247
Rhed Jao5377d792020-07-16 17:37:39 +08003248void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003249 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003250 return;
3251 }
3252 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003253 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003254}
3255
3256void Dumpstate::ShutdownDumpPool() {
3257 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003258 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003259 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003260 if (zip_entry_tasks_) {
3261 zip_entry_tasks_->run(/* do_cancel = */true);
3262 zip_entry_tasks_ = nullptr;
3263 }
3264}
3265
3266void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3267 const std::string& entry_path) {
3268 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3269 if (!task_cancelled) {
3270 AddZipEntry(entry_name, entry_path);
3271 }
3272 android::os::UnlinkAndLogOnError(entry_path);
3273 };
3274 if (zip_entry_tasks_) {
3275 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3276 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3277 } else {
3278 // Invokes AddZipEntryAndCleanup immediately
3279 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3280 }
Rhed Jao5377d792020-07-16 17:37:39 +08003281}
3282
Nandana Duttd2f5f082019-01-18 17:13:52 +00003283Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3284 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003285 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003286 return USER_CONSENT_DENIED;
3287}
3288
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003289Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003290 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003291 // user consent (unless the caller is Shell).
3292 UserConsentResult consent_result;
3293 if (calling_uid == AID_SHELL) {
3294 consent_result = UserConsentResult::APPROVED;
3295 } else {
3296 consent_result = consent_callback_->getResult();
3297 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003298 if (consent_result == UserConsentResult::UNAVAILABLE) {
3299 // User has not responded yet.
3300 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003301 // Telephony is a fast report type, particularly on user builds where information may be
3302 // more aggressively limited. To give the user time to read the consent dialog, increase the
3303 // timeout.
3304 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3305 : USER_CONSENT_TIMEOUT_MS;
3306 if (elapsed_ms < timeout_ms) {
3307 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003308 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3309 sleep(delay_seconds);
3310 }
3311 consent_result = consent_callback_->getResult();
3312 }
3313 if (consent_result == UserConsentResult::DENIED) {
3314 // User has explicitly denied sharing with the app. To be safe delete the
3315 // internal bugreport & tmp files.
3316 return HandleUserConsentDenied();
3317 }
3318 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003319 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3320 if (copy_succeeded) {
3321 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003322 if (options_->do_screenshot &&
3323 options_->screenshot_fd.get() != -1 &&
3324 !options_->is_screenshot_copied) {
3325 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3326 options_->screenshot_fd.get());
3327 options_->is_screenshot_copied = copy_succeeded;
3328 if (copy_succeeded) {
3329 android::os::UnlinkAndLogOnError(screenshot_path_);
3330 }
3331 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003332 }
3333 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3334 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3335 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3336 // Since we do not have user consent to share the bugreport it does not get
3337 // copied over to the calling app but remains in the internal directory from
3338 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003339 std::string final_path = GetPath(".zip");
3340 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3341 if (copy_succeeded) {
3342 android::os::UnlinkAndLogOnError(path_);
3343 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003344 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3345 }
3346 // Unknown result; must be a programming error.
3347 MYLOGE("Unknown user consent result:%d\n", consent_result);
3348 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003349}
3350
Nandana Duttf02564e2019-02-15 15:24:24 +00003351Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003352 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3353 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3354 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003355 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003356 // When directly running dumpstate binary, the output is not expected to be written
3357 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003358 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003359
3360 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003361 // an app; they are irrelevant here because bugreport is triggered via command line.
3362 // Update Last ID before calling Run().
3363 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003364 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003365 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003366 return status;
3367}
3368
3369/* Main entry point for dumpstate binary. */
3370int run_main(int argc, char* argv[]) {
3371 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003372
3373 switch (status) {
3374 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003375 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003376 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003377 ShowUsage();
3378 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003379 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003380 fprintf(stderr, "Invalid combination of args\n");
3381 ShowUsage();
3382 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003383 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003384 FALLTHROUGH_INTENDED;
3385 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3386 FALLTHROUGH_INTENDED;
3387 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003388 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003389 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003390}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003391
3392// TODO(111441001): Default DumpOptions to sensible values.
3393Dumpstate::Dumpstate(const std::string& version)
3394 : pid_(getpid()),
3395 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003396 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003397 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003398 now_(time(nullptr)),
3399 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003400}
3401
3402Dumpstate& Dumpstate::GetInstance() {
3403 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3404 return singleton_;
3405}
3406
Rhed Jao5377d792020-07-16 17:37:39 +08003407DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3408 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3409 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003410 if (!title_.empty()) {
3411 started_ = Nanotime();
3412 }
3413}
3414
3415DurationReporter::~DurationReporter() {
3416 if (!title_.empty()) {
3417 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003418 if (elapsed >= .5f || verbose_) {
3419 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003420 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003421 if (!logcat_only_) {
3422 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003423 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3424 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003425 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003426 }
3427}
3428
3429const int32_t Progress::kDefaultMax = 5000;
3430
3431Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3432}
3433
3434Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3435 : Progress(initial_max, growth_factor, "") {
3436 progress_ = progress;
3437}
3438
3439Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3440 : initial_max_(initial_max),
3441 progress_(0),
3442 max_(initial_max),
3443 growth_factor_(growth_factor),
3444 n_runs_(0),
3445 average_max_(0),
3446 path_(path) {
3447 if (!path_.empty()) {
3448 Load();
3449 }
3450}
3451
3452void Progress::Load() {
3453 MYLOGD("Loading stats from %s\n", path_.c_str());
3454 std::string content;
3455 if (!android::base::ReadFileToString(path_, &content)) {
3456 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3457 return;
3458 }
3459 if (content.empty()) {
3460 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3461 return;
3462 }
3463 std::vector<std::string> lines = android::base::Split(content, "\n");
3464
3465 if (lines.size() < 1) {
3466 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3467 (int)lines.size(), max_);
3468 return;
3469 }
3470 char* ptr;
3471 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3472 average_max_ = strtol(ptr, nullptr, 10);
3473 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3474 average_max_ > STATS_MAX_AVERAGE) {
3475 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3476 initial_max_ = Progress::kDefaultMax;
3477 } else {
3478 initial_max_ = average_max_;
3479 }
3480 max_ = initial_max_;
3481
3482 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3483}
3484
3485void Progress::Save() {
3486 int32_t total = n_runs_ * average_max_ + progress_;
3487 int32_t runs = n_runs_ + 1;
3488 int32_t average = floor(((float)total) / runs);
3489 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3490 path_.c_str());
3491 if (path_.empty()) {
3492 return;
3493 }
3494
3495 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3496 if (!android::base::WriteStringToFile(content, path_)) {
3497 MYLOGE("Could not save stats on %s\n", path_.c_str());
3498 }
3499}
3500
3501int32_t Progress::Get() const {
3502 return progress_;
3503}
3504
3505bool Progress::Inc(int32_t delta_sec) {
3506 bool changed = false;
3507 if (delta_sec >= 0) {
3508 progress_ += delta_sec;
3509 if (progress_ > max_) {
3510 int32_t old_max = max_;
3511 max_ = floor((float)progress_ * growth_factor_);
3512 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3513 changed = true;
3514 }
3515 }
3516 return changed;
3517}
3518
3519int32_t Progress::GetMax() const {
3520 return max_;
3521}
3522
3523int32_t Progress::GetInitialMax() const {
3524 return initial_max_;
3525}
3526
3527void Progress::Dump(int fd, const std::string& prefix) const {
3528 const char* pr = prefix.c_str();
3529 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3530 dprintf(fd, "%smax: %d\n", pr, max_);
3531 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3532 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3533 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3534 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3535 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3536}
3537
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003538std::string Dumpstate::GetPath(const std::string& suffix) const {
3539 return GetPath(bugreport_internal_dir_, suffix);
3540}
3541
3542std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3543 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3544 name_.c_str(), suffix.c_str());
3545}
3546
3547void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3548 progress_ = std::move(progress);
3549}
3550
3551void for_each_userid(void (*func)(int), const char *header) {
3552 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3553 "for_each_userid(%s)", header);
3554 DurationReporter duration_reporter(title);
3555 if (PropertiesHelper::IsDryRun()) return;
3556
3557 DIR *d;
3558 struct dirent *de;
3559
3560 if (header) printf("\n------ %s ------\n", header);
3561 func(0);
3562
3563 if (!(d = opendir("/data/system/users"))) {
3564 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3565 return;
3566 }
3567
3568 while ((de = readdir(d))) {
3569 int userid;
3570 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3571 continue;
3572 }
3573 func(userid);
3574 }
3575
3576 closedir(d);
3577}
3578
3579static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3580 DIR *d;
3581 struct dirent *de;
3582
3583 if (!(d = opendir("/proc"))) {
3584 printf("Failed to open /proc (%s)\n", strerror(errno));
3585 return;
3586 }
3587
3588 if (header) printf("\n------ %s ------\n", header);
3589 while ((de = readdir(d))) {
3590 if (ds.IsUserConsentDenied()) {
3591 MYLOGE(
3592 "Returning early because user denied consent to share bugreport with calling app.");
3593 closedir(d);
3594 return;
3595 }
3596 int pid;
3597 int fd;
3598 char cmdpath[255];
3599 char cmdline[255];
3600
3601 if (!(pid = atoi(de->d_name))) {
3602 continue;
3603 }
3604
3605 memset(cmdline, 0, sizeof(cmdline));
3606
3607 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3608 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3609 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3610 close(fd);
3611 if (cmdline[0]) {
3612 helper(pid, cmdline, arg);
3613 continue;
3614 }
3615 }
3616
3617 // if no cmdline, a kernel thread has comm
3618 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3619 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3620 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3621 close(fd);
3622 if (cmdline[1]) {
3623 cmdline[0] = '[';
3624 size_t len = strcspn(cmdline, "\f\b\r\n");
3625 cmdline[len] = ']';
3626 cmdline[len+1] = '\0';
3627 }
3628 }
3629 if (!cmdline[0]) {
3630 strcpy(cmdline, "N/A");
3631 }
3632 helper(pid, cmdline, arg);
3633 }
3634
3635 closedir(d);
3636}
3637
3638static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3639 for_each_pid_func *func = (for_each_pid_func*) arg;
3640 func(pid, cmdline);
3641}
3642
3643void for_each_pid(for_each_pid_func func, const char *header) {
3644 std::string title = header == nullptr ? "for_each_pid"
3645 : android::base::StringPrintf("for_each_pid(%s)", header);
3646 DurationReporter duration_reporter(title);
3647 if (PropertiesHelper::IsDryRun()) return;
3648
3649 __for_each_pid(for_each_pid_helper, header, (void *) func);
3650}
3651
3652static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3653 DIR *d;
3654 struct dirent *de;
3655 char taskpath[255];
3656 for_each_tid_func *func = (for_each_tid_func *) arg;
3657
3658 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3659
3660 if (!(d = opendir(taskpath))) {
3661 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3662 return;
3663 }
3664
3665 func(pid, pid, cmdline);
3666
3667 while ((de = readdir(d))) {
3668 if (ds.IsUserConsentDenied()) {
3669 MYLOGE(
3670 "Returning early because user denied consent to share bugreport with calling app.");
3671 closedir(d);
3672 return;
3673 }
3674 int tid;
3675 int fd;
3676 char commpath[255];
3677 char comm[255];
3678
3679 if (!(tid = atoi(de->d_name))) {
3680 continue;
3681 }
3682
3683 if (tid == pid)
3684 continue;
3685
3686 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3687 memset(comm, 0, sizeof(comm));
3688 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3689 strcpy(comm, "N/A");
3690 } else {
3691 char *c;
3692 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3693 close(fd);
3694
3695 c = strrchr(comm, '\n');
3696 if (c) {
3697 *c = '\0';
3698 }
3699 }
3700 func(pid, tid, comm);
3701 }
3702
3703 closedir(d);
3704}
3705
3706void for_each_tid(for_each_tid_func func, const char *header) {
3707 std::string title = header == nullptr ? "for_each_tid"
3708 : android::base::StringPrintf("for_each_tid(%s)", header);
3709 DurationReporter duration_reporter(title);
3710
3711 if (PropertiesHelper::IsDryRun()) return;
3712
3713 __for_each_pid(for_each_tid_helper, header, (void *) func);
3714}
3715
3716void show_wchan(int pid, int tid, const char *name) {
3717 if (PropertiesHelper::IsDryRun()) return;
3718
3719 char path[255];
3720 char buffer[255];
3721 int fd, ret, save_errno;
3722 char name_buffer[255];
3723
3724 memset(buffer, 0, sizeof(buffer));
3725
3726 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3727 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3728 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3729 return;
3730 }
3731
3732 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3733 save_errno = errno;
3734 close(fd);
3735
3736 if (ret < 0) {
3737 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3738 return;
3739 }
3740
3741 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3742 pid == tid ? 0 : 3, "", name);
3743
3744 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3745
3746 return;
3747}
3748
3749// print time in centiseconds
3750static void snprcent(char *buffer, size_t len, size_t spc,
3751 unsigned long long time) {
3752 static long hz; // cache discovered hz
3753
3754 if (hz <= 0) {
3755 hz = sysconf(_SC_CLK_TCK);
3756 if (hz <= 0) {
3757 hz = 1000;
3758 }
3759 }
3760
3761 // convert to centiseconds
3762 time = (time * 100 + (hz / 2)) / hz;
3763
3764 char str[16];
3765
3766 snprintf(str, sizeof(str), " %llu.%02u",
3767 time / 100, (unsigned)(time % 100));
3768 size_t offset = strlen(buffer);
3769 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3770 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3771}
3772
3773// print permille as a percent
3774static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3775 char str[16];
3776
3777 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3778 size_t offset = strlen(buffer);
3779 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3780 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3781}
3782
3783void show_showtime(int pid, const char *name) {
3784 if (PropertiesHelper::IsDryRun()) return;
3785
3786 char path[255];
3787 char buffer[1023];
3788 int fd, ret, save_errno;
3789
3790 memset(buffer, 0, sizeof(buffer));
3791
3792 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3793 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3794 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3795 return;
3796 }
3797
3798 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3799 save_errno = errno;
3800 close(fd);
3801
3802 if (ret < 0) {
3803 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3804 return;
3805 }
3806
3807 // field 14 is utime
3808 // field 15 is stime
3809 // field 42 is iotime
3810 unsigned long long utime = 0, stime = 0, iotime = 0;
3811 if (sscanf(buffer,
3812 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3813 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3814 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3815 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3816 &utime, &stime, &iotime) != 3) {
3817 return;
3818 }
3819
3820 unsigned long long total = utime + stime;
3821 if (!total) {
3822 return;
3823 }
3824
3825 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3826 if (permille > 1000) {
3827 permille = 1000;
3828 }
3829
3830 // try to beautify and stabilize columns at <80 characters
3831 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3832 if ((name[0] != '[') || utime) {
3833 snprcent(buffer, sizeof(buffer), 57, utime);
3834 }
3835 snprcent(buffer, sizeof(buffer), 65, stime);
3836 if ((name[0] != '[') || iotime) {
3837 snprcent(buffer, sizeof(buffer), 73, iotime);
3838 }
3839 if (iotime) {
3840 snprdec(buffer, sizeof(buffer), 79, permille);
3841 }
3842 puts(buffer); // adds a trailing newline
3843
3844 return;
3845}
3846
3847void do_dmesg() {
3848 const char *title = "KERNEL LOG (dmesg)";
3849 DurationReporter duration_reporter(title);
3850 printf("------ %s ------\n", title);
3851
3852 if (PropertiesHelper::IsDryRun()) return;
3853
3854 /* Get size of kernel buffer */
3855 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3856 if (size <= 0) {
3857 printf("Unexpected klogctl return value: %d\n\n", size);
3858 return;
3859 }
3860 char *buf = (char *) malloc(size + 1);
3861 if (buf == nullptr) {
3862 printf("memory allocation failed\n\n");
3863 return;
3864 }
3865 int retval = klogctl(KLOG_READ_ALL, buf, size);
3866 if (retval < 0) {
3867 printf("klogctl failure\n\n");
3868 free(buf);
3869 return;
3870 }
3871 buf[retval] = '\0';
3872 printf("%s\n\n", buf);
3873 free(buf);
3874 return;
3875}
3876
3877void do_showmap(int pid, const char *name) {
3878 char title[255];
3879 char arg[255];
3880
3881 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3882 snprintf(arg, sizeof(arg), "%d", pid);
3883 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3884}
3885
3886int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3887 DurationReporter duration_reporter(title);
3888
3889 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3890
3891 UpdateProgress(WEIGHT_FILE);
3892
3893 return status;
3894}
3895
3896int read_file_as_long(const char *path, long int *output) {
3897 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3898 if (fd < 0) {
3899 int err = errno;
3900 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3901 return -1;
3902 }
3903 char buffer[50];
3904 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3905 if (bytes_read == -1) {
3906 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3907 return -2;
3908 }
3909 if (bytes_read == 0) {
3910 MYLOGE("File %s is empty\n", path);
3911 return -3;
3912 }
3913 *output = atoi(buffer);
3914 return 0;
3915}
3916
3917/* calls skip to gate calling dump_from_fd recursively
3918 * in the specified directory. dump_from_fd defaults to
3919 * dump_file_from_fd above when set to NULL. skip defaults
3920 * to false when set to NULL. dump_from_fd will always be
3921 * called with title NULL.
3922 */
3923int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3924 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3925 DurationReporter duration_reporter(title);
3926 DIR *dirp;
3927 struct dirent *d;
3928 char *newpath = nullptr;
3929 const char *slash = "/";
3930 int retval = 0;
3931
3932 if (!title.empty()) {
3933 printf("------ %s (%s) ------\n", title.c_str(), dir);
3934 }
3935 if (PropertiesHelper::IsDryRun()) return 0;
3936
3937 if (dir[strlen(dir) - 1] == '/') {
3938 ++slash;
3939 }
3940 dirp = opendir(dir);
3941 if (dirp == nullptr) {
3942 retval = -errno;
3943 MYLOGE("%s: %s\n", dir, strerror(errno));
3944 return retval;
3945 }
3946
3947 if (!dump_from_fd) {
3948 dump_from_fd = dump_file_from_fd;
3949 }
3950 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3951 if ((d->d_name[0] == '.')
3952 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3953 || (d->d_name[1] == '\0'))) {
3954 continue;
3955 }
3956 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3957 (d->d_type == DT_DIR) ? "/" : "");
3958 if (!newpath) {
3959 retval = -errno;
3960 continue;
3961 }
3962 if (skip && (*skip)(newpath)) {
3963 continue;
3964 }
3965 if (d->d_type == DT_DIR) {
3966 int ret = dump_files("", newpath, skip, dump_from_fd);
3967 if (ret < 0) {
3968 retval = ret;
3969 }
3970 continue;
3971 }
3972 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3973 if (fd.get() < 0) {
3974 retval = -1;
3975 printf("*** %s: %s\n", newpath, strerror(errno));
3976 continue;
3977 }
3978 (*dump_from_fd)(nullptr, newpath, fd.get());
3979 }
3980 closedir(dirp);
3981 if (!title.empty()) {
3982 printf("\n");
3983 }
3984 return retval;
3985}
3986
3987/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3988 * it's possible to avoid issues where opening the file itself can get
3989 * stuck.
3990 */
3991int dump_file_from_fd(const char *title, const char *path, int fd) {
3992 if (PropertiesHelper::IsDryRun()) return 0;
3993
3994 int flags = fcntl(fd, F_GETFL);
3995 if (flags == -1) {
3996 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3997 return -1;
3998 } else if (!(flags & O_NONBLOCK)) {
3999 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4000 return -1;
4001 }
4002 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4003}
4004
4005int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004006 const CommandOptions& options, bool verbose_duration, int out_fd) {
4007 DurationReporter duration_reporter(title, false /* logcat_only */,
4008 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004009
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004010 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004011
4012 /* TODO: for now we're simplifying the progress calculation by using the
4013 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4014 * where its weight should be much higher proportionally to its timeout.
4015 * Ideally, it should use a options.EstimatedDuration() instead...*/
4016 UpdateProgress(options.Timeout());
4017
4018 return status;
4019}
4020
4021void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004022 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004023 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4024 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4025 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004026 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004027}
4028
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004029static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004030 int s = android_get_control_socket(service);
4031 if (s < 0) {
4032 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4033 return -1;
4034 }
4035 fcntl(s, F_SETFD, FD_CLOEXEC);
4036
4037 // Set backlog to 0 to make sure that queue size will be minimum.
4038 // In Linux, because the minimum queue will be 1, connect() will be blocked
4039 // if the other clients already called connect() and the connection request was not accepted.
4040 if (listen(s, 0) < 0) {
4041 MYLOGE("listen(control socket): %s\n", strerror(errno));
4042 return -1;
4043 }
4044
4045 struct sockaddr addr;
4046 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004047 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004048
4049 // Close socket just after accept(), to make sure that connect() by client will get error
4050 // when the socket is used by the other services.
4051 // There is still a race condition possibility between accept and close, but there is no way
4052 // to close-on-accept atomically.
4053 // See detail; b/123306389#comment25
4054 close(s);
4055
4056 if (fd < 0) {
4057 MYLOGE("accept(control socket): %s\n", strerror(errno));
4058 return -1;
4059 }
4060
4061 return fd;
4062}
4063
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004064// TODO: should call is_valid_output_file and/or be merged into it.
4065void create_parent_dirs(const char *path) {
4066 char *chp = const_cast<char *> (path);
4067
4068 /* skip initial slash */
4069 if (chp[0] == '/')
4070 chp++;
4071
4072 /* create leading directories, if necessary */
4073 struct stat dir_stat;
4074 while (chp && chp[0]) {
4075 chp = strchr(chp, '/');
4076 if (chp) {
4077 *chp = 0;
4078 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4079 MYLOGI("Creating directory %s\n", path);
4080 if (mkdir(path, 0770)) { /* drwxrwx--- */
4081 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4082 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4083 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4084 }
4085 }
4086 *chp++ = '/';
4087 }
4088 }
4089}
4090
4091bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4092 create_parent_dirs(path);
4093
4094 int fd = TEMP_FAILURE_RETRY(open(path,
4095 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4096 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4097 if (fd < 0) {
4098 MYLOGE("%s: %s\n", path, strerror(errno));
4099 return false;
4100 }
4101
4102 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4103 close(fd);
4104 return true;
4105}
4106
4107bool redirect_to_file(FILE* redirect, char* path) {
4108 return _redirect_to_file(redirect, path, O_TRUNC);
4109}
4110
4111bool redirect_to_existing_file(FILE* redirect, char* path) {
4112 return _redirect_to_file(redirect, path, O_APPEND);
4113}
4114
4115void dump_route_tables() {
4116 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4117 if (PropertiesHelper::IsDryRun()) return;
4118 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4119 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4120 FILE* fp = fopen(RT_TABLES_PATH, "re");
4121 if (!fp) {
4122 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4123 return;
4124 }
4125 char table[16];
4126 // Each line has an integer (the table number), a space, and a string (the table name). We only
4127 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4128 // Add a fixed max limit so this doesn't go awry.
4129 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4130 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4131 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4132 }
4133 fclose(fp);
4134}
4135
Li Li830179f2022-01-04 12:53:29 -08004136void dump_frozen_cgroupfs(const char *dir, int level,
4137 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4138 DIR *dirp;
4139 struct dirent *d;
4140 char *newpath = nullptr;
4141
4142 dirp = opendir(dir);
4143 if (dirp == nullptr) {
4144 MYLOGE("%s: %s\n", dir, strerror(errno));
4145 return;
4146 }
4147
4148 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4149 if ((d->d_name[0] == '.')
4150 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4151 || (d->d_name[1] == '\0'))) {
4152 continue;
4153 }
4154 if (d->d_type == DT_DIR) {
4155 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4156 if (!newpath) {
4157 continue;
4158 }
4159 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4160 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4161 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4162 char *freezer = nullptr;
4163 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4164 if (freezer) {
4165 FILE* fp = fopen(freezer, "r");
4166 if (fp != NULL) {
4167 int frozen;
4168 fscanf(fp, "%d", &frozen);
4169 if (frozen > 0) {
4170 dump_files("", newpath, skip_none, dump_from_fd);
4171 }
4172 fclose(fp);
4173 }
4174 free(freezer);
4175 }
4176 }
4177 }
4178 }
4179 closedir(dirp);
4180}
4181
4182void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004183 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4184 DurationReporter duration_reporter("FROZEN CGROUPFS");
4185 if (PropertiesHelper::IsDryRun()) return;
4186 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4187}
4188
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004189void Dumpstate::UpdateProgress(int32_t delta_sec) {
4190 if (progress_ == nullptr) {
4191 MYLOGE("UpdateProgress: progress_ not set\n");
4192 return;
4193 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004194 // This function updates progress related members of the dumpstate and reports
4195 // progress percentage to the bugreport client. Since it could be called by
4196 // different dump tasks at the same time if the parallel run is enabled, a
4197 // mutex lock is necessary here to synchronize the call.
4198 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004199
4200 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004201 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004202
4203 // ...but only notifiy listeners when necessary.
4204 if (!options_->do_progress_updates) return;
4205
4206 int progress = progress_->Get();
4207 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004208 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004209
Nandana Dutt402a8392019-06-14 14:25:13 +01004210 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004211 return;
4212 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004213 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004214
4215 if (control_socket_fd_ >= 0) {
4216 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4217 fsync(control_socket_fd_);
4218 }
4219
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004220 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004221 if (percent % 10 == 0) {
4222 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004223 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004224 } else {
4225 // stderr is ignored on normal invocations, but useful when calling
4226 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004227 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004228 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004229
4230 listener_->onProgress(percent);
4231 }
4232}
4233
4234void Dumpstate::TakeScreenshot(const std::string& path) {
4235 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4236 int status =
4237 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4238 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4239 if (status == 0) {
4240 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4241 } else {
4242 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4243 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004244 if (listener_ != nullptr) {
4245 // Show a visual indication to indicate screenshot is taken via
4246 // IDumpstateListener.onScreenshotTaken()
4247 listener_->onScreenshotTaken(status == 0);
4248 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004249}
4250
4251bool is_dir(const char* pathname) {
4252 struct stat info;
4253 if (stat(pathname, &info) == -1) {
4254 return false;
4255 }
4256 return S_ISDIR(info.st_mode);
4257}
4258
4259time_t get_mtime(int fd, time_t default_mtime) {
4260 struct stat info;
4261 if (fstat(fd, &info) == -1) {
4262 return default_mtime;
4263 }
4264 return info.st_mtime;
4265}