blob: 890c15f895604a6f991f031ecb8d7772695b843c [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>
Felipe Lemef0292972016-11-22 13:57:05 -080091#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070092#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070093#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080094
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000095namespace dumpstate_hal_hidl_1_0 = android::hardware::dumpstate::V1_0;
96namespace dumpstate_hal_hidl = android::hardware::dumpstate::V1_1;
97namespace dumpstate_hal_aidl = aidl::android::hardware::dumpstate;
98
Vishnu Naire97d6122018-01-18 13:58:56 -080099using ::std::literals::chrono_literals::operator""ms;
100using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +0800101using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800102
Felipe Leme47e9be22016-12-21 15:37:07 -0800103// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800104using android::defaultServiceManager;
105using android::Dumpsys;
106using android::INVALID_OPERATION;
107using android::IServiceManager;
108using android::OK;
109using android::sp;
110using android::status_t;
111using android::String16;
112using android::String8;
113using android::TIMED_OUT;
114using android::UNKNOWN_ERROR;
115using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000116using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000117using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800118using android::os::dumpstate::CommandOptions;
119using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800120using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800121using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800122using android::os::dumpstate::TaskQueue;
Chris Morinbc223142022-02-04 14:17:11 -0800123using android::os::dumpstate::WaitForTask;
Felipe Leme47e9be22016-12-21 15:37:07 -0800124
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100125// Keep in sync with
126// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
127static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
128
129/* Most simple commands have 10 as timeout, so 5 is a good estimate */
130static const int32_t WEIGHT_FILE = 5;
131
132// TODO: temporary variables and functions used during C++ refactoring
133static Dumpstate& ds = Dumpstate::GetInstance();
134static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100135 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800136 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
137 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100138}
139
140// Reasonable value for max stats.
141static const int STATS_MAX_N_RUNS = 1000;
142static const long STATS_MAX_AVERAGE = 100000;
143
144CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
145
Nandana Duttd2f5f082019-01-18 17:13:52 +0000146typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
147
Colin Crossf45fa6b2012-03-26 12:38:26 -0700148/* read before root is shed */
149static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700150static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000151static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800152// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
153// it's often the case that they time out far too quickly for consent with such a hefty dialog for
154// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
155// roughly match full reports' durations.
156static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700157
Felipe Leme1d486fe2016-10-14 18:06:47 -0700158// TODO: variables and functions below should be part of dumpstate object
159
Felipe Leme635ca312016-01-05 14:23:02 -0800160static std::set<std::string> mount_points;
161void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800162
Todd Poynor2a83daa2013-11-22 15:44:22 -0800163#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700164#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700165#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800166
Felipe Lemee82a27d2016-01-05 13:35:44 -0800167#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700168#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700169#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700170#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800171#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100172#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
173#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800174#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900175#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800176#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700177#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800178#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900179#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700180#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000181#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700182#define CGROUPFS_DIR "/sys/fs/cgroup"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700183
Narayan Kamath8f788292017-05-25 13:20:39 +0100184// TODO(narayan): Since this information has to be kept in sync
185// with tombstoned, we should just put it in a common header.
186//
187// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100188static const std::string TOMBSTONE_DIR = "/data/tombstones/";
189static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
190static const std::string ANR_DIR = "/data/anr/";
191static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192
Felipe Lemee844a9d2016-09-21 15:01:39 -0700193// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000194
Nandana Dutt5c390032019-03-12 10:52:56 +0000195#define RETURN_IF_USER_DENIED_CONSENT() \
196 if (ds.IsUserConsentDenied()) { \
197 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
198 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
199 }
200
201// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
202// if consent is found to be denied.
203#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
204 RETURN_IF_USER_DENIED_CONSENT(); \
205 func_ptr(__VA_ARGS__); \
206 RETURN_IF_USER_DENIED_CONSENT();
207
Rhed Jao5377d792020-07-16 17:37:39 +0800208// Runs func_ptr, and logs a duration report after it's finished.
209#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
210 { \
211 DurationReporter duration_reporter_in_macro(log_title); \
212 func_ptr(__VA_ARGS__); \
213 }
214
215// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
216// is output after a slow function is finished.
217#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
218 RETURN_IF_USER_DENIED_CONSENT(); \
219 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
220 RETURN_IF_USER_DENIED_CONSENT();
221
Chris Morinbc223142022-02-04 14:17:11 -0800222#define WAIT_TASK_WITH_CONSENT_CHECK(future) \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800223 RETURN_IF_USER_DENIED_CONSENT(); \
Chris Morinbc223142022-02-04 14:17:11 -0800224 WaitForTask(future); \
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800225 RETURN_IF_USER_DENIED_CONSENT();
226
Sahana Raof35ed432019-07-12 10:47:52 +0100227static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
228
Rhed Jao5377d792020-07-16 17:37:39 +0800229// Names of parallel tasks, they are used for the DumpPool to identify the dump
230// task and the log title of the duration report.
231static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800232static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
233static const std::string DUMP_HALS_TASK = "DUMP HALS";
234static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800235static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao5377d792020-07-16 17:37:39 +0800236
Nandana Dutt979388e2018-11-30 16:48:55 +0000237namespace android {
238namespace os {
239namespace {
240
241static int Open(std::string path, int flags, mode_t mode = 0) {
242 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
243 if (fd == -1) {
244 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
245 }
246 return fd;
247}
248
mhasank2d75c442020-06-11 15:05:25 -0700249static int OpenForWrite(std::string path) {
250 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
251 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
252}
Nandana Dutt979388e2018-11-30 16:48:55 +0000253
254static int OpenForRead(std::string path) {
255 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
256}
257
258bool CopyFile(int in_fd, int out_fd) {
259 char buf[4096];
260 ssize_t byte_count;
261 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
262 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
263 return false;
264 }
265 }
266 return (byte_count != -1);
267}
268
269static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000270 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000271
272 // Obtain a handle to the source file.
273 android::base::unique_fd in_fd(OpenForRead(input_file));
274 if (out_fd != -1 && in_fd.get() != -1) {
275 if (CopyFile(in_fd.get(), out_fd)) {
276 return true;
277 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000278 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000279 }
280 return false;
281}
282
Nandana Duttd2f5f082019-01-18 17:13:52 +0000283static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000284 if (file.empty()) {
285 return false;
286 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000287 if (unlink(file.c_str())) {
288 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000289 return false;
290 }
291 return true;
292}
Nandana Dutt979388e2018-11-30 16:48:55 +0000293
Nikita Ioffea325a572019-05-16 19:49:47 +0100294int64_t GetModuleMetadataVersion() {
295 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
296 if (binder == nullptr) {
297 MYLOGE("Failed to retrieve package_native service");
298 return 0L;
299 }
300 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
301 std::string package_name;
302 auto status = package_service->getModuleMetadataPackageName(&package_name);
303 if (!status.isOk()) {
304 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
305 return 0L;
306 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100307 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100308 int64_t version_code;
309 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
310 &version_code);
311 if (!status.isOk()) {
312 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
313 return 0L;
314 }
315 return version_code;
316}
317
mhasank2d75c442020-06-11 15:05:25 -0700318static bool PathExists(const std::string& path) {
319 struct stat sb;
320 return stat(path.c_str(), &sb) == 0;
321}
322
323static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
324 if (input_file == output_file) {
325 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
326 output_file.c_str());
327 return false;
328 }
329 else if (PathExists(output_file)) {
330 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
331 return false;
332 }
333
334 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
335 android::base::unique_fd out_fd(OpenForWrite(output_file));
336 return CopyFileToFd(input_file, out_fd.get());
337}
338
Nandana Dutt979388e2018-11-30 16:48:55 +0000339} // namespace
340} // namespace os
341} // namespace android
342
Felipe Leme678727a2016-09-21 17:22:11 -0700343static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800344 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800345 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
346 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
347}
348static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
349 int out_fd) {
350 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700351}
352static int DumpFile(const std::string& title, const std::string& path) {
353 return ds.DumpFile(title, path);
354}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800355
Felipe Lemee844a9d2016-09-21 15:01:39 -0700356// Relative directory (inside the zip) for all files copied as-is into the bugreport.
357static const std::string ZIP_ROOT_DIR = "FS";
358
Vishnu Naire97d6122018-01-18 13:58:56 -0800359static const std::string kProtoPath = "proto/";
360static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700361static const std::string kDumpstateBoardFiles[] = {
362 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700363 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700364};
365static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
366
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700367static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700368static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700369
Felipe Lemef0292972016-11-22 13:57:05 -0800370static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
371
Narayan Kamath8f788292017-05-25 13:20:39 +0100372/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100373 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800374 * The returned vector is sorted by the mtimes of the dumps with descending
Chris Morinc2cba7a2022-02-01 17:06:50 -0800375 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100376 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700377static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800378 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100379 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100380
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700381 if (dump_dir == nullptr) {
382 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700383 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700384 }
385
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700386 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100387 struct dirent* entry = nullptr;
388 while ((entry = readdir(dump_dir.get()))) {
389 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100390 continue;
391 }
392
Narayan Kamathbd863722017-06-01 18:50:12 +0100393 const std::string base_name(entry->d_name);
394 if (base_name.find(file_prefix) != 0) {
395 continue;
396 }
397
398 const std::string abs_path = dir_path + base_name;
399 android::base::unique_fd fd(
400 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
401 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700402 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100403 break;
404 }
405
406 struct stat st = {};
407 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700408 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100409 continue;
410 }
411
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700412 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700413 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800414 if (!dump_data.empty()) {
415 std::sort(dump_data.begin(), dump_data.end(),
416 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
417 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100418
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700419 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100420}
421
Narayan Kamathbd863722017-06-01 18:50:12 +0100422static bool AddDumps(const std::vector<DumpData>::const_iterator start,
423 const std::vector<DumpData>::const_iterator end,
424 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100425 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100426 for (auto it = start; it != end; ++it) {
427 const std::string& name = it->name;
428 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100429 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100430
431 // Seek to the beginning of the file before dumping any data. A given
432 // DumpData entry might be dumped multiple times in the report.
433 //
434 // For example, the most recent ANR entry is dumped to the body of the
435 // main entry and it also shows up as a separate entry in the bugreport
436 // ZIP file.
437 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
438 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
439 strerror(errno));
440 }
441
Chris Morinc2cba7a2022-02-01 17:06:50 -0800442 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800443 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100444 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100445 }
446 } else {
447 dump_file_from_fd(type_name, name.c_str(), fd);
448 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100449 }
450
451 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700452}
453
Felipe Leme635ca312016-01-05 14:23:02 -0800454// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700455void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800456 char path[PATH_MAX];
457
458 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
459 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700460 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800461 char linkname[PATH_MAX];
462 ssize_t r = readlink(path, linkname, PATH_MAX);
463 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800464 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800465 return;
466 }
467 linkname[r] = '\0';
468
469 if (mount_points.find(linkname) == mount_points.end()) {
470 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700471 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700472 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800473 mount_points.insert(linkname);
474 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800475 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800476 }
477 }
478}
479
480void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700481 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800482 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800483 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700484 for_each_pid(do_mountinfo, nullptr);
485 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800486}
487
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700488static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
489{
490 DIR *d;
491 struct dirent *de;
492 char path[PATH_MAX];
493
494 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700495 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700496 return;
497 }
498
499 while ((de = readdir(d))) {
500 if (de->d_type != DT_LNK) {
501 continue;
502 }
503 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700504 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700505 }
506
507 closedir(d);
508}
509
Mark Salyzyn326842f2015-04-30 09:49:41 -0700510static bool skip_not_stat(const char *path) {
511 static const char stat[] = "/stat";
512 size_t len = strlen(path);
513 if (path[len - 1] == '/') { /* Directory? */
514 return false;
515 }
516 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
517}
518
Felipe Leme4c2d6632016-09-28 14:32:00 -0700519static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800520 return false;
521}
522
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700523unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700524
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800525//
526// stat offsets
527// Name units description
528// ---- ----- -----------
529// read I/Os requests number of read I/Os processed
530#define __STAT_READ_IOS 0
531// read merges requests number of read I/Os merged with in-queue I/O
532#define __STAT_READ_MERGES 1
533// read sectors sectors number of sectors read
534#define __STAT_READ_SECTORS 2
535// read ticks milliseconds total wait time for read requests
536#define __STAT_READ_TICKS 3
537// write I/Os requests number of write I/Os processed
538#define __STAT_WRITE_IOS 4
539// write merges requests number of write I/Os merged with in-queue I/O
540#define __STAT_WRITE_MERGES 5
541// write sectors sectors number of sectors written
542#define __STAT_WRITE_SECTORS 6
543// write ticks milliseconds total wait time for write requests
544#define __STAT_WRITE_TICKS 7
545// in_flight requests number of I/Os currently in flight
546#define __STAT_IN_FLIGHT 8
547// io_ticks milliseconds total time this block device has been active
548#define __STAT_IO_TICKS 9
549// time_in_queue milliseconds total wait time for all requests
550#define __STAT_IN_QUEUE 10
551#define __STAT_NUMBER_FIELD 11
552//
553// read I/Os, write I/Os
554// =====================
555//
556// These values increment when an I/O request completes.
557//
558// read merges, write merges
559// =========================
560//
561// These values increment when an I/O request is merged with an
562// already-queued I/O request.
563//
564// read sectors, write sectors
565// ===========================
566//
567// These values count the number of sectors read from or written to this
568// block device. The "sectors" in question are the standard UNIX 512-byte
569// sectors, not any device- or filesystem-specific block size. The
570// counters are incremented when the I/O completes.
571#define SECTOR_SIZE 512
572//
573// read ticks, write ticks
574// =======================
575//
576// These values count the number of milliseconds that I/O requests have
577// waited on this block device. If there are multiple I/O requests waiting,
578// these values will increase at a rate greater than 1000/second; for
579// example, if 60 read requests wait for an average of 30 ms, the read_ticks
580// field will increase by 60*30 = 1800.
581//
582// in_flight
583// =========
584//
585// This value counts the number of I/O requests that have been issued to
586// the device driver but have not yet completed. It does not include I/O
587// requests that are in the queue but not yet issued to the device driver.
588//
589// io_ticks
590// ========
591//
592// This value counts the number of milliseconds during which the device has
593// had I/O requests queued.
594//
595// time_in_queue
596// =============
597//
598// This value counts the number of milliseconds that I/O requests have waited
599// on this block device. If there are multiple I/O requests waiting, this
600// value will increase as the product of the number of milliseconds times the
601// number of requests waiting (see "read ticks" above for an example).
602#define S_TO_MS 1000
603//
604
Mark Salyzyn326842f2015-04-30 09:49:41 -0700605static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800606 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700607 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700608 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700609 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700610 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700611 getline(&buffer, &i, fp);
612 fclose(fp);
613 if (!buffer) {
614 return -errno;
615 }
616 i = strlen(buffer);
617 while ((i > 0) && (buffer[i - 1] == '\n')) {
618 buffer[--i] = '\0';
619 }
620 if (!*buffer) {
621 free(buffer);
622 return 0;
623 }
624 z = true;
625 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800626 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627 if (fields[i] != 0) {
628 z = false;
629 }
630 }
631 if (z) { /* never accessed */
632 free(buffer);
633 return 0;
634 }
635
Wei Wang509bb5d2017-06-09 14:42:12 -0700636 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
637 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700638 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700639
640 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
641 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
642 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700643 free(buffer);
644
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800645 if (fields[__STAT_IO_TICKS]) {
646 unsigned long read_perf = 0;
647 unsigned long read_ios = 0;
648 if (fields[__STAT_READ_TICKS]) {
649 unsigned long long divisor = fields[__STAT_READ_TICKS]
650 * fields[__STAT_IO_TICKS];
651 read_perf = ((unsigned long long)SECTOR_SIZE
652 * fields[__STAT_READ_SECTORS]
653 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
654 / divisor;
655 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
656 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
657 / divisor;
658 }
659
660 unsigned long write_perf = 0;
661 unsigned long write_ios = 0;
662 if (fields[__STAT_WRITE_TICKS]) {
663 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
664 * fields[__STAT_IO_TICKS];
665 write_perf = ((unsigned long long)SECTOR_SIZE
666 * fields[__STAT_WRITE_SECTORS]
667 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
668 / divisor;
669 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
670 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
671 / divisor;
672 }
673
674 unsigned queue = (fields[__STAT_IN_QUEUE]
675 + (fields[__STAT_IO_TICKS] >> 1))
676 / fields[__STAT_IO_TICKS];
677
678 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700679 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 -0800680 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700681 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 -0800682 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800683 }
684
685 /* bugreport timeout factor adjustment */
686 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
687 worst_write_perf = write_perf;
688 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700689 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700690 return 0;
691}
692
Yao Chenbe3bbc12018-01-17 16:31:10 -0800693static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
694
Tom Cherryf4472f32020-08-05 09:31:17 -0700695// Returns the actual readable size of the given buffer or -1 on error.
696static long logcat_buffer_readable_size(const std::string& buffer) {
697 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
698 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
699 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
700
701 return android_logger_get_log_readable_size(logger);
702}
703
704// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800705static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
706 unsigned long timeout_ms = 0;
707 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700708 long readable_size = logcat_buffer_readable_size(buffer);
709 if (readable_size > 0) {
710 // Engineering margin is ten-fold our guess.
711 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
712 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800713 }
714 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700715}
716
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800717// Opens a socket and returns its file descriptor.
718static int open_socket(const char* service);
719
Nandana Duttd2f5f082019-01-18 17:13:52 +0000720Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
721}
722
723android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
724 std::lock_guard<std::mutex> lock(lock_);
725 result_ = APPROVED;
726 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800727
728 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
729 // consent is granted.
730 if (ds.options_->is_screenshot_copied) {
731 return android::binder::Status::ok();
732 }
733
734 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
735 !ds.do_early_screenshot_) {
736 return android::binder::Status::ok();
737 }
738
739 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
740 ds.options_->screenshot_fd.get());
741 ds.options_->is_screenshot_copied = copy_succeeded;
742 if (copy_succeeded) {
743 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
744 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000745 return android::binder::Status::ok();
746}
747
748android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
749 std::lock_guard<std::mutex> lock(lock_);
750 result_ = DENIED;
751 MYLOGW("User denied consent to share bugreport\n");
752 return android::binder::Status::ok();
753}
754
755UserConsentResult Dumpstate::ConsentCallback::getResult() {
756 std::lock_guard<std::mutex> lock(lock_);
757 return result_;
758}
759
760uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800761 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000762}
763
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700764void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700765 std::string build, fingerprint, radio, bootloader, network;
766 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700767
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700768 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
769 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700770 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
771 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
772 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700773 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700774
Felipe Lemed8b94e52016-12-08 10:21:44 -0800775 printf("========================================================\n");
776 printf("== dumpstate: %s\n", date);
777 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700778
Felipe Lemed8b94e52016-12-08 10:21:44 -0800779 printf("\n");
780 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700781 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800782 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
783 printf("Bootloader: %s\n", bootloader.c_str());
784 printf("Radio: %s\n", radio.c_str());
785 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100786 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
787 if (module_metadata_version != 0) {
788 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
789 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100790 printf("SDK extension versions [r=%s s=%s]\n",
791 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
792 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700793
Felipe Lemed8b94e52016-12-08 10:21:44 -0800794 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800795 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800796 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800797 printf("Uptime: ");
798 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
799 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800801 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
802 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000803 options_->args.c_str(), options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800804 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800805}
806
Felipe Leme24b66ee2016-06-16 10:55:26 -0700807// List of file extensions that can cause a zip file attachment to be rejected by some email
808// service providers.
809static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
810 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
811 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
812 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
813};
814
Vishnu Naire97d6122018-01-18 13:58:56 -0800815status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
816 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700817 std::string valid_name = entry_name;
818
819 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700820 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700821 if (idx != std::string::npos) {
822 std::string extension = entry_name.substr(idx);
823 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
824 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
825 valid_name = entry_name + ".renamed";
826 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
827 }
828 }
829
Felipe Leme6fe9db62016-02-12 09:04:16 -0800830 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
831 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700832 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
833 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700834 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700835 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700836 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800837 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800838 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000839 bool finished_entry = false;
840 auto finish_entry = [this, &finished_entry] {
841 if (!finished_entry) {
842 // This should only be called when we're going to return an earlier error,
843 // which would've been logged. This may imply the file is already corrupt
844 // and any further logging from FinishEntry is more likely to mislead than
845 // not.
846 this->zip_writer_->FinishEntry();
847 }
848 };
849 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800850 auto start = std::chrono::steady_clock::now();
851 auto end = start + timeout;
852 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800853
Felipe Leme770410d2016-01-26 17:07:14 -0800854 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800855 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800856 if (timeout.count() > 0) {
857 // lambda to recalculate the timeout.
858 auto time_left_ms = [end]() {
859 auto now = std::chrono::steady_clock::now();
860 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
861 return std::max(diff.count(), 0LL);
862 };
863
864 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
865 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000866 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
867 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800868 return -errno;
869 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000870 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800871 entry_name.c_str(), strerror(errno), timeout.count());
872 return TIMED_OUT;
873 }
874 }
875
Zach Riggle22200402016-08-18 01:01:24 -0400876 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800877 if (bytes_read == 0) {
878 break;
879 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800880 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800881 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800882 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700883 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700885 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800886 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887 }
888 }
889
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700890 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000891 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700892 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700893 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800894 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800895 }
896
Vishnu Naire97d6122018-01-18 13:58:56 -0800897 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800898}
899
Felipe Leme1d486fe2016-10-14 18:06:47 -0700900bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
901 android::base::unique_fd fd(
902 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700903 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800904 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800905 return false;
906 }
907
Vishnu Naire97d6122018-01-18 13:58:56 -0800908 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800909}
910
911/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700912static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800913 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800914}
915
Felipe Leme1d486fe2016-10-14 18:06:47 -0700916void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700917 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800918 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700919 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800920}
921
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800923 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700925 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700926 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700927 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800928 return false;
929 }
930
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700931 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700933 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700934 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800935 return false;
936 }
937
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700938 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700939 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700940 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800941 return false;
942 }
943
944 return true;
945}
946
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800947static void DoKmsg() {
948 struct stat st;
949 if (!stat(PSTORE_LAST_KMSG, &st)) {
950 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
951 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
952 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
953 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
954 } else {
955 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
956 DumpFile("LAST KMSG", "/proc/last_kmsg");
957 }
958}
959
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800960static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800961 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800962 RunCommand(
963 "KERNEL LOG",
964 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
965 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
966}
967
Nandana Duttdb379fa2019-10-09 16:54:41 +0100968static void DoSystemLogcat(time_t since) {
969 char since_str[80];
970 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
971
972 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
973 RunCommand("SYSTEM LOG",
974 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
975 since_str},
976 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
977}
978
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800979static void DoRadioLogcat() {
980 unsigned long timeout_ms = logcat_timeout({"radio"});
981 RunCommand(
982 "RADIO LOG",
983 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
984 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
985}
986
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800987static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800988 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800989 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
990 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800991 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100992 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800993 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
994 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800995 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800996 RunCommand(
997 "EVENT LOG",
998 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +0100999 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001000 timeout_ms = logcat_timeout({"stats"});
1001 RunCommand(
1002 "STATS LOG",
1003 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001004 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001005 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001006
1007 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1008
1009 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001010 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1011 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001012}
1013
Mike Ma5c267872019-08-21 11:31:34 -07001014static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001015 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1016 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1017 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1018 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1019 if (fd < 0) {
1020 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1021 return;
1022 }
1023 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1024 bool empty = 0 == lseek(fd, 0, SEEK_END);
1025 if (!empty) {
1026 // Use a different name from "incident.proto"
1027 // /proto/incident.proto is reserved for incident service dump
1028 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001029 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1030 path);
1031 } else {
1032 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001033 }
Mike Ma5c267872019-08-21 11:31:34 -07001034}
1035
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001036static void MaybeAddSystemTraceToZip() {
1037 // This function copies into the .zip the system trace that was snapshotted
1038 // by the early call to MaybeSnapshotSystemTrace(), if any background
1039 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001040 if (!ds.has_system_trace_) {
1041 // No background trace was happening at the time dumpstate was invoked.
1042 return;
1043 }
1044 ds.AddZipEntry(
1045 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1046 SYSTEM_TRACE_SNAPSHOT);
1047 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1048}
1049
Sunny Goyal35949782019-11-19 15:54:36 -08001050static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001051 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1052 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1053 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1054 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1055 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1056 if (fd < 0) {
1057 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1058 return;
1059 }
1060 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1061 CommandOptions::WithTimeout(120).Build());
1062 bool empty = 0 == lseek(fd, 0, SEEK_END);
1063 if (!empty) {
1064 ds.AddZipEntry("visible_windows.zip", path);
1065 } else {
1066 MYLOGW("Failed to dump visible windows\n");
1067 }
1068 unlink(path.c_str());
1069}
1070
Jayachandran Ca94c7172017-06-10 15:08:12 -07001071static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001072 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1073 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001074 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001075 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001076 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1077 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1078 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1079 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001080}
1081
David Andersond9ba4752018-12-11 18:26:59 -08001082static void DumpDynamicPartitionInfo() {
1083 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1084 return;
1085 }
1086
1087 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001088 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001089}
1090
Chris Morin5a50d482022-02-01 17:41:18 -08001091static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001092 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1093 anr_traces_dir.c_str());
1094
1095 // If we're here, dump_traces_path will always be a temporary file
1096 // (created with mkostemp or similar) that contains dumps taken earlier
1097 // on in the process.
1098 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001099 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1100 dump_traces_path);
1101 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001102
1103 const int ret = unlink(dump_traces_path);
1104 if (ret == -1) {
1105 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1106 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001107 }
1108 }
1109
Narayan Kamathbd863722017-06-01 18:50:12 +01001110 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001111 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001112 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001113 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001114 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001115
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001116 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001117 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001118 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001119 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001120 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1121 }
1122}
1123
1124static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001125 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001126
Chris Morin5a50d482022-02-01 17:41:18 -08001127 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001128
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001129 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1130
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001131 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001132 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001133 int i = 0;
1134 while (true) {
1135 const std::string slow_trace_path =
1136 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1137 if (stat(slow_trace_path.c_str(), &st)) {
1138 // No traces file at this index, done with the files.
1139 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001140 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001141 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1142 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001143 }
1144}
1145
Wei Wang509bb5d2017-06-09 14:42:12 -07001146static void DumpBlockStatFiles() {
1147 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001148
Wei Wang1dc1ef52017-06-12 11:28:37 -07001149 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1150
1151 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001152 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1153 return;
1154 }
1155
1156 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001157 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001158 if ((d->d_name[0] == '.')
1159 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1160 || (d->d_name[1] == '\0'))) {
1161 continue;
1162 }
1163 const std::string new_path =
1164 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1165 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1166 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1167 printf("\n");
1168 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001169 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001170}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001171
1172static void DumpPacketStats() {
1173 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001174}
1175
1176static void DumpIpAddrAndRules() {
1177 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1178 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1179 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1180 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1181 RunCommand("IP RULES", {"ip", "rule", "show"});
1182 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1183}
1184
Nandana Dutt5c390032019-03-12 10:52:56 +00001185static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1186 std::chrono::milliseconds timeout,
1187 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001188 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001189 sp<android::IServiceManager> sm = defaultServiceManager();
1190 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001191 Vector<String16> args;
1192 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001193 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1194 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001195 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001196 std::string path(title);
1197 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001198 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001199 if (PropertiesHelper::IsDryRun()) {
1200 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1201 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1202 } else {
1203 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1204 if (status == OK) {
1205 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1206 std::chrono::duration<double> elapsed_seconds;
1207 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1208 service == String16("meminfo")) {
1209 // Use a longer timeout for meminfo, since 30s is not always enough.
1210 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1211 /* as_proto = */ false, elapsed_seconds,
1212 bytes_written);
1213 } else {
1214 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1215 /* as_proto = */ false, elapsed_seconds,
1216 bytes_written);
1217 }
1218 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1219 bool dump_complete = (status == OK);
1220 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001221 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001222 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001223
1224 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1225 std::chrono::steady_clock::now() - start);
1226 if (elapsed_duration > timeout) {
1227 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1228 elapsed_duration.count());
1229 break;
1230 }
1231 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001232 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001233}
1234
Vishnu Nair64afc022018-02-01 15:29:34 -08001235static void RunDumpsysText(const std::string& title, int priority,
1236 std::chrono::milliseconds timeout,
1237 std::chrono::milliseconds service_timeout) {
1238 DurationReporter duration_reporter(title);
1239 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1240 fsync(STDOUT_FILENO);
1241 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1242}
1243
1244/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001245static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1246 std::chrono::milliseconds timeout,
1247 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001248 DurationReporter duration_reporter(title);
1249 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1250 fsync(STDOUT_FILENO);
1251 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1252 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001253
1254 RETURN_IF_USER_DENIED_CONSENT();
1255
1256 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1257 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001258}
1259
Nandana Dutt5c390032019-03-12 10:52:56 +00001260static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1261 std::chrono::milliseconds timeout,
1262 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 sp<android::IServiceManager> sm = defaultServiceManager();
1264 Dumpsys dumpsys(sm.get());
1265 Vector<String16> args;
1266 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1267 DurationReporter duration_reporter(title);
1268
1269 auto start = std::chrono::steady_clock::now();
1270 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1271 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001272 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001273 std::string path(kProtoPath);
1274 path.append(String8(service).c_str());
1275 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1276 path.append("_CRITICAL");
1277 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1278 path.append("_HIGH");
1279 }
1280 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001281 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001282 if (status == OK) {
1283 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1284 bool dumpTerminated = (status == OK);
1285 dumpsys.stopDumpThread(dumpTerminated);
1286 }
1287 ZipWriter::FileEntry file_entry;
1288 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001289
1290 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1291 std::chrono::steady_clock::now() - start);
1292 if (elapsed_duration > timeout) {
1293 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1294 elapsed_duration.count());
1295 break;
1296 }
1297 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001298 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001299}
1300
Nandana Dutta7db6342018-11-21 14:53:34 +00001301// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001302static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001303 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1304 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001305
1306 RETURN_IF_USER_DENIED_CONSENT();
1307
1308 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1309 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001310}
1311
1312// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001313static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001314 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1315 // high priority. Reduce timeout once they are able to dump in a shorter time or
1316 // moved to a parallel task.
1317 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1318 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001319
1320 RETURN_IF_USER_DENIED_CONSENT();
1321
1322 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1323 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001324}
1325
1326// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001327static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001328 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001329
1330 RETURN_IF_USER_DENIED_CONSENT();
1331
1332 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1333 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001334}
1335
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001336/*
1337 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1338 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1339 * if it's not running in the parallel task.
1340 */
1341static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001342 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001343 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1344 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001345
Steven Moreland44cd9482018-01-04 16:24:13 -08001346 using android::hidl::manager::V1_0::IServiceManager;
1347 using android::hardware::defaultServiceManager;
1348
1349 sp<IServiceManager> sm = defaultServiceManager();
1350 if (sm == nullptr) {
1351 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1352 return;
1353 }
1354
1355 auto ret = sm->list([&](const auto& interfaces) {
1356 for (const std::string& interface : interfaces) {
1357 std::string cleanName = interface;
1358 std::replace_if(cleanName.begin(),
1359 cleanName.end(),
1360 [](char c) {
1361 return !isalnum(c) &&
1362 std::string("@-_:.").find(c) == std::string::npos;
1363 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001364 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001365
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001366 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001367 {
1368 auto fd = android::base::unique_fd(
1369 TEMP_FAILURE_RETRY(open(path.c_str(),
1370 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1371 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1372 if (fd < 0) {
1373 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1374 continue;
1375 }
1376 RunCommandToFd(fd,
1377 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001378 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001379 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1380
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001381 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001382 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001383 if (!empty) {
1384 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1385 path);
1386 } else {
1387 unlink(path.c_str());
1388 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001389 }
1390 });
1391
1392 if (!ret.isOk()) {
1393 MYLOGE("Could not list hals from hwservicemanager.\n");
1394 }
1395}
1396
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001397static void DumpExternalFragmentationInfo() {
1398 struct stat st;
1399 if (stat("/proc/buddyinfo", &st) != 0) {
1400 MYLOGE("Unable to dump external fragmentation info\n");
1401 return;
1402 }
1403
1404 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1405 std::ifstream ifs("/proc/buddyinfo");
1406 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1407 for (std::string line; std::getline(ifs, line);) {
1408 std::smatch match_results;
1409 if (std::regex_match(line, match_results, unusable_index_regex)) {
1410 std::stringstream free_pages(std::string{match_results[3]});
1411 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1412 std::istream_iterator<int>());
1413
1414 int total_free_pages = 0;
1415 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1416 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1417 }
1418
1419 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1420 match_results[2].str().c_str());
1421
1422 int usable_free_pages = total_free_pages;
1423 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1424 auto unusable_index = (total_free_pages - usable_free_pages) /
1425 static_cast<double>(total_free_pages);
1426 printf(" %5.3f", unusable_index);
1427 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1428 }
1429
1430 printf("\n");
1431 }
1432 }
1433 printf("\n");
1434}
1435
mhasankd451a472020-05-26 18:02:39 -07001436static void DumpstateLimitedOnly() {
1437 // Trimmed-down version of dumpstate to only include a whitelisted
1438 // set of logs (system log, event log, and system server / system app
1439 // crashes, and networking logs). See b/136273873 and b/138459828
1440 // for context.
1441 DurationReporter duration_reporter("DUMPSTATE");
1442 unsigned long timeout_ms;
1443 // calculate timeout
1444 timeout_ms = logcat_timeout({"main", "system", "crash"});
1445 RunCommand("SYSTEM LOG",
1446 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1447 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1448 timeout_ms = logcat_timeout({"events"});
1449 RunCommand(
1450 "EVENT LOG",
1451 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1452 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1453
1454 printf("========================================================\n");
1455 printf("== Networking Service\n");
1456 printf("========================================================\n");
1457
1458 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1459 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001460 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1461 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001462
1463 printf("========================================================\n");
1464 printf("== Dropbox crashes\n");
1465 printf("========================================================\n");
1466
1467 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1468 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1469
1470 printf("========================================================\n");
1471 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1472 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1473 printf("========================================================\n");
1474 printf("== dumpstate: done (id %d)\n", ds.id_);
1475 printf("========================================================\n");
1476}
1477
Rhed Jaoe017f982020-07-21 17:58:41 +08001478/*
1479 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1480 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1481 * if it's not running in the parallel task.
1482 */
1483static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1484 dprintf(out_fd, "========================================================\n");
1485 dprintf(out_fd, "== Checkins\n");
1486 dprintf(out_fd, "========================================================\n");
1487
1488 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1489 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1490 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1491 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1492 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1493 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1494}
1495
1496/*
1497 * Runs dumpsys on activity service to dump all application activities, services
1498 * and providers in the device.
1499 *
1500 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1501 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1502 * if it's not running in the parallel task.
1503 */
1504static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1505 dprintf(out_fd, "========================================================\n");
1506 dprintf(out_fd, "== Running Application Activities\n");
1507 dprintf(out_fd, "========================================================\n");
1508
1509 // The following dumpsys internally collects output from running apps, so it can take a long
1510 // time. So let's extend the timeout.
1511
1512 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1513
1514 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1515
1516 dprintf(out_fd, "========================================================\n");
1517 dprintf(out_fd, "== Running Application Services (platform)\n");
1518 dprintf(out_fd, "========================================================\n");
1519
1520 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1521 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1522
1523 dprintf(out_fd, "========================================================\n");
1524 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1525 dprintf(out_fd, "========================================================\n");
1526
1527 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1528 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1529
1530 dprintf(out_fd, "========================================================\n");
1531 dprintf(out_fd, "== Running Application Providers (platform)\n");
1532 dprintf(out_fd, "========================================================\n");
1533
1534 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001535 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001536
1537 dprintf(out_fd, "========================================================\n");
1538 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1539 dprintf(out_fd, "========================================================\n");
1540
1541 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1542 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1543}
1544
Nandana Dutt5c390032019-03-12 10:52:56 +00001545// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1546// via the consent they are shown. Ignores other errors that occur while running various
1547// commands. The consent checking is currently done around long running tasks, which happen to
1548// be distributed fairly evenly throughout the function.
1549static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001550 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001551
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001552 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
Chris Morinbc223142022-02-04 14:17:11 -08001553 std::future<std::string> dump_hals, dump_incident_report, dump_board, dump_checkins;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001554 if (ds.dump_pool_) {
1555 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1556 // drop root user. Restarts it with two threads for the parallel run.
1557 ds.dump_pool_->start(/* thread_counts = */2);
1558
Chris Morinbc223142022-02-04 14:17:11 -08001559 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1560 dump_incident_report = ds.dump_pool_->enqueueTask(
1561 DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1562 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1563 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1564 dump_checkins = ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001565 }
1566
Nandana Dutt5c390032019-03-12 10:52:56 +00001567 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1568 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1569 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001570 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001571 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001572 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001573 DumpFile("MEMORY INFO", "/proc/meminfo");
1574 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001575 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001576
1577 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1578
Sunny Goyal35949782019-11-19 15:54:36 -08001579 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1580
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001581 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1582 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1583 DumpFile("SLAB INFO", "/proc/slabinfo");
1584 DumpFile("ZONEINFO", "/proc/zoneinfo");
1585 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1586 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001587 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001588
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001589 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001590
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001591 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001592 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001593
1594 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1595 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001596
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001597 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001598 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_hals));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001599 } else {
1600 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1601 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001602
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001603 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001604 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001605 struct stat s;
1606 if (stat("/proc/modules", &s) != 0) {
1607 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1608 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001609 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001610 RunCommand("MODULES INFO",
1611 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1612 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1613 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001614 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001615
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001616 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001617 DoKernelLogcat();
1618 } else {
1619 do_dmesg();
1620 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001621
Felipe Lemef0292972016-11-22 13:57:05 -08001622 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001623
1624 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1625
Jeff Brown1dc94e32014-09-11 14:15:27 -07001626 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001627 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001628
Jack Yu5a6b2e22020-08-14 18:13:35 +08001629 /* Dump Nfc NCI logs */
1630 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001631
Paul Chang0d2aad72020-02-13 20:04:03 +08001632 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001633 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001634 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001635 }
1636
Felipe Lemee184f662016-10-27 10:04:47 -07001637 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001638
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001639 MaybeAddSystemTraceToZip();
1640
Narayan Kamath8f788292017-05-25 13:20:39 +01001641 // NOTE: tombstones are always added as separate entries in the zip archive
1642 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001643 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001644 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001645 if (!tombstones_dumped) {
1646 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001647 }
1648
Jayachandran Ca94c7172017-06-10 15:08:12 -07001649 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001650
Chenbo Feng276a3b62018-08-07 11:44:49 -07001651 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1652
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001653 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001654
Jayachandran Ca94c7172017-06-10 15:08:12 -07001655 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001656
1657 dump_route_tables();
1658
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001659 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1660 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1661 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001662
Nandana Dutt5c390032019-03-12 10:52:56 +00001663 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001664
Chiachang Wang668ede42021-05-17 17:14:20 +08001665 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1666 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1667 // dump with priority parameters to dump high priority information.
1668 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1669 CommandOptions::WithTimeout(10).Build());
1670
Elliott Hughes23ccc622017-02-28 10:14:22 -08001671 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001672
Jin Qianf334d662017-10-10 14:41:37 -07001673 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001674
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001675 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001676
Colin Crossf45fa6b2012-03-26 12:38:26 -07001677 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001678 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1679 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1680
1681 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1682 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1683 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1684 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1685 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001686
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001687 /* Add window and surface trace files. */
1688 if (!PropertiesHelper::IsUserBuild()) {
1689 ds.AddDir(WMTRACE_DATA_DIR, false);
1690 }
1691
Yifan Hongd90cc652020-02-08 16:52:02 -08001692 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1693
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001694 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001695 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_board));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001696 } else {
1697 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1698 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001699
Steven Moreland7440ddb2016-12-15 16:13:39 -08001700 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001701 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1702 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001703 // su does not exist on user builds, so try running without it.
1704 // This way any implementations of vril-dump that do not require
1705 // root can run on user builds.
1706 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001707 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001708 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001709 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001710 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001711 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712 }
1713
Felipe Lemed8b94e52016-12-08 10:21:44 -08001714 printf("========================================================\n");
1715 printf("== Android Framework Services\n");
1716 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001717
Nandana Dutt5c390032019-03-12 10:52:56 +00001718 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001719
Jack He91ff2fe2021-02-18 18:23:43 -08001720 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1721 ds.AddDir("/data/misc/bluetooth/logs", true);
1722
Rhed Jaoe017f982020-07-21 17:58:41 +08001723 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001724 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_checkins));
Rhed Jaoe017f982020-07-21 17:58:41 +08001725 } else {
1726 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1727 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001728
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001729 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001730
Adrian Roos8b397ab2017-04-04 16:35:44 -07001731 printf("========================================================\n");
1732 printf("== Dropbox crashes\n");
1733 printf("========================================================\n");
1734
1735 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1736 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1737
Felipe Lemed8b94e52016-12-08 10:21:44 -08001738 printf("========================================================\n");
1739 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1740 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1741 printf("========================================================\n");
1742 printf("== dumpstate: done (id %d)\n", ds.id_);
1743 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001744
1745 printf("========================================================\n");
1746 printf("== Obtaining statsd metadata\n");
1747 printf("========================================================\n");
1748 // This differs from the usual dumpsys stats, which is the stats report data.
1749 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001750
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001751 // Add linker configuration directory
1752 ds.AddDir(LINKERCONFIG_DIR, true);
1753
Li Li830179f2022-01-04 12:53:29 -08001754 /* Dump frozen cgroupfs */
1755 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001756
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001757 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001758 WAIT_TASK_WITH_CONSENT_CHECK(std::move(dump_incident_report));
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001759 } else {
1760 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1761 DumpIncidentReport);
1762 }
Mike Ma5c267872019-08-21 11:31:34 -07001763
Nandana Dutt5c390032019-03-12 10:52:56 +00001764 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001765}
1766
Nandana Dutt5c390032019-03-12 10:52:56 +00001767/*
1768 * Dumps state for the default case; drops root after it's no longer necessary.
1769 *
1770 * Returns RunStatus::OK if everything went fine.
1771 * Returns RunStatus::ERROR if there was an error.
1772 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1773 * with the caller.
1774 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001775Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001776 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1777 // buffer.
1778 DoLogcat();
1779 // Capture timestamp after first logcat to use in next logcat
1780 time_t logcat_ts = time(nullptr);
1781
Nandana Dutt4be45d12018-09-26 15:04:23 +01001782 /* collect stack traces from Dalvik and native processes (needs root) */
Chris Morinbc223142022-02-04 14:17:11 -08001783 std::future<std::string> dump_traces;
Rhed Jao5377d792020-07-16 17:37:39 +08001784 if (dump_pool_) {
1785 RETURN_IF_USER_DENIED_CONSENT();
1786 // One thread is enough since we only need to enqueue DumpTraces here.
1787 dump_pool_->start(/* thread_counts = */1);
1788
1789 // DumpTraces takes long time, post it to the another thread in the
1790 // pool, if pool is available
Chris Morinbc223142022-02-04 14:17:11 -08001791 dump_traces = dump_pool_->enqueueTask(
1792 DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
Rhed Jao5377d792020-07-16 17:37:39 +08001793 } else {
1794 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1795 &dump_traces_path);
1796 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001797
1798 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001799 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001800 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1801 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001802 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001803
1804 ds.AddDir(RECOVERY_DIR, true);
1805 ds.AddDir(RECOVERY_DATA_DIR, true);
1806 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1807 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1808 if (!PropertiesHelper::IsUserBuild()) {
1809 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1810 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001811 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001812 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001813 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001814 add_mountinfo();
1815 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001816 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001817 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001818
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001819 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001820 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1821
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001822 // Dump IPsec stats. No keys are exposed here.
1823 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1824
Nandana Dutt4be45d12018-09-26 15:04:23 +01001825 // Run ss as root so we can see socket marks.
1826 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1827
1828 // Run iotop as root to show top 100 IO threads
1829 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1830
Erick Reyese68df822019-02-11 14:46:36 -08001831 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001832 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1833 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001834
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001835 DumpFile("PSI cpu", "/proc/pressure/cpu");
1836 DumpFile("PSI memory", "/proc/pressure/memory");
1837 DumpFile("PSI io", "/proc/pressure/io");
1838
Rhed Jao5377d792020-07-16 17:37:39 +08001839 if (dump_pool_) {
1840 RETURN_IF_USER_DENIED_CONSENT();
Chris Morinbc223142022-02-04 14:17:11 -08001841 WaitForTask(std::move(dump_traces));
Rhed Jao5377d792020-07-16 17:37:39 +08001842
Chris Morinbc223142022-02-04 14:17:11 -08001843 // Current running thread in the pool is the root user also. Delete
1844 // the pool and make a new one later to ensure none of threads in the pool are root.
1845 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao5377d792020-07-16 17:37:39 +08001846 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001847 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001848 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001849 }
1850
Nandana Dutt5c390032019-03-12 10:52:56 +00001851 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001852 Dumpstate::RunStatus status = dumpstate();
1853 // Capture logcat since the last time we did it.
1854 DoSystemLogcat(logcat_ts);
1855 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001856}
1857
Rhed Jaob5685b32020-08-14 17:19:17 +08001858// Common states for telephony and wifi which are needed to be collected before
1859// dumpstate drop the root user.
1860static void DumpstateRadioAsRoot() {
1861 DumpIpTablesAsRoot();
1862 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1863}
1864
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001865// This method collects common dumpsys for telephony and wifi. Typically, wifi
1866// reports are fine to include all information, but telephony reports on user
1867// builds need to strip some content (see DumpstateTelephonyOnly).
1868static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001869 // We need to be picky about some stuff for telephony reports on user builds.
1870 if (!include_sensitive_info) {
1871 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1872 DoRadioLogcat();
1873 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001874 // DumpHals takes long time, post it to the another thread in the pool,
1875 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001876 std::future<std::string> dump_hals;
Rhed Jaob5685b32020-08-14 17:19:17 +08001877 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001878 dump_hals = ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001879 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001880 // Contains various system properties and process startup info.
1881 do_dmesg();
1882 // Logs other than the radio buffer may contain package/component names and potential PII.
1883 DoLogcat();
1884 // Too broad for connectivity problems.
1885 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001886 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1887 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08001888 WaitForTask(std::move(dump_hals));
Rhed Jaob5685b32020-08-14 17:19:17 +08001889 } else {
1890 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1891 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001892 }
1893
Jayachandran Ca94c7172017-06-10 15:08:12 -07001894 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001895 DumpIpAddrAndRules();
1896 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001897 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1898 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001899}
1900
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001901// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1902// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1903// for what can be included on user builds: all reported information MUST directly relate to
1904// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1905// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1906// names are not), and MUST NOT contain logs of user application traffic.
1907// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001908static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001909 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001910
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001911 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001912
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001913 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001914
Rhed Jaob5685b32020-08-14 17:19:17 +08001915 DumpstateRadioAsRoot();
1916 if (!DropRootUser()) {
1917 return;
1918 }
1919
1920 // Starts thread pool after the root user is dropped, and two additional threads
1921 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
Chris Morinbc223142022-02-04 14:17:11 -08001922 std::future<std::string> dump_board;
Rhed Jaob5685b32020-08-14 17:19:17 +08001923 if (ds.dump_pool_) {
1924 ds.dump_pool_->start(/*thread_counts =*/2);
1925
1926 // DumpstateBoard takes long time, post it to the another thread in the pool,
1927 // if pool is available.
Chris Morinbc223142022-02-04 14:17:11 -08001928 dump_board = ds.dump_pool_->enqueueTaskWithFd(
1929 DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaob5685b32020-08-14 17:19:17 +08001930 }
1931
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001932 DumpstateRadioCommon(include_sensitive_info);
1933
1934 if (include_sensitive_info) {
1935 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1936 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1937 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1938 // way.
1939 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1940 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001941
1942 printf("========================================================\n");
1943 printf("== Android Framework Services\n");
1944 printf("========================================================\n");
1945
Vishnu Nair652cc802017-11-30 15:18:30 -08001946 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1947 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001948 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1949 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001950 if (include_sensitive_info) {
1951 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1952 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1953 SEC_TO_MSEC(10));
1954 } else {
1955 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1956 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1957 // give a higher timeout as well.
1958 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1959 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1960 }
1961 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001962 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1963 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001964 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001965 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1966 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001967 if (include_sensitive_info) {
1968 // Contains raw IP addresses, omit from reports on user builds.
1969 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1970 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1971 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1972 SEC_TO_MSEC(10));
1973 // Contains package/component names, omit from reports on user builds.
1974 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1975 SEC_TO_MSEC(10));
1976 // Contains package names, but should be relatively simple to remove them (also contains
1977 // UIDs already), omit from reports on user builds.
1978 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1979 SEC_TO_MSEC(10));
1980 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001981
1982 printf("========================================================\n");
1983 printf("== Running Application Services\n");
1984 printf("========================================================\n");
1985
1986 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1987
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001988 if (include_sensitive_info) {
1989 printf("========================================================\n");
1990 printf("== Running Application Services (non-platform)\n");
1991 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001992
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001993 // Contains package/component names and potential PII, omit from reports on user builds.
1994 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1995 // carrier_config dumpsys instead.
1996 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1997 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001998
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001999 printf("========================================================\n");
2000 printf("== Checkins\n");
2001 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002002
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002003 // Contains package/component names, omit from reports on user builds.
2004 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2005 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002006
2007 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002008 printf("== dumpstate: done (id %d)\n", ds.id_);
2009 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002010
2011 if (ds.dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08002012 WaitForTask(std::move(dump_board));
Rhed Jaob5685b32020-08-14 17:19:17 +08002013 } else {
2014 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2015 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002016}
2017
mukesh agrawal253dad42018-01-23 21:59:59 -08002018// This method collects dumpsys for wifi debugging only
2019static void DumpstateWifiOnly() {
2020 DurationReporter duration_reporter("DUMPSTATE");
2021
Rhed Jaob5685b32020-08-14 17:19:17 +08002022 DumpstateRadioAsRoot();
2023 if (!DropRootUser()) {
2024 return;
2025 }
2026
2027 // Starts thread pool after the root user is dropped. Only one additional
2028 // thread is needed for DumpHals in the DumpstateRadioCommon.
2029 if (ds.dump_pool_) {
2030 ds.dump_pool_->start(/*thread_counts =*/1);
2031 }
2032
mukesh agrawal253dad42018-01-23 21:59:59 -08002033 DumpstateRadioCommon();
2034
2035 printf("========================================================\n");
2036 printf("== Android Framework Services\n");
2037 printf("========================================================\n");
2038
2039 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2040 SEC_TO_MSEC(10));
2041 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2042 SEC_TO_MSEC(10));
2043
2044 printf("========================================================\n");
2045 printf("== dumpstate: done (id %d)\n", ds.id_);
2046 printf("========================================================\n");
2047}
2048
Nandana Duttcf419a72019-03-14 10:40:17 +00002049Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002050 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002051 const size_t buf_size = temp_file_pattern.length() + 1;
2052 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2053 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2054
2055 // Create a new, empty file to receive all trace dumps.
2056 //
2057 // TODO: This can be simplified once we remove support for the old style
2058 // dumps. We can have a file descriptor passed in to dump_traces instead
2059 // of creating a file, closing it and then reopening it again.
2060 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2061 if (fd < 0) {
2062 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002063 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002064 }
2065
2066 // Nobody should have access to this temporary file except dumpstate, but we
2067 // temporarily grant 'read' to 'others' here because this file is created
2068 // when tombstoned is still running as root, but dumped after dropping. This
2069 // can go away once support for old style dumping has.
2070 const int chmod_ret = fchmod(fd, 0666);
2071 if (chmod_ret < 0) {
2072 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002073 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002074 }
2075
2076 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2077 if (proc.get() == nullptr) {
2078 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002079 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002080 }
2081
2082 // Number of times process dumping has timed out. If we encounter too many
2083 // failures, we'll give up.
2084 int timeout_failures = 0;
2085 bool dalvik_found = false;
2086
2087 const std::set<int> hal_pids = get_interesting_hal_pids();
2088
2089 struct dirent* d;
2090 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002091 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002092 int pid = atoi(d->d_name);
2093 if (pid <= 0) {
2094 continue;
2095 }
2096
2097 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2098 std::string exe;
2099 if (!android::base::Readlink(link_name, &exe)) {
2100 continue;
2101 }
2102
2103 bool is_java_process;
2104 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2105 // Don't bother dumping backtraces for the zygote.
2106 if (IsZygote(pid)) {
2107 continue;
2108 }
2109
2110 dalvik_found = true;
2111 is_java_process = true;
2112 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2113 is_java_process = false;
2114 } else {
2115 // Probably a native process we don't care about, continue.
2116 continue;
2117 }
2118
2119 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2120 if (timeout_failures == 3) {
2121 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2122 break;
2123 }
2124
2125 const uint64_t start = Nanotime();
2126 const int ret = dump_backtrace_to_file_timeout(
2127 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2128 is_java_process ? 5 : 20, fd);
2129
2130 if (ret == -1) {
2131 // For consistency, the header and footer to this message match those
2132 // dumped by debuggerd in the success case.
2133 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2134 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2135 dprintf(fd, "---- end %d ----", pid);
2136 timeout_failures++;
2137 continue;
2138 }
2139
2140 // We've successfully dumped stack traces, reset the failure count
2141 // and write a summary of the elapsed time to the file and continue with the
2142 // next process.
2143 timeout_failures = 0;
2144
2145 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2146 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2147 }
2148
2149 if (!dalvik_found) {
2150 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2151 }
2152
Nandana Duttcf419a72019-03-14 10:40:17 +00002153 *path = file_name_buf.release();
2154 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002155}
2156
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002157static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2158 const Dumpstate::BugreportMode bugreport_mode) {
2159 switch (bugreport_mode) {
2160 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2161 return dumpstate_hal_hidl::DumpstateMode::FULL;
2162 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2163 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2164 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2165 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2166 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2167 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2168 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2169 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2170 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2171 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2172 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2173 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2174 }
2175 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2176}
2177
2178static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2179 const Dumpstate::BugreportMode bugreport_mode) {
2180 switch (bugreport_mode) {
2181 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2182 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2183 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2184 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2185 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2186 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2187 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2188 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2189 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2190 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2191 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2192 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2193 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2194 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2195 }
2196 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2197}
2198
2199static void DoDumpstateBoardHidl(
2200 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2201 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2202 const Dumpstate::BugreportMode bugreport_mode,
2203 const size_t timeout_sec) {
2204
2205 using ScopedNativeHandle =
2206 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2207 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2208 [](native_handle_t* handle) {
2209 // we don't close file handle's here
2210 // via native_handle_close(handle)
2211 // instead we let dumpstate_fds close the file handles when
2212 // dumpstate_fds gets destroyed
2213 native_handle_delete(handle);
2214 });
2215 if (handle == nullptr) {
2216 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2217 return;
2218 }
2219
2220 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2221 handle.get()->data[i] = dumpstate_fds[i].get();
2222 }
2223
2224 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2225 // implement just 1.0.
2226 const char* descriptor_to_kill;
2227 using DumpstateBoardTask = std::packaged_task<bool()>;
2228 DumpstateBoardTask dumpstate_board_task;
2229 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2230 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2231 if (dumpstate_hal != nullptr) {
2232 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2233
2234 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2235 GetDumpstateHalModeHidl(bugreport_mode);
2236
2237 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2238 dumpstate_board_task =
2239 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2240 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2241 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2242 SEC_TO_MSEC(timeout_sec));
2243 if (!status.isOk()) {
2244 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2245 return false;
2246 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2247 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2248 dumpstate_hal_hidl::toString(status).c_str());
2249 return false;
2250 }
2251 return true;
2252 });
2253 } else {
2254 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2255
2256 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2257 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2258 ::android::hardware::Return<void> status =
2259 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2260 if (!status.isOk()) {
2261 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2262 return false;
2263 }
2264 return true;
2265 });
2266 }
2267 auto result = dumpstate_board_task.get_future();
2268 std::thread(std::move(dumpstate_board_task)).detach();
2269
2270 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2271 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2272 if (!android::base::SetProperty(
2273 "ctl.interface_restart",
2274 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2275 MYLOGE("Couldn't restart dumpstate HAL\n");
2276 }
2277 }
2278 // Wait some time for init to kill dumpstate vendor HAL
2279 constexpr size_t killing_timeout_sec = 10;
2280 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2281 MYLOGE(
2282 "killing dumpstateBoard timed out after %zus, continue and "
2283 "there might be racing in content\n",
2284 killing_timeout_sec);
2285 }
2286}
2287
2288static void DoDumpstateBoardAidl(
2289 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2290 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2291 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2292 MYLOGI("Using IDumpstateDevice AIDL HAL");
2293
2294 const char* descriptor_to_kill;
2295 using DumpstateBoardTask = std::packaged_task<bool()>;
2296 DumpstateBoardTask dumpstate_board_task;
2297 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2298 GetDumpstateHalModeAidl(bugreport_mode);
2299
2300 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2301 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2302 timeout_sec]() -> bool {
2303 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2304
2305 if (!status.isOk()) {
2306 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2307 return false;
2308 }
2309 return true;
2310 });
2311 auto result = dumpstate_board_task.get_future();
2312 std::thread(std::move(dumpstate_board_task)).detach();
2313
2314 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2315 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2316 if (!android::base::SetProperty(
2317 "ctl.interface_restart",
2318 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2319 MYLOGE("Couldn't restart dumpstate HAL\n");
2320 }
2321 }
2322 // Wait some time for init to kill dumpstate vendor HAL
2323 constexpr size_t killing_timeout_sec = 10;
2324 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2325 MYLOGE(
2326 "killing dumpstateBoard timed out after %zus, continue and "
2327 "there might be racing in content\n",
2328 killing_timeout_sec);
2329 }
2330}
2331
2332static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2333 const std::string aidl_instance_name =
2334 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2335
2336 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2337 return nullptr;
2338 }
2339
2340 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2341
2342 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2343}
2344
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002345void Dumpstate::DumpstateBoard(int out_fd) {
2346 dprintf(out_fd, "========================================================\n");
2347 dprintf(out_fd, "== Board\n");
2348 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002349
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002350 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002351 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002352 * set to true and unmount it after invoking dumpstateBoard_* methods.
2353 * This is to enable debug builds to not have debugfs mounted during runtime.
2354 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002355 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002356 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002357 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002358 if (mount_debugfs) {
2359 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2360 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002361 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002362 }
2363
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002364 std::vector<std::string> paths;
2365 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002366 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002367 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2368 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002369 remover.emplace_back(android::base::make_scope_guard(
2370 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002371 }
Jie Song9fbfad02017-06-20 16:29:42 -07002372
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002373 // get dumpstate HAL AIDL implementation
2374 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2375 GetDumpstateBoardAidlService());
2376 if (dumpstate_hal_handle_aidl == nullptr) {
2377 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2378 }
2379
2380 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2381 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2382 if (dumpstate_hal_handle_aidl == nullptr) {
2383 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2384 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2385 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2386 }
2387 }
2388
2389 // if neither HIDL nor AIDL implementation found, then return
2390 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2391 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002392 return;
2393 }
2394
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002395 // this is used to hold the file descriptors and when this variable goes out of scope
2396 // the file descriptors are closed
2397 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002398
Nandana Dutt5c390032019-03-12 10:52:56 +00002399 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002400 for (size_t i = 0; i < paths.size(); i++) {
2401 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2402
2403 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2404 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2405 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2406 if (fd < 0) {
2407 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2408 return;
2409 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002410
2411 dumpstate_fds.emplace_back(fd.release());
2412 // we call fd.release() here to make sure "fd" does not get closed
2413 // after "fd" goes out of scope after this block.
2414 // "fd" will be closed when "dumpstate_fds" goes out of scope
2415 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002416 }
2417
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002418 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2419 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2420 // will kill the HAL and grab whatever it dumped in time.
Michael Eastwood8523ea02022-03-10 16:33:08 -08002421 constexpr size_t timeout_sec = 45;
Wei Wang587eac92018-04-05 12:17:20 -07002422
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002423 if (dumpstate_hal_handle_aidl != nullptr) {
2424 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2425 timeout_sec);
2426 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2427 // run HIDL HAL only if AIDL HAL not found
2428 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2429 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002430 }
2431
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002432 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002433 auto keep_debugfs_mounted =
2434 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2435 if (keep_debugfs_mounted.empty())
2436 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002437 }
2438
Wei Wang587eac92018-04-05 12:17:20 -07002439 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2440 for (size_t i = 0; i < paths.size(); i++) {
2441 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002442 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2443 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002444 file_sizes[i] = -1;
2445 continue;
2446 }
2447 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002448 }
2449
2450 for (size_t i = 0; i < paths.size(); i++) {
2451 if (file_sizes[i] == -1) {
2452 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002453 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002454 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002455 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002456 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002457 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002458 remover[i].Disable();
2459 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2460 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002461 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002462}
2463
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002464static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002465 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002466 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2467 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002468 " -h: display this help message\n"
2469 " -b: play sound file instead of vibrate, at beginning of job\n"
2470 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002471 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002472 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002473 " -s: write zipped file to control socket (for init)\n"
2474 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002475 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002476 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002477 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002478 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002479 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002480 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002481}
2482
Wei Liuf87959e2016-08-26 14:51:42 -07002483static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002484 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002485}
2486
Felipe Leme1d486fe2016-10-14 18:06:47 -07002487bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002488 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2489 if (zip_entry_tasks_) {
2490 zip_entry_tasks_->run(/* do_cancel = */false);
2491 }
2492
Felipe Leme9a523ae2016-10-20 15:10:33 -07002493 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002494 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002495 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002496 // Final timestamp
2497 char date[80];
2498 time_t the_real_now_please_stand_up = time(nullptr);
2499 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002500 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002501 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002502
Felipe Leme9a523ae2016-10-20 15:10:33 -07002503 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002504 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002505 return false;
2506 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002507 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002508 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002509 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002510 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002511
Felipe Leme0f3fb202016-06-10 17:10:53 -07002512 // Add log file (which contains stderr output) to zip...
2513 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002514 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002515 MYLOGE("Failed to add dumpstate log to .zip file\n");
2516 return false;
2517 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002518 // TODO: Should truncate the existing file.
2519 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002520 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2521 return false;
2522 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002523 fprintf(stderr, "\n");
2524
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002525 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002526 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002527 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002528 return false;
2529 }
2530
Felipe Leme1d486fe2016-10-14 18:06:47 -07002531 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2532 ds.zip_file.reset(nullptr);
2533
Felipe Lemee9d2c542016-11-15 11:48:26 -08002534 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002535 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002536
Felipe Leme1e9edc62015-12-21 16:02:13 -08002537 return true;
2538}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002539
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002540static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2541 // clang-format off
2542 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2543 "--receiver-foreground", "--receiver-include-background", "-a", action};
2544 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002545
2546 am.insert(am.end(), args.begin(), args.end());
2547
Felipe Leme8d2410e2017-02-08 09:46:08 -08002548 RunCommand("", am,
2549 CommandOptions::WithTimeout(20)
2550 .Log("Sending broadcast: '%s'\n")
2551 .Always()
2552 .DropRoot()
2553 .RedirectStderr()
2554 .Build());
2555}
2556
Felipe Leme35b8cf12017-02-10 15:47:29 -08002557static void Vibrate(int duration_ms) {
2558 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002559 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2560 "oneshot", std::to_string(duration_ms)};
2561 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002562 CommandOptions::WithTimeout(10)
2563 .Log("Vibrate: '%s'\n")
2564 .Always()
2565 .Build());
2566 // clang-format on
2567}
2568
Nandana Dutt979388e2018-11-30 16:48:55 +00002569static void MaybeResolveSymlink(std::string* path) {
2570 std::string resolved_path;
2571 if (android::base::Readlink(*path, &resolved_path)) {
2572 *path = resolved_path;
2573 }
2574}
2575
Nandana Dutt4be45d12018-09-26 15:04:23 +01002576/*
2577 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002578 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002579 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002580static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002581 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2582
Nandana Dutt4be45d12018-09-26 15:04:23 +01002583 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2584 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002585 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002586 char date[80];
2587 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2588 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002589
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002590 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002591 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002592 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002593 ds.base_name_ += "-wifi";
2594 }
2595
Paul Chang0d2aad72020-02-13 20:04:03 +08002596 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002597 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002598 }
2599 ds.tmp_path_ = ds.GetPath(".tmp");
2600 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2601
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002602 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002603 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002604 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002605 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002606 "Bugreport dir: [%s] "
2607 "Base name: [%s] "
2608 "Suffix: [%s] "
2609 "Log path: [%s] "
2610 "Temporary path: [%s] "
2611 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002612 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2613 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002614
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002615 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2616 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2617 create_parent_dirs(ds.path_.c_str());
2618 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2619 if (ds.zip_file == nullptr) {
2620 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2621 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002622 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002623 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2624 ds.AddTextZipEntry("version.txt", ds.version_);
2625 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002626}
2627
2628/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002629 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002630 * printing zipped file status, etc.
2631 */
2632static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002633 bool do_text_file = !ds.FinishZipFile();
2634 if (do_text_file) {
2635 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002636 }
mhasank2d75c442020-06-11 15:05:25 -07002637
2638 std::string final_path = ds.path_;
2639 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002640 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002641 android::os::CopyFileToFile(ds.path_, final_path);
2642 }
2643
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002644 if (ds.options_->stream_to_socket) {
2645 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2646 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002647 if (do_text_file) {
2648 dprintf(ds.control_socket_fd_,
2649 "FAIL:could not create zip file, check %s "
2650 "for more details\n",
2651 ds.log_path_.c_str());
2652 } else {
mhasank2d75c442020-06-11 15:05:25 -07002653 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002654 }
2655 }
2656}
2657
Nandana Dutt4be45d12018-09-26 15:04:23 +01002658
Nandana Dutt58d72e22018-11-16 10:30:48 +00002659static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2660 switch (mode) {
2661 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2662 return "BUGREPORT_FULL";
2663 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2664 return "BUGREPORT_INTERACTIVE";
2665 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2666 return "BUGREPORT_REMOTE";
2667 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2668 return "BUGREPORT_WEAR";
2669 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2670 return "BUGREPORT_TELEPHONY";
2671 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2672 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002673 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2674 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002675 }
2676}
2677
Paul Changf59c2b72020-03-10 02:08:55 +08002678static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2679 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002680 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2681 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002682 options->bugreport_mode = mode;
2683 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002684 switch (mode) {
2685 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002686 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002687 break;
2688 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002689 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002690 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002691 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002692 break;
2693 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002694 options->do_vibrate = false;
2695 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002696 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002697 break;
2698 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002699 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002700 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002701 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002702 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002703 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002704 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002705 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002706 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002707 break;
2708 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002709 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002710 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002711 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002712 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2713 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002714 }
2715}
2716
Nandana Dutt58d72e22018-11-16 10:30:48 +00002717static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002718 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002719 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002720 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002721 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002722 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002723 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002724 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002725 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002726 options.do_progress_updates, options.bugreport_fd.get(),
2727 options.bugreport_mode_string.c_str(),
2728 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002729}
2730
Nandana Dutt54dbd672019-01-11 12:58:05 +00002731void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2732 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002733 const android::base::unique_fd& screenshot_fd_in,
2734 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002735 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
Todd Frederick621533f2022-03-26 02:54:17 +00002736 bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
2737 screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002738
Paul Changf59c2b72020-03-10 02:08:55 +08002739 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002740}
2741
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002742Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2743 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002744 int c;
mhasankd451a472020-05-26 18:02:39 -07002745 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002746 switch (c) {
2747 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002748 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002749 case 's': stream_to_socket = true; break;
2750 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002751 case 'v': show_header_only = true; break;
2752 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002753 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002754 case 'P': do_progress_updates = true; break;
2755 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002756 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002757 case 'V':
2758 case 'd':
2759 case 'z':
2760 // compatibility no-op
2761 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002762 case 'w':
2763 // This was already processed
2764 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002765 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002766 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002767 break;
2768 default:
2769 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002770 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002771 break;
2772 // clang-format on
2773 }
2774 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002775
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002776 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002777 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002778 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002779 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002780 }
2781 }
2782
2783 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2784 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002785
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002786 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002787}
2788
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002789bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002790 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002791 return false;
2792 }
2793
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002794 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002795 return false;
2796 }
2797
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002798 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002799 return false;
2800 }
2801 return true;
2802}
2803
Nandana Dutt197661d2018-11-16 16:40:21 +00002804void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2805 options_ = std::move(options);
2806}
2807
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002808void Dumpstate::Initialize() {
2809 /* gets the sequential id */
2810 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2811 id_ = ++last_id;
2812 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2813}
2814
Nandana Duttd2f5f082019-01-18 17:13:52 +00002815Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2816 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002817 if (listener_ != nullptr) {
2818 switch (status) {
2819 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002820 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002821 break;
2822 case Dumpstate::RunStatus::HELP:
2823 break;
2824 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002825 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002826 break;
2827 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002828 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2829 break;
2830 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2831 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2832 break;
2833 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2834 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002835 break;
2836 }
2837 }
2838 return status;
2839}
2840
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002841void Dumpstate::Cancel() {
2842 CleanupTmpFiles();
2843 android::os::UnlinkAndLogOnError(log_path_);
2844 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2845 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2846 kDumpstateBoardFiles[i]);
2847 }
2848 tombstone_data_.clear();
2849 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002850
2851 // Instead of shutdown the pool, we delete temporary files directly since
2852 // shutdown blocking the call.
2853 if (dump_pool_) {
2854 dump_pool_->deleteTempFiles();
2855 }
2856 if (zip_entry_tasks_) {
2857 zip_entry_tasks_->run(/*do_cancel =*/ true);
2858 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002859}
2860
Nandana Dutt979388e2018-11-30 16:48:55 +00002861/*
2862 * Dumps relevant information to a bugreport based on the given options.
2863 *
2864 * The bugreport can be dumped to a file or streamed to a socket.
2865 *
2866 * How dumping to file works:
2867 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2868 * stderr is redirected a log file.
2869 *
2870 * The temporary bugreport is then populated via printfs, dumping contents of files and
2871 * output of commands to stdout.
2872 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002873 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002874 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002875 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002876 *
mhasank2d75c442020-06-11 15:05:25 -07002877 * Bugreports are first generated in a local directory and later copied to the caller's fd
2878 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002879 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002880Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2881 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002882 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002883 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002884 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002885 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002886 return RunStatus::INVALID_INPUT;
2887 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002888 /* set as high priority, and protect from OOM killer */
2889 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002890
Felipe Lemed071c682016-10-20 16:48:00 -07002891 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002892 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002893 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002894 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002895 } else {
2896 /* fallback to kernels <= 2.6.35 */
2897 oom_adj = fopen("/proc/self/oom_adj", "we");
2898 if (oom_adj) {
2899 fputs("-17", oom_adj);
2900 fclose(oom_adj);
2901 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002902 }
2903
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002904 if (version_ == VERSION_DEFAULT) {
2905 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002906 }
2907
Chris Morin5a50d482022-02-01 17:41:18 -08002908 if (version_ != VERSION_CURRENT) {
2909 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
2910 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002911 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002912 }
2913
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002914 if (options_->show_header_only) {
2915 PrintHeader();
2916 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002917 }
2918
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002919 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2920 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002921
Felipe Leme7447d7c2016-11-03 18:12:22 -07002922 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002923 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002924 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002925 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002926
Sahana Raof35ed432019-07-12 10:47:52 +01002927 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2928 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2929 } else {
2930 // Wake lock will be released automatically on process death
2931 MYLOGD("Wake lock acquired.\n");
2932 }
2933
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002934 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002935
Felipe Lemef0292972016-11-22 13:57:05 -08002936 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002937 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2938 }
2939
Nandana Dutt235c6672019-11-14 15:22:32 +00002940 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002941 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002942
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002943 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002944
Christopher Ferrised9354f2014-10-01 17:35:01 -07002945 // If we are going to use a socket, do it as early as possible
2946 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002947 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002948 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002949 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002950 if (control_socket_fd_ == -1) {
2951 return ERROR;
2952 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002953 if (options_->progress_updates_to_socket) {
2954 options_->do_progress_updates = 1;
2955 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002956 }
2957
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002958 if (!PrepareToWriteToFile()) {
2959 return ERROR;
2960 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002961
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002962 // Interactive, wear & telephony modes are default to true.
2963 // and may enable from cli option or when using control socket
2964 if (options_->do_progress_updates) {
2965 // clang-format off
2966 std::vector<std::string> am_args = {
2967 "--receiver-permission", "android.permission.DUMP",
2968 };
2969 // clang-format on
2970 // Send STARTED broadcast for apps that listen to bugreport generation events
2971 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2972 if (options_->progress_updates_to_socket) {
2973 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002974 }
2975 }
2976
Nick Kralevichf3599b32016-01-25 15:05:16 -08002977 /* read /proc/cmdline before dropping root */
2978 FILE *cmdline = fopen("/proc/cmdline", "re");
2979 if (cmdline) {
2980 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2981 fclose(cmdline);
2982 }
2983
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002984 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002985 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002986 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002987
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002988 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002989 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2990 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002991 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002992 }
2993 }
2994
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002995 int dup_stdout_fd;
2996 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002997 // Redirect stderr to log_path_ for debugging.
2998 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2999 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3000 return ERROR;
3001 }
3002 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3003 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3004 strerror(errno));
3005 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003006
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003007 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3008 // moved into zip file later, if zipping.
3009 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3010 // TODO: why not write to a file instead of stdout to overcome this problem?
3011 /* TODO: rather than generating a text file now and zipping it later,
3012 it would be more efficient to redirect stdout to the zip entry
3013 directly, but the libziparchive doesn't support that option yet. */
3014 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3015 return ERROR;
3016 }
3017 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3018 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3019 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003020 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003021
3022 // Don't buffer stdout
3023 setvbuf(stdout, nullptr, _IONBF, 0);
3024
Rhed Jao5377d792020-07-16 17:37:39 +08003025 // Enable the parallel run if the client requests to output to a file.
3026 EnableParallelRunIfNeeded();
3027 // Using scope guard to make sure the dump pool can be shut down correctly.
3028 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3029 ShutdownDumpPool();
3030 });
3031
Felipe Leme608385d2016-02-01 10:35:38 -08003032 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3033 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003034 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003035 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003036
Gavin Corkery6968f552020-11-22 18:09:05 +00003037 bool is_dumpstate_restricted = options_->telephony_only
3038 || options_->wifi_only
3039 || options_->limited_only;
3040 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003041 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003042 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003043 }
3044 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003045
3046 if (!is_dumpstate_restricted) {
3047 // Snapshot the system trace now (if running) to avoid that dumpstate's
3048 // own activity pushes out interesting data from the trace ring buffer.
3049 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3050 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003051
3052 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3053 // from WMTRACE_DATA_DIR.
3054 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003055 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003056 onUiIntensiveBugreportDumpsFinished(calling_uid);
3057 MaybeCheckUserConsent(calling_uid, calling_package);
3058 if (options_->telephony_only) {
3059 DumpstateTelephonyOnly(calling_package);
3060 } else if (options_->wifi_only) {
3061 DumpstateWifiOnly();
3062 } else if (options_->limited_only) {
3063 DumpstateLimitedOnly();
3064 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003065 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003066 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003067 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003068 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003069 HandleUserConsentDenied();
3070 }
3071 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003072 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003073 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003074
Felipe Leme55b42a62015-11-10 17:39:08 -08003075 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003076 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003077
Abhijeet Kaure370d682019-10-01 16:49:30 +01003078 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003079 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003080
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003081 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003082 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01003083 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003084 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003085 if (status != Dumpstate::RunStatus::OK &&
3086 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3087 // Do an early return if there were errors. We make an exception for consent
3088 // timing out because it's possible the user got distracted. In this case the
3089 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003090 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003091 return status;
3092 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003093 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3094 MYLOGI(
3095 "Did not receive user consent yet."
3096 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003097 const String16 incidentcompanion("incidentcompanion");
3098 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3099 if (ics != nullptr) {
3100 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3101 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3102 consent_callback_.get());
3103 } else {
3104 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3105 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003106 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003107 }
3108
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003109 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003110 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003111 for (int i = 0; i < 3; i++) {
3112 Vibrate(75);
3113 usleep((75 + 50) * 1000);
3114 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003115 }
3116
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003117 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3118 progress_->GetInitialMax());
3119 progress_->Save();
3120 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003121
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003122 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003123
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003124 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003125 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003126 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003127 }
3128
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003129 tombstone_data_.clear();
3130 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003131
Nandana Duttd2f5f082019-01-18 17:13:52 +00003132 return (consent_callback_ != nullptr &&
3133 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3134 ? USER_CONSENT_TIMED_OUT
3135 : RunStatus::OK;
3136}
3137
Paul Chang0d2aad72020-02-13 20:04:03 +08003138void Dumpstate::MaybeTakeEarlyScreenshot() {
3139 if (!options_->do_screenshot || !do_early_screenshot_) {
3140 return;
3141 }
3142
3143 TakeScreenshot();
3144}
3145
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003146void Dumpstate::MaybeSnapshotSystemTrace() {
3147 // If a background system trace is happening and is marked as "suitable for
3148 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3149 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3150 // case that no trace is ongoing, this command is a no-op.
3151 // Note: this should not be enqueued as we need to freeze the trace before
3152 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3153 // the dumpstate's own activity which is irrelevant.
3154 int res = RunCommand(
3155 "SERIALIZE PERFETTO TRACE",
3156 {"perfetto", "--save-for-bugreport"},
3157 CommandOptions::WithTimeout(10)
3158 .DropRoot()
3159 .CloseAllFileDescriptorsOnExec()
3160 .Build());
3161 has_system_trace_ = res == 0;
3162 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3163 // file in the later stages.
3164}
3165
Yohei Yukawa95305b32021-03-09 07:54:27 -08003166void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003167 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3168 for (const auto& service : {"window", "input_method"}) {
3169 RunCommand(
3170 // Empty name because it's not intended to be classified as a bugreport section.
3171 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3172 "", {"cmd", service, "tracing", "save-for-bugreport"},
3173 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3174 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003175}
3176
Paul Changeb4b4642020-05-28 22:05:47 +08003177void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003178 if (calling_uid == AID_SHELL || !CalledByApi()) {
3179 return;
3180 }
3181 if (listener_ != nullptr) {
3182 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3183 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003184 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003185 }
3186}
3187
Jichao Lie89d9c12019-11-21 19:02:51 -08003188void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3189 if (calling_uid == AID_SHELL || !CalledByApi()) {
3190 // No need to get consent for shell triggered dumpstates, or not through
3191 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003192 return;
3193 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003194 consent_callback_ = new ConsentCallback();
3195 const String16 incidentcompanion("incidentcompanion");
3196 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003197 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003198 if (ics != nullptr) {
3199 MYLOGD("Checking user consent via incidentcompanion service\n");
3200 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003201 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003202 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003203 } else {
3204 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3205 }
3206}
3207
Nandana Dutt5c390032019-03-12 10:52:56 +00003208bool Dumpstate::IsUserConsentDenied() const {
3209 return ds.consent_callback_ != nullptr &&
3210 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3211}
3212
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003213bool Dumpstate::CalledByApi() const {
3214 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3215}
3216
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003217void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003218 android::os::UnlinkAndLogOnError(tmp_path_);
3219 android::os::UnlinkAndLogOnError(screenshot_path_);
3220 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003221 if (dump_traces_path != nullptr) {
3222 android::os::UnlinkAndLogOnError(dump_traces_path);
3223 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003224}
3225
Rhed Jao5377d792020-07-16 17:37:39 +08003226void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003227 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003228 return;
3229 }
3230 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003231 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003232}
3233
3234void Dumpstate::ShutdownDumpPool() {
3235 if (dump_pool_) {
Chris Morinbc223142022-02-04 14:17:11 -08003236 dump_pool_.reset();
Rhed Jao5377d792020-07-16 17:37:39 +08003237 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003238 if (zip_entry_tasks_) {
3239 zip_entry_tasks_->run(/* do_cancel = */true);
3240 zip_entry_tasks_ = nullptr;
3241 }
3242}
3243
3244void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3245 const std::string& entry_path) {
3246 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3247 if (!task_cancelled) {
3248 AddZipEntry(entry_name, entry_path);
3249 }
3250 android::os::UnlinkAndLogOnError(entry_path);
3251 };
3252 if (zip_entry_tasks_) {
3253 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3254 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3255 } else {
3256 // Invokes AddZipEntryAndCleanup immediately
3257 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3258 }
Rhed Jao5377d792020-07-16 17:37:39 +08003259}
3260
Nandana Duttd2f5f082019-01-18 17:13:52 +00003261Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3262 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003263 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003264 return USER_CONSENT_DENIED;
3265}
3266
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003267Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003268 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003269 // user consent (unless the caller is Shell).
3270 UserConsentResult consent_result;
3271 if (calling_uid == AID_SHELL) {
3272 consent_result = UserConsentResult::APPROVED;
3273 } else {
3274 consent_result = consent_callback_->getResult();
3275 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003276 if (consent_result == UserConsentResult::UNAVAILABLE) {
3277 // User has not responded yet.
3278 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003279 // Telephony is a fast report type, particularly on user builds where information may be
3280 // more aggressively limited. To give the user time to read the consent dialog, increase the
3281 // timeout.
3282 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3283 : USER_CONSENT_TIMEOUT_MS;
3284 if (elapsed_ms < timeout_ms) {
3285 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003286 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3287 sleep(delay_seconds);
3288 }
3289 consent_result = consent_callback_->getResult();
3290 }
3291 if (consent_result == UserConsentResult::DENIED) {
3292 // User has explicitly denied sharing with the app. To be safe delete the
3293 // internal bugreport & tmp files.
3294 return HandleUserConsentDenied();
3295 }
3296 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003297 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3298 if (copy_succeeded) {
3299 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003300 if (options_->do_screenshot &&
3301 options_->screenshot_fd.get() != -1 &&
3302 !options_->is_screenshot_copied) {
3303 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3304 options_->screenshot_fd.get());
3305 options_->is_screenshot_copied = copy_succeeded;
3306 if (copy_succeeded) {
3307 android::os::UnlinkAndLogOnError(screenshot_path_);
3308 }
3309 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003310 }
3311 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3312 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3313 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3314 // Since we do not have user consent to share the bugreport it does not get
3315 // copied over to the calling app but remains in the internal directory from
3316 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003317 std::string final_path = GetPath(".zip");
3318 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3319 if (copy_succeeded) {
3320 android::os::UnlinkAndLogOnError(path_);
3321 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003322 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3323 }
3324 // Unknown result; must be a programming error.
3325 MYLOGE("Unknown user consent result:%d\n", consent_result);
3326 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003327}
3328
Nandana Duttf02564e2019-02-15 15:24:24 +00003329Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003330 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3331 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3332 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003333 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003334 // When directly running dumpstate binary, the output is not expected to be written
3335 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003336 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003337
3338 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003339 // an app; they are irrelevant here because bugreport is triggered via command line.
3340 // Update Last ID before calling Run().
3341 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003342 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003343 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003344 return status;
3345}
3346
3347/* Main entry point for dumpstate binary. */
3348int run_main(int argc, char* argv[]) {
3349 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003350
3351 switch (status) {
3352 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003353 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003354 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003355 ShowUsage();
3356 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003357 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003358 fprintf(stderr, "Invalid combination of args\n");
3359 ShowUsage();
3360 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003361 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003362 FALLTHROUGH_INTENDED;
3363 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3364 FALLTHROUGH_INTENDED;
3365 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003366 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003367 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003368}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003369
3370// TODO(111441001): Default DumpOptions to sensible values.
3371Dumpstate::Dumpstate(const std::string& version)
3372 : pid_(getpid()),
3373 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003374 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003375 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003376 now_(time(nullptr)),
3377 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003378}
3379
3380Dumpstate& Dumpstate::GetInstance() {
3381 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3382 return singleton_;
3383}
3384
Rhed Jao5377d792020-07-16 17:37:39 +08003385DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3386 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3387 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003388 if (!title_.empty()) {
3389 started_ = Nanotime();
3390 }
3391}
3392
3393DurationReporter::~DurationReporter() {
3394 if (!title_.empty()) {
3395 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003396 if (elapsed >= .5f || verbose_) {
3397 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003398 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003399 if (!logcat_only_) {
3400 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003401 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3402 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003403 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003404 }
3405}
3406
3407const int32_t Progress::kDefaultMax = 5000;
3408
3409Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3410}
3411
3412Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3413 : Progress(initial_max, growth_factor, "") {
3414 progress_ = progress;
3415}
3416
3417Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3418 : initial_max_(initial_max),
3419 progress_(0),
3420 max_(initial_max),
3421 growth_factor_(growth_factor),
3422 n_runs_(0),
3423 average_max_(0),
3424 path_(path) {
3425 if (!path_.empty()) {
3426 Load();
3427 }
3428}
3429
3430void Progress::Load() {
3431 MYLOGD("Loading stats from %s\n", path_.c_str());
3432 std::string content;
3433 if (!android::base::ReadFileToString(path_, &content)) {
3434 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3435 return;
3436 }
3437 if (content.empty()) {
3438 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3439 return;
3440 }
3441 std::vector<std::string> lines = android::base::Split(content, "\n");
3442
3443 if (lines.size() < 1) {
3444 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3445 (int)lines.size(), max_);
3446 return;
3447 }
3448 char* ptr;
3449 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3450 average_max_ = strtol(ptr, nullptr, 10);
3451 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3452 average_max_ > STATS_MAX_AVERAGE) {
3453 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3454 initial_max_ = Progress::kDefaultMax;
3455 } else {
3456 initial_max_ = average_max_;
3457 }
3458 max_ = initial_max_;
3459
3460 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3461}
3462
3463void Progress::Save() {
3464 int32_t total = n_runs_ * average_max_ + progress_;
3465 int32_t runs = n_runs_ + 1;
3466 int32_t average = floor(((float)total) / runs);
3467 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3468 path_.c_str());
3469 if (path_.empty()) {
3470 return;
3471 }
3472
3473 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3474 if (!android::base::WriteStringToFile(content, path_)) {
3475 MYLOGE("Could not save stats on %s\n", path_.c_str());
3476 }
3477}
3478
3479int32_t Progress::Get() const {
3480 return progress_;
3481}
3482
3483bool Progress::Inc(int32_t delta_sec) {
3484 bool changed = false;
3485 if (delta_sec >= 0) {
3486 progress_ += delta_sec;
3487 if (progress_ > max_) {
3488 int32_t old_max = max_;
3489 max_ = floor((float)progress_ * growth_factor_);
3490 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3491 changed = true;
3492 }
3493 }
3494 return changed;
3495}
3496
3497int32_t Progress::GetMax() const {
3498 return max_;
3499}
3500
3501int32_t Progress::GetInitialMax() const {
3502 return initial_max_;
3503}
3504
3505void Progress::Dump(int fd, const std::string& prefix) const {
3506 const char* pr = prefix.c_str();
3507 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3508 dprintf(fd, "%smax: %d\n", pr, max_);
3509 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3510 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3511 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3512 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3513 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3514}
3515
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003516std::string Dumpstate::GetPath(const std::string& suffix) const {
3517 return GetPath(bugreport_internal_dir_, suffix);
3518}
3519
3520std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3521 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3522 name_.c_str(), suffix.c_str());
3523}
3524
3525void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3526 progress_ = std::move(progress);
3527}
3528
3529void for_each_userid(void (*func)(int), const char *header) {
3530 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3531 "for_each_userid(%s)", header);
3532 DurationReporter duration_reporter(title);
3533 if (PropertiesHelper::IsDryRun()) return;
3534
3535 DIR *d;
3536 struct dirent *de;
3537
3538 if (header) printf("\n------ %s ------\n", header);
3539 func(0);
3540
3541 if (!(d = opendir("/data/system/users"))) {
3542 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3543 return;
3544 }
3545
3546 while ((de = readdir(d))) {
3547 int userid;
3548 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3549 continue;
3550 }
3551 func(userid);
3552 }
3553
3554 closedir(d);
3555}
3556
3557static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3558 DIR *d;
3559 struct dirent *de;
3560
3561 if (!(d = opendir("/proc"))) {
3562 printf("Failed to open /proc (%s)\n", strerror(errno));
3563 return;
3564 }
3565
3566 if (header) printf("\n------ %s ------\n", header);
3567 while ((de = readdir(d))) {
3568 if (ds.IsUserConsentDenied()) {
3569 MYLOGE(
3570 "Returning early because user denied consent to share bugreport with calling app.");
3571 closedir(d);
3572 return;
3573 }
3574 int pid;
3575 int fd;
3576 char cmdpath[255];
3577 char cmdline[255];
3578
3579 if (!(pid = atoi(de->d_name))) {
3580 continue;
3581 }
3582
3583 memset(cmdline, 0, sizeof(cmdline));
3584
3585 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3586 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3587 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3588 close(fd);
3589 if (cmdline[0]) {
3590 helper(pid, cmdline, arg);
3591 continue;
3592 }
3593 }
3594
3595 // if no cmdline, a kernel thread has comm
3596 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3597 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3598 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3599 close(fd);
3600 if (cmdline[1]) {
3601 cmdline[0] = '[';
3602 size_t len = strcspn(cmdline, "\f\b\r\n");
3603 cmdline[len] = ']';
3604 cmdline[len+1] = '\0';
3605 }
3606 }
3607 if (!cmdline[0]) {
3608 strcpy(cmdline, "N/A");
3609 }
3610 helper(pid, cmdline, arg);
3611 }
3612
3613 closedir(d);
3614}
3615
3616static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3617 for_each_pid_func *func = (for_each_pid_func*) arg;
3618 func(pid, cmdline);
3619}
3620
3621void for_each_pid(for_each_pid_func func, const char *header) {
3622 std::string title = header == nullptr ? "for_each_pid"
3623 : android::base::StringPrintf("for_each_pid(%s)", header);
3624 DurationReporter duration_reporter(title);
3625 if (PropertiesHelper::IsDryRun()) return;
3626
3627 __for_each_pid(for_each_pid_helper, header, (void *) func);
3628}
3629
3630static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3631 DIR *d;
3632 struct dirent *de;
3633 char taskpath[255];
3634 for_each_tid_func *func = (for_each_tid_func *) arg;
3635
3636 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3637
3638 if (!(d = opendir(taskpath))) {
3639 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3640 return;
3641 }
3642
3643 func(pid, pid, cmdline);
3644
3645 while ((de = readdir(d))) {
3646 if (ds.IsUserConsentDenied()) {
3647 MYLOGE(
3648 "Returning early because user denied consent to share bugreport with calling app.");
3649 closedir(d);
3650 return;
3651 }
3652 int tid;
3653 int fd;
3654 char commpath[255];
3655 char comm[255];
3656
3657 if (!(tid = atoi(de->d_name))) {
3658 continue;
3659 }
3660
3661 if (tid == pid)
3662 continue;
3663
3664 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3665 memset(comm, 0, sizeof(comm));
3666 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3667 strcpy(comm, "N/A");
3668 } else {
3669 char *c;
3670 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3671 close(fd);
3672
3673 c = strrchr(comm, '\n');
3674 if (c) {
3675 *c = '\0';
3676 }
3677 }
3678 func(pid, tid, comm);
3679 }
3680
3681 closedir(d);
3682}
3683
3684void for_each_tid(for_each_tid_func func, const char *header) {
3685 std::string title = header == nullptr ? "for_each_tid"
3686 : android::base::StringPrintf("for_each_tid(%s)", header);
3687 DurationReporter duration_reporter(title);
3688
3689 if (PropertiesHelper::IsDryRun()) return;
3690
3691 __for_each_pid(for_each_tid_helper, header, (void *) func);
3692}
3693
3694void show_wchan(int pid, int tid, const char *name) {
3695 if (PropertiesHelper::IsDryRun()) return;
3696
3697 char path[255];
3698 char buffer[255];
3699 int fd, ret, save_errno;
3700 char name_buffer[255];
3701
3702 memset(buffer, 0, sizeof(buffer));
3703
3704 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3705 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3706 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3707 return;
3708 }
3709
3710 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3711 save_errno = errno;
3712 close(fd);
3713
3714 if (ret < 0) {
3715 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3716 return;
3717 }
3718
3719 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3720 pid == tid ? 0 : 3, "", name);
3721
3722 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3723
3724 return;
3725}
3726
3727// print time in centiseconds
3728static void snprcent(char *buffer, size_t len, size_t spc,
3729 unsigned long long time) {
3730 static long hz; // cache discovered hz
3731
3732 if (hz <= 0) {
3733 hz = sysconf(_SC_CLK_TCK);
3734 if (hz <= 0) {
3735 hz = 1000;
3736 }
3737 }
3738
3739 // convert to centiseconds
3740 time = (time * 100 + (hz / 2)) / hz;
3741
3742 char str[16];
3743
3744 snprintf(str, sizeof(str), " %llu.%02u",
3745 time / 100, (unsigned)(time % 100));
3746 size_t offset = strlen(buffer);
3747 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3748 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3749}
3750
3751// print permille as a percent
3752static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3753 char str[16];
3754
3755 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3756 size_t offset = strlen(buffer);
3757 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3758 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3759}
3760
3761void show_showtime(int pid, const char *name) {
3762 if (PropertiesHelper::IsDryRun()) return;
3763
3764 char path[255];
3765 char buffer[1023];
3766 int fd, ret, save_errno;
3767
3768 memset(buffer, 0, sizeof(buffer));
3769
3770 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3771 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3772 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3773 return;
3774 }
3775
3776 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3777 save_errno = errno;
3778 close(fd);
3779
3780 if (ret < 0) {
3781 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3782 return;
3783 }
3784
3785 // field 14 is utime
3786 // field 15 is stime
3787 // field 42 is iotime
3788 unsigned long long utime = 0, stime = 0, iotime = 0;
3789 if (sscanf(buffer,
3790 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3791 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3792 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3793 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3794 &utime, &stime, &iotime) != 3) {
3795 return;
3796 }
3797
3798 unsigned long long total = utime + stime;
3799 if (!total) {
3800 return;
3801 }
3802
3803 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3804 if (permille > 1000) {
3805 permille = 1000;
3806 }
3807
3808 // try to beautify and stabilize columns at <80 characters
3809 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3810 if ((name[0] != '[') || utime) {
3811 snprcent(buffer, sizeof(buffer), 57, utime);
3812 }
3813 snprcent(buffer, sizeof(buffer), 65, stime);
3814 if ((name[0] != '[') || iotime) {
3815 snprcent(buffer, sizeof(buffer), 73, iotime);
3816 }
3817 if (iotime) {
3818 snprdec(buffer, sizeof(buffer), 79, permille);
3819 }
3820 puts(buffer); // adds a trailing newline
3821
3822 return;
3823}
3824
3825void do_dmesg() {
3826 const char *title = "KERNEL LOG (dmesg)";
3827 DurationReporter duration_reporter(title);
3828 printf("------ %s ------\n", title);
3829
3830 if (PropertiesHelper::IsDryRun()) return;
3831
3832 /* Get size of kernel buffer */
3833 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3834 if (size <= 0) {
3835 printf("Unexpected klogctl return value: %d\n\n", size);
3836 return;
3837 }
3838 char *buf = (char *) malloc(size + 1);
3839 if (buf == nullptr) {
3840 printf("memory allocation failed\n\n");
3841 return;
3842 }
3843 int retval = klogctl(KLOG_READ_ALL, buf, size);
3844 if (retval < 0) {
3845 printf("klogctl failure\n\n");
3846 free(buf);
3847 return;
3848 }
3849 buf[retval] = '\0';
3850 printf("%s\n\n", buf);
3851 free(buf);
3852 return;
3853}
3854
3855void do_showmap(int pid, const char *name) {
3856 char title[255];
3857 char arg[255];
3858
3859 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3860 snprintf(arg, sizeof(arg), "%d", pid);
3861 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3862}
3863
3864int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3865 DurationReporter duration_reporter(title);
3866
3867 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3868
3869 UpdateProgress(WEIGHT_FILE);
3870
3871 return status;
3872}
3873
3874int read_file_as_long(const char *path, long int *output) {
3875 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3876 if (fd < 0) {
3877 int err = errno;
3878 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3879 return -1;
3880 }
3881 char buffer[50];
3882 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3883 if (bytes_read == -1) {
3884 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3885 return -2;
3886 }
3887 if (bytes_read == 0) {
3888 MYLOGE("File %s is empty\n", path);
3889 return -3;
3890 }
3891 *output = atoi(buffer);
3892 return 0;
3893}
3894
3895/* calls skip to gate calling dump_from_fd recursively
3896 * in the specified directory. dump_from_fd defaults to
3897 * dump_file_from_fd above when set to NULL. skip defaults
3898 * to false when set to NULL. dump_from_fd will always be
3899 * called with title NULL.
3900 */
3901int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3902 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3903 DurationReporter duration_reporter(title);
3904 DIR *dirp;
3905 struct dirent *d;
3906 char *newpath = nullptr;
3907 const char *slash = "/";
3908 int retval = 0;
3909
3910 if (!title.empty()) {
3911 printf("------ %s (%s) ------\n", title.c_str(), dir);
3912 }
3913 if (PropertiesHelper::IsDryRun()) return 0;
3914
3915 if (dir[strlen(dir) - 1] == '/') {
3916 ++slash;
3917 }
3918 dirp = opendir(dir);
3919 if (dirp == nullptr) {
3920 retval = -errno;
3921 MYLOGE("%s: %s\n", dir, strerror(errno));
3922 return retval;
3923 }
3924
3925 if (!dump_from_fd) {
3926 dump_from_fd = dump_file_from_fd;
3927 }
3928 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3929 if ((d->d_name[0] == '.')
3930 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3931 || (d->d_name[1] == '\0'))) {
3932 continue;
3933 }
3934 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3935 (d->d_type == DT_DIR) ? "/" : "");
3936 if (!newpath) {
3937 retval = -errno;
3938 continue;
3939 }
3940 if (skip && (*skip)(newpath)) {
3941 continue;
3942 }
3943 if (d->d_type == DT_DIR) {
3944 int ret = dump_files("", newpath, skip, dump_from_fd);
3945 if (ret < 0) {
3946 retval = ret;
3947 }
3948 continue;
3949 }
3950 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3951 if (fd.get() < 0) {
3952 retval = -1;
3953 printf("*** %s: %s\n", newpath, strerror(errno));
3954 continue;
3955 }
3956 (*dump_from_fd)(nullptr, newpath, fd.get());
3957 }
3958 closedir(dirp);
3959 if (!title.empty()) {
3960 printf("\n");
3961 }
3962 return retval;
3963}
3964
3965/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3966 * it's possible to avoid issues where opening the file itself can get
3967 * stuck.
3968 */
3969int dump_file_from_fd(const char *title, const char *path, int fd) {
3970 if (PropertiesHelper::IsDryRun()) return 0;
3971
3972 int flags = fcntl(fd, F_GETFL);
3973 if (flags == -1) {
3974 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3975 return -1;
3976 } else if (!(flags & O_NONBLOCK)) {
3977 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3978 return -1;
3979 }
3980 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3981}
3982
3983int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003984 const CommandOptions& options, bool verbose_duration, int out_fd) {
3985 DurationReporter duration_reporter(title, false /* logcat_only */,
3986 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003987
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003988 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003989
3990 /* TODO: for now we're simplifying the progress calculation by using the
3991 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3992 * where its weight should be much higher proportionally to its timeout.
3993 * Ideally, it should use a options.EstimatedDuration() instead...*/
3994 UpdateProgress(options.Timeout());
3995
3996 return status;
3997}
3998
3999void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004000 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004001 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4002 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4003 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004004 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004005}
4006
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004007static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004008 int s = android_get_control_socket(service);
4009 if (s < 0) {
4010 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4011 return -1;
4012 }
4013 fcntl(s, F_SETFD, FD_CLOEXEC);
4014
4015 // Set backlog to 0 to make sure that queue size will be minimum.
4016 // In Linux, because the minimum queue will be 1, connect() will be blocked
4017 // if the other clients already called connect() and the connection request was not accepted.
4018 if (listen(s, 0) < 0) {
4019 MYLOGE("listen(control socket): %s\n", strerror(errno));
4020 return -1;
4021 }
4022
4023 struct sockaddr addr;
4024 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004025 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004026
4027 // Close socket just after accept(), to make sure that connect() by client will get error
4028 // when the socket is used by the other services.
4029 // There is still a race condition possibility between accept and close, but there is no way
4030 // to close-on-accept atomically.
4031 // See detail; b/123306389#comment25
4032 close(s);
4033
4034 if (fd < 0) {
4035 MYLOGE("accept(control socket): %s\n", strerror(errno));
4036 return -1;
4037 }
4038
4039 return fd;
4040}
4041
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004042// TODO: should call is_valid_output_file and/or be merged into it.
4043void create_parent_dirs(const char *path) {
4044 char *chp = const_cast<char *> (path);
4045
4046 /* skip initial slash */
4047 if (chp[0] == '/')
4048 chp++;
4049
4050 /* create leading directories, if necessary */
4051 struct stat dir_stat;
4052 while (chp && chp[0]) {
4053 chp = strchr(chp, '/');
4054 if (chp) {
4055 *chp = 0;
4056 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4057 MYLOGI("Creating directory %s\n", path);
4058 if (mkdir(path, 0770)) { /* drwxrwx--- */
4059 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4060 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4061 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4062 }
4063 }
4064 *chp++ = '/';
4065 }
4066 }
4067}
4068
4069bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4070 create_parent_dirs(path);
4071
4072 int fd = TEMP_FAILURE_RETRY(open(path,
4073 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4074 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4075 if (fd < 0) {
4076 MYLOGE("%s: %s\n", path, strerror(errno));
4077 return false;
4078 }
4079
4080 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4081 close(fd);
4082 return true;
4083}
4084
4085bool redirect_to_file(FILE* redirect, char* path) {
4086 return _redirect_to_file(redirect, path, O_TRUNC);
4087}
4088
4089bool redirect_to_existing_file(FILE* redirect, char* path) {
4090 return _redirect_to_file(redirect, path, O_APPEND);
4091}
4092
4093void dump_route_tables() {
4094 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4095 if (PropertiesHelper::IsDryRun()) return;
4096 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4097 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4098 FILE* fp = fopen(RT_TABLES_PATH, "re");
4099 if (!fp) {
4100 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4101 return;
4102 }
4103 char table[16];
4104 // Each line has an integer (the table number), a space, and a string (the table name). We only
4105 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4106 // Add a fixed max limit so this doesn't go awry.
4107 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4108 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4109 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4110 }
4111 fclose(fp);
4112}
4113
Li Li830179f2022-01-04 12:53:29 -08004114void dump_frozen_cgroupfs(const char *dir, int level,
4115 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4116 DIR *dirp;
4117 struct dirent *d;
4118 char *newpath = nullptr;
4119
4120 dirp = opendir(dir);
4121 if (dirp == nullptr) {
4122 MYLOGE("%s: %s\n", dir, strerror(errno));
4123 return;
4124 }
4125
4126 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4127 if ((d->d_name[0] == '.')
4128 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4129 || (d->d_name[1] == '\0'))) {
4130 continue;
4131 }
4132 if (d->d_type == DT_DIR) {
4133 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4134 if (!newpath) {
4135 continue;
4136 }
4137 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4138 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4139 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4140 char *freezer = nullptr;
4141 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4142 if (freezer) {
4143 FILE* fp = fopen(freezer, "r");
4144 if (fp != NULL) {
4145 int frozen;
4146 fscanf(fp, "%d", &frozen);
4147 if (frozen > 0) {
4148 dump_files("", newpath, skip_none, dump_from_fd);
4149 }
4150 fclose(fp);
4151 }
4152 free(freezer);
4153 }
4154 }
4155 }
4156 }
4157 closedir(dirp);
4158}
4159
4160void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004161 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4162 DurationReporter duration_reporter("FROZEN CGROUPFS");
4163 if (PropertiesHelper::IsDryRun()) return;
4164 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4165}
4166
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004167void Dumpstate::UpdateProgress(int32_t delta_sec) {
4168 if (progress_ == nullptr) {
4169 MYLOGE("UpdateProgress: progress_ not set\n");
4170 return;
4171 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004172 // This function updates progress related members of the dumpstate and reports
4173 // progress percentage to the bugreport client. Since it could be called by
4174 // different dump tasks at the same time if the parallel run is enabled, a
4175 // mutex lock is necessary here to synchronize the call.
4176 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004177
4178 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004179 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004180
4181 // ...but only notifiy listeners when necessary.
4182 if (!options_->do_progress_updates) return;
4183
4184 int progress = progress_->Get();
4185 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004186 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004187
Nandana Dutt402a8392019-06-14 14:25:13 +01004188 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004189 return;
4190 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004191 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004192
4193 if (control_socket_fd_ >= 0) {
4194 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4195 fsync(control_socket_fd_);
4196 }
4197
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004198 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004199 if (percent % 10 == 0) {
4200 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004201 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004202 } else {
4203 // stderr is ignored on normal invocations, but useful when calling
4204 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004205 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004206 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004207
4208 listener_->onProgress(percent);
4209 }
4210}
4211
4212void Dumpstate::TakeScreenshot(const std::string& path) {
4213 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4214 int status =
4215 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4216 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4217 if (status == 0) {
4218 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4219 } else {
4220 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4221 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004222 if (listener_ != nullptr) {
4223 // Show a visual indication to indicate screenshot is taken via
4224 // IDumpstateListener.onScreenshotTaken()
4225 listener_->onScreenshotTaken(status == 0);
4226 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004227}
4228
4229bool is_dir(const char* pathname) {
4230 struct stat info;
4231 if (stat(pathname, &info) == -1) {
4232 return false;
4233 }
4234 return S_ISDIR(info.st_mode);
4235}
4236
4237time_t get_mtime(int fd, time_t default_mtime) {
4238 struct stat info;
4239 if (fstat(fd, &info) == -1) {
4240 return default_mtime;
4241 }
4242 return info.st_mtime;
4243}