blob: 32e680dfea778c8bd3537f4fc91566b2c5636e12 [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;
Felipe Leme47e9be22016-12-21 15:37:07 -0800123
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100124// Keep in sync with
125// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
126static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
127
128/* Most simple commands have 10 as timeout, so 5 is a good estimate */
129static const int32_t WEIGHT_FILE = 5;
130
131// TODO: temporary variables and functions used during C++ refactoring
132static Dumpstate& ds = Dumpstate::GetInstance();
133static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100134 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800135 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
136 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100137}
138
139// Reasonable value for max stats.
140static const int STATS_MAX_N_RUNS = 1000;
141static const long STATS_MAX_AVERAGE = 100000;
142
143CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
144
Nandana Duttd2f5f082019-01-18 17:13:52 +0000145typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
146
Colin Crossf45fa6b2012-03-26 12:38:26 -0700147/* read before root is shed */
148static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700149static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000150static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800151// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
152// it's often the case that they time out far too quickly for consent with such a hefty dialog for
153// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
154// roughly match full reports' durations.
155static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700156
Felipe Leme1d486fe2016-10-14 18:06:47 -0700157// TODO: variables and functions below should be part of dumpstate object
158
Felipe Leme635ca312016-01-05 14:23:02 -0800159static std::set<std::string> mount_points;
160void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800161
Todd Poynor2a83daa2013-11-22 15:44:22 -0800162#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700163#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700164#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800165
Felipe Lemee82a27d2016-01-05 13:35:44 -0800166#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700167#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700168#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700169#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800170#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100171#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
172#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800173#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900174#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800175#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700176#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800177#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900178#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700179#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000180#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700181#define CGROUPFS_DIR "/sys/fs/cgroup"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700182
Narayan Kamath8f788292017-05-25 13:20:39 +0100183// TODO(narayan): Since this information has to be kept in sync
184// with tombstoned, we should just put it in a common header.
185//
186// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100187static const std::string TOMBSTONE_DIR = "/data/tombstones/";
188static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
189static const std::string ANR_DIR = "/data/anr/";
190static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700191
Felipe Lemee844a9d2016-09-21 15:01:39 -0700192// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000193
Nandana Dutt5c390032019-03-12 10:52:56 +0000194#define RETURN_IF_USER_DENIED_CONSENT() \
195 if (ds.IsUserConsentDenied()) { \
196 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
197 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
198 }
199
200// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
201// if consent is found to be denied.
202#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
203 RETURN_IF_USER_DENIED_CONSENT(); \
204 func_ptr(__VA_ARGS__); \
205 RETURN_IF_USER_DENIED_CONSENT();
206
Rhed Jao5377d792020-07-16 17:37:39 +0800207// Runs func_ptr, and logs a duration report after it's finished.
208#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
209 { \
210 DurationReporter duration_reporter_in_macro(log_title); \
211 func_ptr(__VA_ARGS__); \
212 }
213
214// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
215// is output after a slow function is finished.
216#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
217 RETURN_IF_USER_DENIED_CONSENT(); \
218 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
219 RETURN_IF_USER_DENIED_CONSENT();
220
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800221#define WAIT_TASK_WITH_CONSENT_CHECK(task_name, pool_ptr) \
222 RETURN_IF_USER_DENIED_CONSENT(); \
223 pool_ptr->waitForTask(task_name); \
224 RETURN_IF_USER_DENIED_CONSENT();
225
Sahana Raof35ed432019-07-12 10:47:52 +0100226static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
227
Rhed Jao5377d792020-07-16 17:37:39 +0800228// Names of parallel tasks, they are used for the DumpPool to identify the dump
229// task and the log title of the duration report.
230static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800231static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
232static const std::string DUMP_HALS_TASK = "DUMP HALS";
233static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800234static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao5377d792020-07-16 17:37:39 +0800235
Nandana Dutt979388e2018-11-30 16:48:55 +0000236namespace android {
237namespace os {
238namespace {
239
240static int Open(std::string path, int flags, mode_t mode = 0) {
241 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
242 if (fd == -1) {
243 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
244 }
245 return fd;
246}
247
mhasank2d75c442020-06-11 15:05:25 -0700248static int OpenForWrite(std::string path) {
249 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
250 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
251}
Nandana Dutt979388e2018-11-30 16:48:55 +0000252
253static int OpenForRead(std::string path) {
254 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
255}
256
257bool CopyFile(int in_fd, int out_fd) {
258 char buf[4096];
259 ssize_t byte_count;
260 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
261 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
262 return false;
263 }
264 }
265 return (byte_count != -1);
266}
267
268static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000269 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000270
271 // Obtain a handle to the source file.
272 android::base::unique_fd in_fd(OpenForRead(input_file));
273 if (out_fd != -1 && in_fd.get() != -1) {
274 if (CopyFile(in_fd.get(), out_fd)) {
275 return true;
276 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000277 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000278 }
279 return false;
280}
281
Nandana Duttd2f5f082019-01-18 17:13:52 +0000282static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000283 if (file.empty()) {
284 return false;
285 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000286 if (unlink(file.c_str())) {
287 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000288 return false;
289 }
290 return true;
291}
Nandana Dutt979388e2018-11-30 16:48:55 +0000292
Nikita Ioffea325a572019-05-16 19:49:47 +0100293int64_t GetModuleMetadataVersion() {
294 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
295 if (binder == nullptr) {
296 MYLOGE("Failed to retrieve package_native service");
297 return 0L;
298 }
299 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
300 std::string package_name;
301 auto status = package_service->getModuleMetadataPackageName(&package_name);
302 if (!status.isOk()) {
303 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
304 return 0L;
305 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100306 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100307 int64_t version_code;
308 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
309 &version_code);
310 if (!status.isOk()) {
311 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
312 return 0L;
313 }
314 return version_code;
315}
316
mhasank2d75c442020-06-11 15:05:25 -0700317static bool PathExists(const std::string& path) {
318 struct stat sb;
319 return stat(path.c_str(), &sb) == 0;
320}
321
322static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
323 if (input_file == output_file) {
324 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
325 output_file.c_str());
326 return false;
327 }
328 else if (PathExists(output_file)) {
329 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
330 return false;
331 }
332
333 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
334 android::base::unique_fd out_fd(OpenForWrite(output_file));
335 return CopyFileToFd(input_file, out_fd.get());
336}
337
Nandana Dutt979388e2018-11-30 16:48:55 +0000338} // namespace
339} // namespace os
340} // namespace android
341
Felipe Leme678727a2016-09-21 17:22:11 -0700342static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800343 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800344 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
345 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
346}
347static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
348 int out_fd) {
349 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700350}
351static int DumpFile(const std::string& title, const std::string& path) {
352 return ds.DumpFile(title, path);
353}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800354
Felipe Lemee844a9d2016-09-21 15:01:39 -0700355// Relative directory (inside the zip) for all files copied as-is into the bugreport.
356static const std::string ZIP_ROOT_DIR = "FS";
357
Vishnu Naire97d6122018-01-18 13:58:56 -0800358static const std::string kProtoPath = "proto/";
359static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700360static const std::string kDumpstateBoardFiles[] = {
361 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700362 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700363};
364static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
365
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700366static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700367static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700368
Felipe Lemef0292972016-11-22 13:57:05 -0800369static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
370
Narayan Kamath8f788292017-05-25 13:20:39 +0100371/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100372 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800373 * The returned vector is sorted by the mtimes of the dumps with descending
374 * order. If |limit_by_mtime| is set, the vector only contains files that
375 * were written in the last 30 minutes.
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,
378 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700379 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100380 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
381
Narayan Kamathbd863722017-06-01 18:50:12 +0100382 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100383
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700384 if (dump_dir == nullptr) {
385 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700386 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700387 }
388
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700389 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100390 struct dirent* entry = nullptr;
391 while ((entry = readdir(dump_dir.get()))) {
392 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100393 continue;
394 }
395
Narayan Kamathbd863722017-06-01 18:50:12 +0100396 const std::string base_name(entry->d_name);
397 if (base_name.find(file_prefix) != 0) {
398 continue;
399 }
400
401 const std::string abs_path = dir_path + base_name;
402 android::base::unique_fd fd(
403 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
404 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700405 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100406 break;
407 }
408
409 struct stat st = {};
410 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700411 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100412 continue;
413 }
414
Narayan Kamath3f31b632018-02-22 19:42:36 +0000415 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100416 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100417 continue;
418 }
419
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700420 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700421 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800422 if (!dump_data.empty()) {
423 std::sort(dump_data.begin(), dump_data.end(),
424 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
425 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100426
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700427 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100428}
429
Narayan Kamathbd863722017-06-01 18:50:12 +0100430static bool AddDumps(const std::vector<DumpData>::const_iterator start,
431 const std::vector<DumpData>::const_iterator end,
432 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100433 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100434 for (auto it = start; it != end; ++it) {
435 const std::string& name = it->name;
436 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100437 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100438
439 // Seek to the beginning of the file before dumping any data. A given
440 // DumpData entry might be dumped multiple times in the report.
441 //
442 // For example, the most recent ANR entry is dumped to the body of the
443 // main entry and it also shows up as a separate entry in the bugreport
444 // ZIP file.
445 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
446 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
447 strerror(errno));
448 }
449
Narayan Kamath8f788292017-05-25 13:20:39 +0100450 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800451 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100452 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100453 }
454 } else {
455 dump_file_from_fd(type_name, name.c_str(), fd);
456 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100457 }
458
459 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700460}
461
Felipe Leme635ca312016-01-05 14:23:02 -0800462// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700463void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800464 char path[PATH_MAX];
465
466 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
467 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700468 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800469 char linkname[PATH_MAX];
470 ssize_t r = readlink(path, linkname, PATH_MAX);
471 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800472 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800473 return;
474 }
475 linkname[r] = '\0';
476
477 if (mount_points.find(linkname) == mount_points.end()) {
478 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700479 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700480 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800481 mount_points.insert(linkname);
482 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800483 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800484 }
485 }
486}
487
488void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700489 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700490 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800491 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800492 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700493 for_each_pid(do_mountinfo, nullptr);
494 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800495}
496
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700497static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
498{
499 DIR *d;
500 struct dirent *de;
501 char path[PATH_MAX];
502
503 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700504 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700505 return;
506 }
507
508 while ((de = readdir(d))) {
509 if (de->d_type != DT_LNK) {
510 continue;
511 }
512 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700513 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700514 }
515
516 closedir(d);
517}
518
Mark Salyzyn326842f2015-04-30 09:49:41 -0700519static bool skip_not_stat(const char *path) {
520 static const char stat[] = "/stat";
521 size_t len = strlen(path);
522 if (path[len - 1] == '/') { /* Directory? */
523 return false;
524 }
525 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
526}
527
Felipe Leme4c2d6632016-09-28 14:32:00 -0700528static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800529 return false;
530}
531
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700532unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700533
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800534//
535// stat offsets
536// Name units description
537// ---- ----- -----------
538// read I/Os requests number of read I/Os processed
539#define __STAT_READ_IOS 0
540// read merges requests number of read I/Os merged with in-queue I/O
541#define __STAT_READ_MERGES 1
542// read sectors sectors number of sectors read
543#define __STAT_READ_SECTORS 2
544// read ticks milliseconds total wait time for read requests
545#define __STAT_READ_TICKS 3
546// write I/Os requests number of write I/Os processed
547#define __STAT_WRITE_IOS 4
548// write merges requests number of write I/Os merged with in-queue I/O
549#define __STAT_WRITE_MERGES 5
550// write sectors sectors number of sectors written
551#define __STAT_WRITE_SECTORS 6
552// write ticks milliseconds total wait time for write requests
553#define __STAT_WRITE_TICKS 7
554// in_flight requests number of I/Os currently in flight
555#define __STAT_IN_FLIGHT 8
556// io_ticks milliseconds total time this block device has been active
557#define __STAT_IO_TICKS 9
558// time_in_queue milliseconds total wait time for all requests
559#define __STAT_IN_QUEUE 10
560#define __STAT_NUMBER_FIELD 11
561//
562// read I/Os, write I/Os
563// =====================
564//
565// These values increment when an I/O request completes.
566//
567// read merges, write merges
568// =========================
569//
570// These values increment when an I/O request is merged with an
571// already-queued I/O request.
572//
573// read sectors, write sectors
574// ===========================
575//
576// These values count the number of sectors read from or written to this
577// block device. The "sectors" in question are the standard UNIX 512-byte
578// sectors, not any device- or filesystem-specific block size. The
579// counters are incremented when the I/O completes.
580#define SECTOR_SIZE 512
581//
582// read ticks, write ticks
583// =======================
584//
585// These values count the number of milliseconds that I/O requests have
586// waited on this block device. If there are multiple I/O requests waiting,
587// these values will increase at a rate greater than 1000/second; for
588// example, if 60 read requests wait for an average of 30 ms, the read_ticks
589// field will increase by 60*30 = 1800.
590//
591// in_flight
592// =========
593//
594// This value counts the number of I/O requests that have been issued to
595// the device driver but have not yet completed. It does not include I/O
596// requests that are in the queue but not yet issued to the device driver.
597//
598// io_ticks
599// ========
600//
601// This value counts the number of milliseconds during which the device has
602// had I/O requests queued.
603//
604// time_in_queue
605// =============
606//
607// This value counts the number of milliseconds that I/O requests have waited
608// on this block device. If there are multiple I/O requests waiting, this
609// value will increase as the product of the number of milliseconds times the
610// number of requests waiting (see "read ticks" above for an example).
611#define S_TO_MS 1000
612//
613
Mark Salyzyn326842f2015-04-30 09:49:41 -0700614static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800615 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700616 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700617 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700618 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700619 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700620 getline(&buffer, &i, fp);
621 fclose(fp);
622 if (!buffer) {
623 return -errno;
624 }
625 i = strlen(buffer);
626 while ((i > 0) && (buffer[i - 1] == '\n')) {
627 buffer[--i] = '\0';
628 }
629 if (!*buffer) {
630 free(buffer);
631 return 0;
632 }
633 z = true;
634 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800635 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700636 if (fields[i] != 0) {
637 z = false;
638 }
639 }
640 if (z) { /* never accessed */
641 free(buffer);
642 return 0;
643 }
644
Wei Wang509bb5d2017-06-09 14:42:12 -0700645 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
646 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700647 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700648
649 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
650 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
651 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700652 free(buffer);
653
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800654 if (fields[__STAT_IO_TICKS]) {
655 unsigned long read_perf = 0;
656 unsigned long read_ios = 0;
657 if (fields[__STAT_READ_TICKS]) {
658 unsigned long long divisor = fields[__STAT_READ_TICKS]
659 * fields[__STAT_IO_TICKS];
660 read_perf = ((unsigned long long)SECTOR_SIZE
661 * fields[__STAT_READ_SECTORS]
662 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
663 / divisor;
664 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
665 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
666 / divisor;
667 }
668
669 unsigned long write_perf = 0;
670 unsigned long write_ios = 0;
671 if (fields[__STAT_WRITE_TICKS]) {
672 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
673 * fields[__STAT_IO_TICKS];
674 write_perf = ((unsigned long long)SECTOR_SIZE
675 * fields[__STAT_WRITE_SECTORS]
676 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
677 / divisor;
678 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 }
682
683 unsigned queue = (fields[__STAT_IN_QUEUE]
684 + (fields[__STAT_IO_TICKS] >> 1))
685 / fields[__STAT_IO_TICKS];
686
687 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700688 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 -0800689 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700690 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 -0800691 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800692 }
693
694 /* bugreport timeout factor adjustment */
695 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
696 worst_write_perf = write_perf;
697 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700698 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700699 return 0;
700}
701
Yao Chenbe3bbc12018-01-17 16:31:10 -0800702static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
703
Tom Cherryf4472f32020-08-05 09:31:17 -0700704// Returns the actual readable size of the given buffer or -1 on error.
705static long logcat_buffer_readable_size(const std::string& buffer) {
706 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
707 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
708 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
709
710 return android_logger_get_log_readable_size(logger);
711}
712
713// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800714static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
715 unsigned long timeout_ms = 0;
716 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700717 long readable_size = logcat_buffer_readable_size(buffer);
718 if (readable_size > 0) {
719 // Engineering margin is ten-fold our guess.
720 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
721 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800722 }
723 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700724}
725
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800726// Opens a socket and returns its file descriptor.
727static int open_socket(const char* service);
728
Nandana Duttd2f5f082019-01-18 17:13:52 +0000729Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
730}
731
732android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
733 std::lock_guard<std::mutex> lock(lock_);
734 result_ = APPROVED;
735 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800736
737 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
738 // consent is granted.
739 if (ds.options_->is_screenshot_copied) {
740 return android::binder::Status::ok();
741 }
742
743 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
744 !ds.do_early_screenshot_) {
745 return android::binder::Status::ok();
746 }
747
748 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
749 ds.options_->screenshot_fd.get());
750 ds.options_->is_screenshot_copied = copy_succeeded;
751 if (copy_succeeded) {
752 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
753 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000754 return android::binder::Status::ok();
755}
756
757android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
758 std::lock_guard<std::mutex> lock(lock_);
759 result_ = DENIED;
760 MYLOGW("User denied consent to share bugreport\n");
761 return android::binder::Status::ok();
762}
763
764UserConsentResult Dumpstate::ConsentCallback::getResult() {
765 std::lock_guard<std::mutex> lock(lock_);
766 return result_;
767}
768
769uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800770 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000771}
772
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700773void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700774 std::string build, fingerprint, radio, bootloader, network;
775 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700776
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700777 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
778 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700779 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
780 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
781 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700782 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700783
Felipe Lemed8b94e52016-12-08 10:21:44 -0800784 printf("========================================================\n");
785 printf("== dumpstate: %s\n", date);
786 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700787
Felipe Lemed8b94e52016-12-08 10:21:44 -0800788 printf("\n");
789 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700790 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800791 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
792 printf("Bootloader: %s\n", bootloader.c_str());
793 printf("Radio: %s\n", radio.c_str());
794 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100795 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
796 if (module_metadata_version != 0) {
797 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
798 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100799 printf("SDK extension versions [r=%s s=%s]\n",
800 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
801 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700802
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800804 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800806 printf("Uptime: ");
807 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
808 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800809 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800810 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
811 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000812 options_->args.c_str(), options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800813 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800814}
815
Felipe Leme24b66ee2016-06-16 10:55:26 -0700816// List of file extensions that can cause a zip file attachment to be rejected by some email
817// service providers.
818static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
819 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
820 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
821 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
822};
823
Vishnu Naire97d6122018-01-18 13:58:56 -0800824status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
825 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700826 if (!IsZipping()) {
827 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
828 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800829 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800830 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700831 std::string valid_name = entry_name;
832
833 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700834 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700835 if (idx != std::string::npos) {
836 std::string extension = entry_name.substr(idx);
837 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
838 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
839 valid_name = entry_name + ".renamed";
840 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
841 }
842 }
843
Felipe Leme6fe9db62016-02-12 09:04:16 -0800844 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
845 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700846 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
847 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700848 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700849 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700850 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800851 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800852 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000853 bool finished_entry = false;
854 auto finish_entry = [this, &finished_entry] {
855 if (!finished_entry) {
856 // This should only be called when we're going to return an earlier error,
857 // which would've been logged. This may imply the file is already corrupt
858 // and any further logging from FinishEntry is more likely to mislead than
859 // not.
860 this->zip_writer_->FinishEntry();
861 }
862 };
863 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800864 auto start = std::chrono::steady_clock::now();
865 auto end = start + timeout;
866 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800867
Felipe Leme770410d2016-01-26 17:07:14 -0800868 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800869 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 if (timeout.count() > 0) {
871 // lambda to recalculate the timeout.
872 auto time_left_ms = [end]() {
873 auto now = std::chrono::steady_clock::now();
874 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
875 return std::max(diff.count(), 0LL);
876 };
877
878 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
879 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000880 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
881 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800882 return -errno;
883 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000884 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 entry_name.c_str(), strerror(errno), timeout.count());
886 return TIMED_OUT;
887 }
888 }
889
Zach Riggle22200402016-08-18 01:01:24 -0400890 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800891 if (bytes_read == 0) {
892 break;
893 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800894 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800895 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800896 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700897 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800898 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700899 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800901 }
902 }
903
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700904 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000905 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700906 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700907 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800908 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800909 }
910
Vishnu Naire97d6122018-01-18 13:58:56 -0800911 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912}
913
Felipe Leme1d486fe2016-10-14 18:06:47 -0700914bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
915 android::base::unique_fd fd(
916 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700917 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800918 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919 return false;
920 }
921
Vishnu Naire97d6122018-01-18 13:58:56 -0800922 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800923}
924
925/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700926static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800927 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800928}
929
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930void Dumpstate::AddDir(const std::string& dir, bool recursive) {
931 if (!IsZipping()) {
932 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800933 return;
934 }
Felipe Leme678727a2016-09-21 17:22:11 -0700935 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800936 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700937 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800938}
939
Felipe Leme1d486fe2016-10-14 18:06:47 -0700940bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
941 if (!IsZipping()) {
942 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
943 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800944 return false;
945 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800946 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700947 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700948 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700949 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700950 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800951 return false;
952 }
953
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700954 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700955 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700956 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700957 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800958 return false;
959 }
960
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700962 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700963 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800964 return false;
965 }
966
967 return true;
968}
969
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800970static void DoKmsg() {
971 struct stat st;
972 if (!stat(PSTORE_LAST_KMSG, &st)) {
973 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
974 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
975 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
976 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
977 } else {
978 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
979 DumpFile("LAST KMSG", "/proc/last_kmsg");
980 }
981}
982
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800983static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800984 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800985 RunCommand(
986 "KERNEL LOG",
987 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
988 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
989}
990
Nandana Duttdb379fa2019-10-09 16:54:41 +0100991static void DoSystemLogcat(time_t since) {
992 char since_str[80];
993 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
994
995 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
996 RunCommand("SYSTEM LOG",
997 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
998 since_str},
999 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1000}
1001
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001002static void DoRadioLogcat() {
1003 unsigned long timeout_ms = logcat_timeout({"radio"});
1004 RunCommand(
1005 "RADIO LOG",
1006 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1007 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1008}
1009
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001010static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001011 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001012 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1013 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001014 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001015 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001016 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1017 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001018 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001019 RunCommand(
1020 "EVENT LOG",
1021 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001022 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001023 timeout_ms = logcat_timeout({"stats"});
1024 RunCommand(
1025 "STATS LOG",
1026 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001027 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001028 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001029
1030 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1031
1032 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001033 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1034 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001035}
1036
Mike Ma5c267872019-08-21 11:31:34 -07001037static void DumpIncidentReport() {
1038 if (!ds.IsZipping()) {
1039 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1040 return;
1041 }
Mike Ma5c267872019-08-21 11:31:34 -07001042 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1043 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1044 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1045 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1046 if (fd < 0) {
1047 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1048 return;
1049 }
1050 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1051 bool empty = 0 == lseek(fd, 0, SEEK_END);
1052 if (!empty) {
1053 // Use a different name from "incident.proto"
1054 // /proto/incident.proto is reserved for incident service dump
1055 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001056 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1057 path);
1058 } else {
1059 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001060 }
Mike Ma5c267872019-08-21 11:31:34 -07001061}
1062
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001063static void MaybeAddSystemTraceToZip() {
1064 // This function copies into the .zip the system trace that was snapshotted
1065 // by the early call to MaybeSnapshotSystemTrace(), if any background
1066 // tracing was happening.
1067 if (!ds.IsZipping()) {
1068 MYLOGD("Not dumping system trace because it's not a zipped bugreport\n");
1069 return;
1070 }
1071 if (!ds.has_system_trace_) {
1072 // No background trace was happening at the time dumpstate was invoked.
1073 return;
1074 }
1075 ds.AddZipEntry(
1076 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1077 SYSTEM_TRACE_SNAPSHOT);
1078 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1079}
1080
Sunny Goyal35949782019-11-19 15:54:36 -08001081static void DumpVisibleWindowViews() {
1082 if (!ds.IsZipping()) {
1083 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1084 return;
1085 }
1086 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1087 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1088 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1089 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1090 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1091 if (fd < 0) {
1092 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1093 return;
1094 }
1095 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1096 CommandOptions::WithTimeout(120).Build());
1097 bool empty = 0 == lseek(fd, 0, SEEK_END);
1098 if (!empty) {
1099 ds.AddZipEntry("visible_windows.zip", path);
1100 } else {
1101 MYLOGW("Failed to dump visible windows\n");
1102 }
1103 unlink(path.c_str());
1104}
1105
Jayachandran Ca94c7172017-06-10 15:08:12 -07001106static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001107 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1108 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001109 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001110 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001111 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1112 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1113 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1114 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001115}
1116
David Andersond9ba4752018-12-11 18:26:59 -08001117static void DumpDynamicPartitionInfo() {
1118 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1119 return;
1120 }
1121
1122 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001123 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001124}
1125
Narayan Kamath8f788292017-05-25 13:20:39 +01001126static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1127 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1128 anr_traces_dir.c_str());
1129
1130 // If we're here, dump_traces_path will always be a temporary file
1131 // (created with mkostemp or similar) that contains dumps taken earlier
1132 // on in the process.
1133 if (dump_traces_path != nullptr) {
1134 if (add_to_zip) {
1135 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1136 } else {
1137 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1138 dump_traces_path);
1139 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1140 }
1141
1142 const int ret = unlink(dump_traces_path);
1143 if (ret == -1) {
1144 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1145 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001146 }
1147 }
1148
Narayan Kamathbd863722017-06-01 18:50:12 +01001149 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001150 if (ds.anr_data_.size() > 0) {
1151 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001152 "VM TRACES AT LAST ANR", add_to_zip);
1153
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001154 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1155 // it will be present in the body of the main entry if |add_to_zip| == false.
1156 //
1157 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001158 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001159 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001160 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001161 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1162 }
1163}
1164
1165static void AddAnrTraceFiles() {
1166 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1167
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001168 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001169
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001170 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001171
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001172 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1173
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001174 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001175 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001176 int i = 0;
1177 while (true) {
1178 const std::string slow_trace_path =
1179 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1180 if (stat(slow_trace_path.c_str(), &st)) {
1181 // No traces file at this index, done with the files.
1182 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001183 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001184 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1185 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001186 }
1187}
1188
Wei Wang509bb5d2017-06-09 14:42:12 -07001189static void DumpBlockStatFiles() {
1190 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001191
Wei Wang1dc1ef52017-06-12 11:28:37 -07001192 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1193
1194 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001195 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1196 return;
1197 }
1198
1199 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001200 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001201 if ((d->d_name[0] == '.')
1202 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1203 || (d->d_name[1] == '\0'))) {
1204 continue;
1205 }
1206 const std::string new_path =
1207 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1208 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1209 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1210 printf("\n");
1211 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001212 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001213}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001214
1215static void DumpPacketStats() {
1216 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001217}
1218
1219static void DumpIpAddrAndRules() {
1220 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1221 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1222 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1223 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1224 RunCommand("IP RULES", {"ip", "rule", "show"});
1225 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1226}
1227
Nandana Dutt5c390032019-03-12 10:52:56 +00001228static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1229 std::chrono::milliseconds timeout,
1230 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001231 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001232 sp<android::IServiceManager> sm = defaultServiceManager();
1233 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001234 Vector<String16> args;
1235 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001236 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1237 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001238 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001239 std::string path(title);
1240 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001241 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001242 if (PropertiesHelper::IsDryRun()) {
1243 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1244 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1245 } else {
1246 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1247 if (status == OK) {
1248 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1249 std::chrono::duration<double> elapsed_seconds;
1250 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1251 service == String16("meminfo")) {
1252 // Use a longer timeout for meminfo, since 30s is not always enough.
1253 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1254 /* as_proto = */ false, elapsed_seconds,
1255 bytes_written);
1256 } else {
1257 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1258 /* as_proto = */ false, elapsed_seconds,
1259 bytes_written);
1260 }
1261 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1262 bool dump_complete = (status == OK);
1263 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001264 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001265 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001266
1267 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1268 std::chrono::steady_clock::now() - start);
1269 if (elapsed_duration > timeout) {
1270 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1271 elapsed_duration.count());
1272 break;
1273 }
1274 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001275 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001276}
1277
Vishnu Nair64afc022018-02-01 15:29:34 -08001278static void RunDumpsysText(const std::string& title, int priority,
1279 std::chrono::milliseconds timeout,
1280 std::chrono::milliseconds service_timeout) {
1281 DurationReporter duration_reporter(title);
1282 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1283 fsync(STDOUT_FILENO);
1284 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1285}
1286
1287/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001288static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1289 std::chrono::milliseconds timeout,
1290 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001291 DurationReporter duration_reporter(title);
1292 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1293 fsync(STDOUT_FILENO);
1294 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1295 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001296
1297 RETURN_IF_USER_DENIED_CONSENT();
1298
1299 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1300 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001301}
1302
Nandana Dutt5c390032019-03-12 10:52:56 +00001303static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1304 std::chrono::milliseconds timeout,
1305 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001306 if (!ds.IsZipping()) {
1307 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001308 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001309 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001310 sp<android::IServiceManager> sm = defaultServiceManager();
1311 Dumpsys dumpsys(sm.get());
1312 Vector<String16> args;
1313 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1314 DurationReporter duration_reporter(title);
1315
1316 auto start = std::chrono::steady_clock::now();
1317 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1318 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001319 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001320 std::string path(kProtoPath);
1321 path.append(String8(service).c_str());
1322 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1323 path.append("_CRITICAL");
1324 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1325 path.append("_HIGH");
1326 }
1327 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001328 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001329 if (status == OK) {
1330 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1331 bool dumpTerminated = (status == OK);
1332 dumpsys.stopDumpThread(dumpTerminated);
1333 }
1334 ZipWriter::FileEntry file_entry;
1335 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001336
1337 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1338 std::chrono::steady_clock::now() - start);
1339 if (elapsed_duration > timeout) {
1340 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1341 elapsed_duration.count());
1342 break;
1343 }
1344 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001345 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001346}
1347
Nandana Dutta7db6342018-11-21 14:53:34 +00001348// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001349static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001350 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1351 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001352
1353 RETURN_IF_USER_DENIED_CONSENT();
1354
1355 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1356 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001357}
1358
1359// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001360static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001361 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1362 // high priority. Reduce timeout once they are able to dump in a shorter time or
1363 // moved to a parallel task.
1364 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1365 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001366
1367 RETURN_IF_USER_DENIED_CONSENT();
1368
1369 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1370 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001371}
1372
1373// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001374static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001375 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001376
1377 RETURN_IF_USER_DENIED_CONSENT();
1378
1379 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1380 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001381}
1382
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001383/*
1384 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1385 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1386 * if it's not running in the parallel task.
1387 */
1388static void DumpHals(int out_fd = STDOUT_FILENO) {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001389 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001390 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Steven Morelandd3646e02020-09-23 17:26:33 +00001391 CommandOptions::WithTimeout(60).AsRootIfAvailable().Build(),
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001392 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001393 return;
1394 }
Yifan Hong30528a22020-08-07 18:24:06 -07001395 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001396 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1397 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001398
Steven Moreland44cd9482018-01-04 16:24:13 -08001399 using android::hidl::manager::V1_0::IServiceManager;
1400 using android::hardware::defaultServiceManager;
1401
1402 sp<IServiceManager> sm = defaultServiceManager();
1403 if (sm == nullptr) {
1404 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1405 return;
1406 }
1407
1408 auto ret = sm->list([&](const auto& interfaces) {
1409 for (const std::string& interface : interfaces) {
1410 std::string cleanName = interface;
1411 std::replace_if(cleanName.begin(),
1412 cleanName.end(),
1413 [](char c) {
1414 return !isalnum(c) &&
1415 std::string("@-_:.").find(c) == std::string::npos;
1416 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001417 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001418
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001419 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001420 {
1421 auto fd = android::base::unique_fd(
1422 TEMP_FAILURE_RETRY(open(path.c_str(),
1423 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1424 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1425 if (fd < 0) {
1426 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1427 continue;
1428 }
1429 RunCommandToFd(fd,
1430 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001431 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001432 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1433
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001434 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001435 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001436 if (!empty) {
1437 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1438 path);
1439 } else {
1440 unlink(path.c_str());
1441 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001442 }
1443 });
1444
1445 if (!ret.isOk()) {
1446 MYLOGE("Could not list hals from hwservicemanager.\n");
1447 }
1448}
1449
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001450static void DumpExternalFragmentationInfo() {
1451 struct stat st;
1452 if (stat("/proc/buddyinfo", &st) != 0) {
1453 MYLOGE("Unable to dump external fragmentation info\n");
1454 return;
1455 }
1456
1457 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1458 std::ifstream ifs("/proc/buddyinfo");
1459 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1460 for (std::string line; std::getline(ifs, line);) {
1461 std::smatch match_results;
1462 if (std::regex_match(line, match_results, unusable_index_regex)) {
1463 std::stringstream free_pages(std::string{match_results[3]});
1464 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1465 std::istream_iterator<int>());
1466
1467 int total_free_pages = 0;
1468 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1469 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1470 }
1471
1472 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1473 match_results[2].str().c_str());
1474
1475 int usable_free_pages = total_free_pages;
1476 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1477 auto unusable_index = (total_free_pages - usable_free_pages) /
1478 static_cast<double>(total_free_pages);
1479 printf(" %5.3f", unusable_index);
1480 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1481 }
1482
1483 printf("\n");
1484 }
1485 }
1486 printf("\n");
1487}
1488
mhasankd451a472020-05-26 18:02:39 -07001489static void DumpstateLimitedOnly() {
1490 // Trimmed-down version of dumpstate to only include a whitelisted
1491 // set of logs (system log, event log, and system server / system app
1492 // crashes, and networking logs). See b/136273873 and b/138459828
1493 // for context.
1494 DurationReporter duration_reporter("DUMPSTATE");
1495 unsigned long timeout_ms;
1496 // calculate timeout
1497 timeout_ms = logcat_timeout({"main", "system", "crash"});
1498 RunCommand("SYSTEM LOG",
1499 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1500 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1501 timeout_ms = logcat_timeout({"events"});
1502 RunCommand(
1503 "EVENT LOG",
1504 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1505 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1506
1507 printf("========================================================\n");
1508 printf("== Networking Service\n");
1509 printf("========================================================\n");
1510
1511 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1512 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001513 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1514 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001515
1516 printf("========================================================\n");
1517 printf("== Dropbox crashes\n");
1518 printf("========================================================\n");
1519
1520 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1521 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1522
1523 printf("========================================================\n");
1524 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1525 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1526 printf("========================================================\n");
1527 printf("== dumpstate: done (id %d)\n", ds.id_);
1528 printf("========================================================\n");
1529}
1530
Rhed Jaoe017f982020-07-21 17:58:41 +08001531/*
1532 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1533 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1534 * if it's not running in the parallel task.
1535 */
1536static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1537 dprintf(out_fd, "========================================================\n");
1538 dprintf(out_fd, "== Checkins\n");
1539 dprintf(out_fd, "========================================================\n");
1540
1541 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1542 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1543 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1544 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1545 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1546 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1547}
1548
1549/*
1550 * Runs dumpsys on activity service to dump all application activities, services
1551 * and providers in the device.
1552 *
1553 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1554 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1555 * if it's not running in the parallel task.
1556 */
1557static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1558 dprintf(out_fd, "========================================================\n");
1559 dprintf(out_fd, "== Running Application Activities\n");
1560 dprintf(out_fd, "========================================================\n");
1561
1562 // The following dumpsys internally collects output from running apps, so it can take a long
1563 // time. So let's extend the timeout.
1564
1565 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1566
1567 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1568
1569 dprintf(out_fd, "========================================================\n");
1570 dprintf(out_fd, "== Running Application Services (platform)\n");
1571 dprintf(out_fd, "========================================================\n");
1572
1573 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1574 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1575
1576 dprintf(out_fd, "========================================================\n");
1577 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1578 dprintf(out_fd, "========================================================\n");
1579
1580 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1581 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1582
1583 dprintf(out_fd, "========================================================\n");
1584 dprintf(out_fd, "== Running Application Providers (platform)\n");
1585 dprintf(out_fd, "========================================================\n");
1586
1587 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001588 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001589
1590 dprintf(out_fd, "========================================================\n");
1591 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1592 dprintf(out_fd, "========================================================\n");
1593
1594 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1595 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1596}
1597
Nandana Dutt5c390032019-03-12 10:52:56 +00001598// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1599// via the consent they are shown. Ignores other errors that occur while running various
1600// commands. The consent checking is currently done around long running tasks, which happen to
1601// be distributed fairly evenly throughout the function.
1602static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001603 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001604
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001605 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1606 if (ds.dump_pool_) {
1607 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1608 // drop root user. Restarts it with two threads for the parallel run.
1609 ds.dump_pool_->start(/* thread_counts = */2);
1610
1611 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1612 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1613 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaoe017f982020-07-21 17:58:41 +08001614 ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001615 }
1616
Nandana Dutt5c390032019-03-12 10:52:56 +00001617 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1618 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1619 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001620 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001621 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001622 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001623 DumpFile("MEMORY INFO", "/proc/meminfo");
1624 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001625 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001626
1627 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1628
Sunny Goyal35949782019-11-19 15:54:36 -08001629 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1630
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001631 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1632 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1633 DumpFile("SLAB INFO", "/proc/slabinfo");
1634 DumpFile("ZONEINFO", "/proc/zoneinfo");
1635 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1636 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001637 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001638
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001639 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1640 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001641
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001642 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001643 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001644
1645 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1646 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001647
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001648 if (ds.dump_pool_) {
1649 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1650 } else {
1651 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1652 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001653
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001654 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001655 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001656 struct stat s;
1657 if (stat("/proc/modules", &s) != 0) {
1658 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1659 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001660 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001661 RunCommand("MODULES INFO",
1662 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1663 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1664 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001665 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001666
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001667 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001668 DoKernelLogcat();
1669 } else {
1670 do_dmesg();
1671 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001672
Felipe Lemef0292972016-11-22 13:57:05 -08001673 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001674
1675 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1676
Jeff Brown1dc94e32014-09-11 14:15:27 -07001677 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001678 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001679
Jack Yu5a6b2e22020-08-14 18:13:35 +08001680 /* Dump Nfc NCI logs */
1681 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001682
Paul Chang0d2aad72020-02-13 20:04:03 +08001683 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001684 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001685 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001686 }
1687
Felipe Lemee184f662016-10-27 10:04:47 -07001688 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001689
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001690 MaybeAddSystemTraceToZip();
1691
Narayan Kamath8f788292017-05-25 13:20:39 +01001692 // NOTE: tombstones are always added as separate entries in the zip archive
1693 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001694 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001695 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001696 if (!tombstones_dumped) {
1697 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001698 }
1699
Jayachandran Ca94c7172017-06-10 15:08:12 -07001700 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001701
Chenbo Feng276a3b62018-08-07 11:44:49 -07001702 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1703
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001704 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001705
Jayachandran Ca94c7172017-06-10 15:08:12 -07001706 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001707
1708 dump_route_tables();
1709
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001710 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1711 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1712 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001713
Nandana Dutt5c390032019-03-12 10:52:56 +00001714 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001715
Chiachang Wang668ede42021-05-17 17:14:20 +08001716 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1717 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1718 // dump with priority parameters to dump high priority information.
1719 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1720 CommandOptions::WithTimeout(10).Build());
1721
Elliott Hughes23ccc622017-02-28 10:14:22 -08001722 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001723
Jin Qianf334d662017-10-10 14:41:37 -07001724 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001725
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001726 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001727
Colin Crossf45fa6b2012-03-26 12:38:26 -07001728 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001729 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1730 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1731
1732 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1733 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1734 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1735 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1736 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001737
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001738 /* Add window and surface trace files. */
1739 if (!PropertiesHelper::IsUserBuild()) {
1740 ds.AddDir(WMTRACE_DATA_DIR, false);
1741 }
1742
Yifan Hongd90cc652020-02-08 16:52:02 -08001743 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1744
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001745 if (ds.dump_pool_) {
1746 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1747 } else {
1748 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1749 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001750
Steven Moreland7440ddb2016-12-15 16:13:39 -08001751 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001752 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1753 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001754 // su does not exist on user builds, so try running without it.
1755 // This way any implementations of vril-dump that do not require
1756 // root can run on user builds.
1757 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001758 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001759 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001760 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001761 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001762 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001763 }
1764
Felipe Lemed8b94e52016-12-08 10:21:44 -08001765 printf("========================================================\n");
1766 printf("== Android Framework Services\n");
1767 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001768
Nandana Dutt5c390032019-03-12 10:52:56 +00001769 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001770
Jack He91ff2fe2021-02-18 18:23:43 -08001771 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1772 ds.AddDir("/data/misc/bluetooth/logs", true);
1773
Rhed Jaoe017f982020-07-21 17:58:41 +08001774 if (ds.dump_pool_) {
1775 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
1776 } else {
1777 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1778 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001779
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001780 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001781
Adrian Roos8b397ab2017-04-04 16:35:44 -07001782 printf("========================================================\n");
1783 printf("== Dropbox crashes\n");
1784 printf("========================================================\n");
1785
1786 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1787 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1788
Felipe Lemed8b94e52016-12-08 10:21:44 -08001789 printf("========================================================\n");
1790 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1791 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1792 printf("========================================================\n");
1793 printf("== dumpstate: done (id %d)\n", ds.id_);
1794 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001795
1796 printf("========================================================\n");
1797 printf("== Obtaining statsd metadata\n");
1798 printf("========================================================\n");
1799 // This differs from the usual dumpsys stats, which is the stats report data.
1800 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001801
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001802 // Add linker configuration directory
1803 ds.AddDir(LINKERCONFIG_DIR, true);
1804
Li Li2eedd412021-06-30 15:11:53 -07001805 /* Dump cgroupfs */
1806 ds.AddDir(CGROUPFS_DIR, true);
1807
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001808 if (ds.dump_pool_) {
1809 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1810 } else {
1811 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1812 DumpIncidentReport);
1813 }
Mike Ma5c267872019-08-21 11:31:34 -07001814
Nandana Dutt5c390032019-03-12 10:52:56 +00001815 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001816}
1817
Nandana Dutt5c390032019-03-12 10:52:56 +00001818/*
1819 * Dumps state for the default case; drops root after it's no longer necessary.
1820 *
1821 * Returns RunStatus::OK if everything went fine.
1822 * Returns RunStatus::ERROR if there was an error.
1823 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1824 * with the caller.
1825 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001826Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001827 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1828 // buffer.
1829 DoLogcat();
1830 // Capture timestamp after first logcat to use in next logcat
1831 time_t logcat_ts = time(nullptr);
1832
Nandana Dutt4be45d12018-09-26 15:04:23 +01001833 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao5377d792020-07-16 17:37:39 +08001834 if (dump_pool_) {
1835 RETURN_IF_USER_DENIED_CONSENT();
1836 // One thread is enough since we only need to enqueue DumpTraces here.
1837 dump_pool_->start(/* thread_counts = */1);
1838
1839 // DumpTraces takes long time, post it to the another thread in the
1840 // pool, if pool is available
1841 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1842 } else {
1843 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1844 &dump_traces_path);
1845 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001846
1847 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001848 if (!PropertiesHelper::IsDryRun()) {
1849 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1850 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1851 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001852
1853 ds.AddDir(RECOVERY_DIR, true);
1854 ds.AddDir(RECOVERY_DATA_DIR, true);
1855 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1856 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1857 if (!PropertiesHelper::IsUserBuild()) {
1858 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1859 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001860 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001861 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001862 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001863 add_mountinfo();
1864 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001865 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001866 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001867
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001868 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001869 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1870
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001871 // Dump IPsec stats. No keys are exposed here.
1872 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1873
Nandana Dutt4be45d12018-09-26 15:04:23 +01001874 // Run ss as root so we can see socket marks.
1875 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1876
1877 // Run iotop as root to show top 100 IO threads
1878 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1879
Erick Reyese68df822019-02-11 14:46:36 -08001880 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001881 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1882 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001883
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001884 DumpFile("PSI cpu", "/proc/pressure/cpu");
1885 DumpFile("PSI memory", "/proc/pressure/memory");
1886 DumpFile("PSI io", "/proc/pressure/io");
1887
Rhed Jao5377d792020-07-16 17:37:39 +08001888 if (dump_pool_) {
1889 RETURN_IF_USER_DENIED_CONSENT();
1890 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1891
1892 // Current running thread in the pool is the root user also. Shutdown
1893 // the pool and restart later to ensure all threads in the pool could
1894 // drop the root user.
1895 dump_pool_->shutdown();
1896 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001897 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001898 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001899 }
1900
Nandana Dutt5c390032019-03-12 10:52:56 +00001901 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001902 Dumpstate::RunStatus status = dumpstate();
1903 // Capture logcat since the last time we did it.
1904 DoSystemLogcat(logcat_ts);
1905 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001906}
1907
Rhed Jaob5685b32020-08-14 17:19:17 +08001908// Common states for telephony and wifi which are needed to be collected before
1909// dumpstate drop the root user.
1910static void DumpstateRadioAsRoot() {
1911 DumpIpTablesAsRoot();
1912 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1913}
1914
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001915// This method collects common dumpsys for telephony and wifi. Typically, wifi
1916// reports are fine to include all information, but telephony reports on user
1917// builds need to strip some content (see DumpstateTelephonyOnly).
1918static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001919 // We need to be picky about some stuff for telephony reports on user builds.
1920 if (!include_sensitive_info) {
1921 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1922 DoRadioLogcat();
1923 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001924 // DumpHals takes long time, post it to the another thread in the pool,
1925 // if pool is available.
1926 if (ds.dump_pool_) {
1927 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1928 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001929 // Contains various system properties and process startup info.
1930 do_dmesg();
1931 // Logs other than the radio buffer may contain package/component names and potential PII.
1932 DoLogcat();
1933 // Too broad for connectivity problems.
1934 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001935 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1936 if (ds.dump_pool_) {
1937 ds.dump_pool_->waitForTask(DUMP_HALS_TASK);
1938 } else {
1939 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1940 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001941 }
1942
Jayachandran Ca94c7172017-06-10 15:08:12 -07001943 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001944 DumpIpAddrAndRules();
1945 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001946 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1947 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001948}
1949
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001950// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1951// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1952// for what can be included on user builds: all reported information MUST directly relate to
1953// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1954// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1955// names are not), and MUST NOT contain logs of user application traffic.
1956// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001957static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001958 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001959
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001960 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001961
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001962 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001963
Rhed Jaob5685b32020-08-14 17:19:17 +08001964 DumpstateRadioAsRoot();
1965 if (!DropRootUser()) {
1966 return;
1967 }
1968
1969 // Starts thread pool after the root user is dropped, and two additional threads
1970 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1971 if (ds.dump_pool_) {
1972 ds.dump_pool_->start(/*thread_counts =*/2);
1973
1974 // DumpstateBoard takes long time, post it to the another thread in the pool,
1975 // if pool is available.
1976 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1977 }
1978
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001979 DumpstateRadioCommon(include_sensitive_info);
1980
1981 if (include_sensitive_info) {
1982 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1983 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1984 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1985 // way.
1986 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1987 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001988
1989 printf("========================================================\n");
1990 printf("== Android Framework Services\n");
1991 printf("========================================================\n");
1992
Vishnu Nair652cc802017-11-30 15:18:30 -08001993 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1994 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001995 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1996 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001997 if (include_sensitive_info) {
1998 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1999 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
2000 SEC_TO_MSEC(10));
2001 } else {
2002 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2003 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2004 // give a higher timeout as well.
2005 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2006 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2007 }
2008 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002009 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2010 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002011 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002012 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2013 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002014 if (include_sensitive_info) {
2015 // Contains raw IP addresses, omit from reports on user builds.
2016 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2017 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2018 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2019 SEC_TO_MSEC(10));
2020 // Contains package/component names, omit from reports on user builds.
2021 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2022 SEC_TO_MSEC(10));
2023 // Contains package names, but should be relatively simple to remove them (also contains
2024 // UIDs already), omit from reports on user builds.
2025 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2026 SEC_TO_MSEC(10));
2027 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002028
2029 printf("========================================================\n");
2030 printf("== Running Application Services\n");
2031 printf("========================================================\n");
2032
2033 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2034
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002035 if (include_sensitive_info) {
2036 printf("========================================================\n");
2037 printf("== Running Application Services (non-platform)\n");
2038 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002039
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002040 // Contains package/component names and potential PII, omit from reports on user builds.
2041 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2042 // carrier_config dumpsys instead.
2043 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2044 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002045
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002046 printf("========================================================\n");
2047 printf("== Checkins\n");
2048 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002049
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002050 // Contains package/component names, omit from reports on user builds.
2051 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2052 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002053
2054 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002055 printf("== dumpstate: done (id %d)\n", ds.id_);
2056 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002057
2058 if (ds.dump_pool_) {
2059 ds.dump_pool_->waitForTask(DUMP_BOARD_TASK);
2060 } else {
2061 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2062 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002063}
2064
mukesh agrawal253dad42018-01-23 21:59:59 -08002065// This method collects dumpsys for wifi debugging only
2066static void DumpstateWifiOnly() {
2067 DurationReporter duration_reporter("DUMPSTATE");
2068
Rhed Jaob5685b32020-08-14 17:19:17 +08002069 DumpstateRadioAsRoot();
2070 if (!DropRootUser()) {
2071 return;
2072 }
2073
2074 // Starts thread pool after the root user is dropped. Only one additional
2075 // thread is needed for DumpHals in the DumpstateRadioCommon.
2076 if (ds.dump_pool_) {
2077 ds.dump_pool_->start(/*thread_counts =*/1);
2078 }
2079
mukesh agrawal253dad42018-01-23 21:59:59 -08002080 DumpstateRadioCommon();
2081
2082 printf("========================================================\n");
2083 printf("== Android Framework Services\n");
2084 printf("========================================================\n");
2085
2086 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
2088 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2089 SEC_TO_MSEC(10));
2090
2091 printf("========================================================\n");
2092 printf("== dumpstate: done (id %d)\n", ds.id_);
2093 printf("========================================================\n");
2094}
2095
Nandana Duttcf419a72019-03-14 10:40:17 +00002096Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002097 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002098 const size_t buf_size = temp_file_pattern.length() + 1;
2099 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2100 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2101
2102 // Create a new, empty file to receive all trace dumps.
2103 //
2104 // TODO: This can be simplified once we remove support for the old style
2105 // dumps. We can have a file descriptor passed in to dump_traces instead
2106 // of creating a file, closing it and then reopening it again.
2107 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2108 if (fd < 0) {
2109 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002110 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002111 }
2112
2113 // Nobody should have access to this temporary file except dumpstate, but we
2114 // temporarily grant 'read' to 'others' here because this file is created
2115 // when tombstoned is still running as root, but dumped after dropping. This
2116 // can go away once support for old style dumping has.
2117 const int chmod_ret = fchmod(fd, 0666);
2118 if (chmod_ret < 0) {
2119 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002120 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002121 }
2122
2123 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2124 if (proc.get() == nullptr) {
2125 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002126 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002127 }
2128
2129 // Number of times process dumping has timed out. If we encounter too many
2130 // failures, we'll give up.
2131 int timeout_failures = 0;
2132 bool dalvik_found = false;
2133
2134 const std::set<int> hal_pids = get_interesting_hal_pids();
2135
2136 struct dirent* d;
2137 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002138 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002139 int pid = atoi(d->d_name);
2140 if (pid <= 0) {
2141 continue;
2142 }
2143
2144 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2145 std::string exe;
2146 if (!android::base::Readlink(link_name, &exe)) {
2147 continue;
2148 }
2149
2150 bool is_java_process;
2151 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2152 // Don't bother dumping backtraces for the zygote.
2153 if (IsZygote(pid)) {
2154 continue;
2155 }
2156
2157 dalvik_found = true;
2158 is_java_process = true;
2159 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2160 is_java_process = false;
2161 } else {
2162 // Probably a native process we don't care about, continue.
2163 continue;
2164 }
2165
2166 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2167 if (timeout_failures == 3) {
2168 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2169 break;
2170 }
2171
2172 const uint64_t start = Nanotime();
2173 const int ret = dump_backtrace_to_file_timeout(
2174 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2175 is_java_process ? 5 : 20, fd);
2176
2177 if (ret == -1) {
2178 // For consistency, the header and footer to this message match those
2179 // dumped by debuggerd in the success case.
2180 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2181 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2182 dprintf(fd, "---- end %d ----", pid);
2183 timeout_failures++;
2184 continue;
2185 }
2186
2187 // We've successfully dumped stack traces, reset the failure count
2188 // and write a summary of the elapsed time to the file and continue with the
2189 // next process.
2190 timeout_failures = 0;
2191
2192 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2193 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2194 }
2195
2196 if (!dalvik_found) {
2197 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2198 }
2199
Nandana Duttcf419a72019-03-14 10:40:17 +00002200 *path = file_name_buf.release();
2201 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002202}
2203
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002204static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2205 const Dumpstate::BugreportMode bugreport_mode) {
2206 switch (bugreport_mode) {
2207 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2208 return dumpstate_hal_hidl::DumpstateMode::FULL;
2209 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2210 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2211 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2212 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2213 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2214 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2215 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2216 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2217 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2218 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2219 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2220 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2221 }
2222 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2223}
2224
2225static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2226 const Dumpstate::BugreportMode bugreport_mode) {
2227 switch (bugreport_mode) {
2228 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2229 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2230 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2231 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2232 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2233 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2234 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2235 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2236 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2237 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2238 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2239 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2240 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2241 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2242 }
2243 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2244}
2245
2246static void DoDumpstateBoardHidl(
2247 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2248 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2249 const Dumpstate::BugreportMode bugreport_mode,
2250 const size_t timeout_sec) {
2251
2252 using ScopedNativeHandle =
2253 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2254 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2255 [](native_handle_t* handle) {
2256 // we don't close file handle's here
2257 // via native_handle_close(handle)
2258 // instead we let dumpstate_fds close the file handles when
2259 // dumpstate_fds gets destroyed
2260 native_handle_delete(handle);
2261 });
2262 if (handle == nullptr) {
2263 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2264 return;
2265 }
2266
2267 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2268 handle.get()->data[i] = dumpstate_fds[i].get();
2269 }
2270
2271 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2272 // implement just 1.0.
2273 const char* descriptor_to_kill;
2274 using DumpstateBoardTask = std::packaged_task<bool()>;
2275 DumpstateBoardTask dumpstate_board_task;
2276 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2277 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2278 if (dumpstate_hal != nullptr) {
2279 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2280
2281 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2282 GetDumpstateHalModeHidl(bugreport_mode);
2283
2284 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2285 dumpstate_board_task =
2286 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2287 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2288 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2289 SEC_TO_MSEC(timeout_sec));
2290 if (!status.isOk()) {
2291 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2292 return false;
2293 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2294 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2295 dumpstate_hal_hidl::toString(status).c_str());
2296 return false;
2297 }
2298 return true;
2299 });
2300 } else {
2301 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2302
2303 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2304 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2305 ::android::hardware::Return<void> status =
2306 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2307 if (!status.isOk()) {
2308 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2309 return false;
2310 }
2311 return true;
2312 });
2313 }
2314 auto result = dumpstate_board_task.get_future();
2315 std::thread(std::move(dumpstate_board_task)).detach();
2316
2317 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2318 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2319 if (!android::base::SetProperty(
2320 "ctl.interface_restart",
2321 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2322 MYLOGE("Couldn't restart dumpstate HAL\n");
2323 }
2324 }
2325 // Wait some time for init to kill dumpstate vendor HAL
2326 constexpr size_t killing_timeout_sec = 10;
2327 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2328 MYLOGE(
2329 "killing dumpstateBoard timed out after %zus, continue and "
2330 "there might be racing in content\n",
2331 killing_timeout_sec);
2332 }
2333}
2334
2335static void DoDumpstateBoardAidl(
2336 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2337 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2338 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2339 MYLOGI("Using IDumpstateDevice AIDL HAL");
2340
2341 const char* descriptor_to_kill;
2342 using DumpstateBoardTask = std::packaged_task<bool()>;
2343 DumpstateBoardTask dumpstate_board_task;
2344 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2345 GetDumpstateHalModeAidl(bugreport_mode);
2346
2347 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2348 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2349 timeout_sec]() -> bool {
2350 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2351
2352 if (!status.isOk()) {
2353 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2354 return false;
2355 }
2356 return true;
2357 });
2358 auto result = dumpstate_board_task.get_future();
2359 std::thread(std::move(dumpstate_board_task)).detach();
2360
2361 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2362 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2363 if (!android::base::SetProperty(
2364 "ctl.interface_restart",
2365 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2366 MYLOGE("Couldn't restart dumpstate HAL\n");
2367 }
2368 }
2369 // Wait some time for init to kill dumpstate vendor HAL
2370 constexpr size_t killing_timeout_sec = 10;
2371 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2372 MYLOGE(
2373 "killing dumpstateBoard timed out after %zus, continue and "
2374 "there might be racing in content\n",
2375 killing_timeout_sec);
2376 }
2377}
2378
2379static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2380 const std::string aidl_instance_name =
2381 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2382
2383 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2384 return nullptr;
2385 }
2386
2387 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2388
2389 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2390}
2391
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002392void Dumpstate::DumpstateBoard(int out_fd) {
2393 dprintf(out_fd, "========================================================\n");
2394 dprintf(out_fd, "== Board\n");
2395 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002396
Felipe Leme6f674ae2016-11-18 17:10:33 -08002397 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002398 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002399 return;
2400 }
2401
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002402 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002403 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002404 * set to true and unmount it after invoking dumpstateBoard_* methods.
2405 * This is to enable debug builds to not have debugfs mounted during runtime.
2406 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002407 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002408 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002409 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002410 if (mount_debugfs) {
2411 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2412 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002413 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002414 }
2415
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002416 std::vector<std::string> paths;
2417 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002418 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002419 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2420 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002421 remover.emplace_back(android::base::make_scope_guard(
2422 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002423 }
Jie Song9fbfad02017-06-20 16:29:42 -07002424
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002425 // get dumpstate HAL AIDL implementation
2426 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2427 GetDumpstateBoardAidlService());
2428 if (dumpstate_hal_handle_aidl == nullptr) {
2429 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2430 }
2431
2432 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2433 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2434 if (dumpstate_hal_handle_aidl == nullptr) {
2435 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2436 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2437 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2438 }
2439 }
2440
2441 // if neither HIDL nor AIDL implementation found, then return
2442 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2443 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002444 return;
2445 }
2446
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002447 // this is used to hold the file descriptors and when this variable goes out of scope
2448 // the file descriptors are closed
2449 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002450
Nandana Dutt5c390032019-03-12 10:52:56 +00002451 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002452 for (size_t i = 0; i < paths.size(); i++) {
2453 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2454
2455 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2456 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2457 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2458 if (fd < 0) {
2459 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2460 return;
2461 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002462
2463 dumpstate_fds.emplace_back(fd.release());
2464 // we call fd.release() here to make sure "fd" does not get closed
2465 // after "fd" goes out of scope after this block.
2466 // "fd" will be closed when "dumpstate_fds" goes out of scope
2467 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002468 }
2469
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002470 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2471 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2472 // will kill the HAL and grab whatever it dumped in time.
2473 constexpr size_t timeout_sec = 30;
Wei Wang587eac92018-04-05 12:17:20 -07002474
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002475 if (dumpstate_hal_handle_aidl != nullptr) {
2476 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2477 timeout_sec);
2478 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2479 // run HIDL HAL only if AIDL HAL not found
2480 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2481 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002482 }
2483
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002484 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002485 auto keep_debugfs_mounted =
2486 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2487 if (keep_debugfs_mounted.empty())
2488 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002489 }
2490
Wei Wang587eac92018-04-05 12:17:20 -07002491 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2492 for (size_t i = 0; i < paths.size(); i++) {
2493 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002494 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2495 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002496 file_sizes[i] = -1;
2497 continue;
2498 }
2499 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002500 }
2501
2502 for (size_t i = 0; i < paths.size(); i++) {
2503 if (file_sizes[i] == -1) {
2504 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002505 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002506 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002507 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002508 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002509 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002510 remover[i].Disable();
2511 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2512 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002513 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002514}
2515
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002516static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002517 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002518 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2519 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002520 " -h: display this help message\n"
2521 " -b: play sound file instead of vibrate, at beginning of job\n"
2522 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002523 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002524 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002525 " -s: write zipped file to control socket (for init)\n"
2526 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002527 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002528 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002529 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002530 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002531 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002532 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002533}
2534
Wei Liuf87959e2016-08-26 14:51:42 -07002535static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002536 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002537}
2538
Felipe Leme1d486fe2016-10-14 18:06:47 -07002539bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002540 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2541 if (zip_entry_tasks_) {
2542 zip_entry_tasks_->run(/* do_cancel = */false);
2543 }
2544
Felipe Leme9a523ae2016-10-20 15:10:33 -07002545 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002546 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002547 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002548 // Final timestamp
2549 char date[80];
2550 time_t the_real_now_please_stand_up = time(nullptr);
2551 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002552 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002553 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002554
Felipe Leme9a523ae2016-10-20 15:10:33 -07002555 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002556 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002557 return false;
2558 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002559 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002560 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002561 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002562 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002563
Felipe Leme0f3fb202016-06-10 17:10:53 -07002564 // Add log file (which contains stderr output) to zip...
2565 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002566 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002567 MYLOGE("Failed to add dumpstate log to .zip file\n");
2568 return false;
2569 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002570 // TODO: Should truncate the existing file.
2571 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002572 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2573 return false;
2574 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002575 fprintf(stderr, "\n");
2576
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002577 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002578 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002579 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002580 return false;
2581 }
2582
Felipe Leme1d486fe2016-10-14 18:06:47 -07002583 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2584 ds.zip_file.reset(nullptr);
2585
Felipe Lemee9d2c542016-11-15 11:48:26 -08002586 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002587 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002588
Felipe Leme1e9edc62015-12-21 16:02:13 -08002589 return true;
2590}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002591
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002592static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2593 // clang-format off
2594 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2595 "--receiver-foreground", "--receiver-include-background", "-a", action};
2596 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002597
2598 am.insert(am.end(), args.begin(), args.end());
2599
Felipe Leme8d2410e2017-02-08 09:46:08 -08002600 RunCommand("", am,
2601 CommandOptions::WithTimeout(20)
2602 .Log("Sending broadcast: '%s'\n")
2603 .Always()
2604 .DropRoot()
2605 .RedirectStderr()
2606 .Build());
2607}
2608
Felipe Leme35b8cf12017-02-10 15:47:29 -08002609static void Vibrate(int duration_ms) {
2610 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002611 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2612 "oneshot", std::to_string(duration_ms)};
2613 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002614 CommandOptions::WithTimeout(10)
2615 .Log("Vibrate: '%s'\n")
2616 .Always()
2617 .Build());
2618 // clang-format on
2619}
2620
Nandana Dutt979388e2018-11-30 16:48:55 +00002621static void MaybeResolveSymlink(std::string* path) {
2622 std::string resolved_path;
2623 if (android::base::Readlink(*path, &resolved_path)) {
2624 *path = resolved_path;
2625 }
2626}
2627
Nandana Dutt4be45d12018-09-26 15:04:23 +01002628/*
2629 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002630 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002631 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002632static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002633 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2634
Nandana Dutt4be45d12018-09-26 15:04:23 +01002635 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2636 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002637 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002638 char date[80];
2639 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2640 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002641
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002642 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002643 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002644 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002645 ds.base_name_ += "-wifi";
2646 }
2647
Paul Chang0d2aad72020-02-13 20:04:03 +08002648 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002649 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002650 }
2651 ds.tmp_path_ = ds.GetPath(".tmp");
2652 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2653
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002654 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002655 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002656 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002657 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002658 "Bugreport dir: [%s] "
2659 "Base name: [%s] "
2660 "Suffix: [%s] "
2661 "Log path: [%s] "
2662 "Temporary path: [%s] "
2663 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002664 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2665 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002666
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002667 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2668 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2669 create_parent_dirs(ds.path_.c_str());
2670 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2671 if (ds.zip_file == nullptr) {
2672 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2673 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002674 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002675 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2676 ds.AddTextZipEntry("version.txt", ds.version_);
2677 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002678}
2679
2680/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002681 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002682 * printing zipped file status, etc.
2683 */
2684static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002685 bool do_text_file = !ds.FinishZipFile();
2686 if (do_text_file) {
2687 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002688 }
mhasank2d75c442020-06-11 15:05:25 -07002689
2690 std::string final_path = ds.path_;
2691 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002692 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002693 android::os::CopyFileToFile(ds.path_, final_path);
2694 }
2695
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002696 if (ds.options_->stream_to_socket) {
2697 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2698 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002699 if (do_text_file) {
2700 dprintf(ds.control_socket_fd_,
2701 "FAIL:could not create zip file, check %s "
2702 "for more details\n",
2703 ds.log_path_.c_str());
2704 } else {
mhasank2d75c442020-06-11 15:05:25 -07002705 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002706 }
2707 }
2708}
2709
Nandana Dutt4be45d12018-09-26 15:04:23 +01002710
Nandana Dutt58d72e22018-11-16 10:30:48 +00002711static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2712 switch (mode) {
2713 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2714 return "BUGREPORT_FULL";
2715 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2716 return "BUGREPORT_INTERACTIVE";
2717 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2718 return "BUGREPORT_REMOTE";
2719 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2720 return "BUGREPORT_WEAR";
2721 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2722 return "BUGREPORT_TELEPHONY";
2723 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2724 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002725 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2726 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002727 }
2728}
2729
Paul Changf59c2b72020-03-10 02:08:55 +08002730static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2731 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002732 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2733 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002734 options->bugreport_mode = mode;
2735 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002736 switch (mode) {
2737 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002738 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002739 break;
2740 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002741 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002742 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002743 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002744 break;
2745 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002746 options->do_vibrate = false;
2747 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002748 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002749 break;
2750 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002751 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002752 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002753 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002754 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002755 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002756 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002757 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002758 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002759 break;
2760 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002761 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002762 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002763 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002764 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2765 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002766 }
2767}
2768
Nandana Dutt58d72e22018-11-16 10:30:48 +00002769static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002770 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002771 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002772 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002773 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002774 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002775 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002776 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002777 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002778 options.do_progress_updates, options.bugreport_fd.get(),
2779 options.bugreport_mode_string.c_str(),
2780 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002781}
2782
Nandana Dutt54dbd672019-01-11 12:58:05 +00002783void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2784 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002785 const android::base::unique_fd& screenshot_fd_in,
2786 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002787 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2788 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2789 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002790
Paul Changf59c2b72020-03-10 02:08:55 +08002791 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002792}
2793
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002794Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2795 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002796 int c;
mhasankd451a472020-05-26 18:02:39 -07002797 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002798 switch (c) {
2799 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002800 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002801 case 's': stream_to_socket = true; break;
2802 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002803 case 'v': show_header_only = true; break;
2804 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002805 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002806 case 'P': do_progress_updates = true; break;
2807 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002808 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002809 case 'V':
2810 case 'd':
2811 case 'z':
2812 // compatibility no-op
2813 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002814 case 'w':
2815 // This was already processed
2816 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002817 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002818 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002819 break;
2820 default:
2821 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002822 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002823 break;
2824 // clang-format on
2825 }
2826 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002827
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002828 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002829 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002830 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002831 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002832 }
2833 }
2834
2835 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2836 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002837
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002838 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002839}
2840
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002841bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002842 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002843 return false;
2844 }
2845
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002846 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002847 return false;
2848 }
2849
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002850 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002851 return false;
2852 }
2853 return true;
2854}
2855
Nandana Dutt197661d2018-11-16 16:40:21 +00002856void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2857 options_ = std::move(options);
2858}
2859
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002860void Dumpstate::Initialize() {
2861 /* gets the sequential id */
2862 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2863 id_ = ++last_id;
2864 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2865}
2866
Nandana Duttd2f5f082019-01-18 17:13:52 +00002867Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2868 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002869 if (listener_ != nullptr) {
2870 switch (status) {
2871 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002872 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002873 break;
2874 case Dumpstate::RunStatus::HELP:
2875 break;
2876 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002877 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002878 break;
2879 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002880 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2881 break;
2882 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2883 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2884 break;
2885 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2886 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002887 break;
2888 }
2889 }
2890 return status;
2891}
2892
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002893void Dumpstate::Cancel() {
2894 CleanupTmpFiles();
2895 android::os::UnlinkAndLogOnError(log_path_);
2896 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2897 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2898 kDumpstateBoardFiles[i]);
2899 }
2900 tombstone_data_.clear();
2901 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002902
2903 // Instead of shutdown the pool, we delete temporary files directly since
2904 // shutdown blocking the call.
2905 if (dump_pool_) {
2906 dump_pool_->deleteTempFiles();
2907 }
2908 if (zip_entry_tasks_) {
2909 zip_entry_tasks_->run(/*do_cancel =*/ true);
2910 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002911}
2912
Nandana Dutt979388e2018-11-30 16:48:55 +00002913/*
2914 * Dumps relevant information to a bugreport based on the given options.
2915 *
2916 * The bugreport can be dumped to a file or streamed to a socket.
2917 *
2918 * How dumping to file works:
2919 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2920 * stderr is redirected a log file.
2921 *
2922 * The temporary bugreport is then populated via printfs, dumping contents of files and
2923 * output of commands to stdout.
2924 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002925 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002926 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002927 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002928 *
mhasank2d75c442020-06-11 15:05:25 -07002929 * Bugreports are first generated in a local directory and later copied to the caller's fd
2930 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002931 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002932Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2933 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002934 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002935 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002936 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002937 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 return RunStatus::INVALID_INPUT;
2939 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002940 /* set as high priority, and protect from OOM killer */
2941 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002942
Felipe Lemed071c682016-10-20 16:48:00 -07002943 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002944 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002945 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002946 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002947 } else {
2948 /* fallback to kernels <= 2.6.35 */
2949 oom_adj = fopen("/proc/self/oom_adj", "we");
2950 if (oom_adj) {
2951 fputs("-17", oom_adj);
2952 fclose(oom_adj);
2953 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002954 }
2955
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002956 if (version_ == VERSION_DEFAULT) {
2957 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002958 }
2959
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002960 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002961 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002962 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002963 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002964 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002965 }
2966
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002967 if (options_->show_header_only) {
2968 PrintHeader();
2969 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002970 }
2971
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002972 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2973 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002974
Felipe Leme7447d7c2016-11-03 18:12:22 -07002975 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002976 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002977 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002978 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002979
Sahana Raof35ed432019-07-12 10:47:52 +01002980 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2981 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2982 } else {
2983 // Wake lock will be released automatically on process death
2984 MYLOGD("Wake lock acquired.\n");
2985 }
2986
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002987 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002988
Felipe Lemef0292972016-11-22 13:57:05 -08002989 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002990 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2991 }
2992
Nandana Dutt235c6672019-11-14 15:22:32 +00002993 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002994 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002995
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002996 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002997
Christopher Ferrised9354f2014-10-01 17:35:01 -07002998 // If we are going to use a socket, do it as early as possible
2999 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003000 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07003001 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003002 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00003003 if (control_socket_fd_ == -1) {
3004 return ERROR;
3005 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003006 if (options_->progress_updates_to_socket) {
3007 options_->do_progress_updates = 1;
3008 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07003009 }
3010
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003011 if (!PrepareToWriteToFile()) {
3012 return ERROR;
3013 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08003014
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003015 // Interactive, wear & telephony modes are default to true.
3016 // and may enable from cli option or when using control socket
3017 if (options_->do_progress_updates) {
3018 // clang-format off
3019 std::vector<std::string> am_args = {
3020 "--receiver-permission", "android.permission.DUMP",
3021 };
3022 // clang-format on
3023 // Send STARTED broadcast for apps that listen to bugreport generation events
3024 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
3025 if (options_->progress_updates_to_socket) {
3026 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08003027 }
3028 }
3029
Nick Kralevichf3599b32016-01-25 15:05:16 -08003030 /* read /proc/cmdline before dropping root */
3031 FILE *cmdline = fopen("/proc/cmdline", "re");
3032 if (cmdline) {
3033 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
3034 fclose(cmdline);
3035 }
3036
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003037 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08003038 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05003039 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003040
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003041 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003042 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
3043 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003044 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08003045 }
3046 }
3047
Nandana Dutt3f8c7172018-09-25 12:01:54 +01003048 int dup_stdout_fd;
3049 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003050 // Redirect stderr to log_path_ for debugging.
3051 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
3052 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
3053 return ERROR;
3054 }
3055 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
3056 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
3057 strerror(errno));
3058 }
Nandana Dutt979388e2018-11-30 16:48:55 +00003059
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003060 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3061 // moved into zip file later, if zipping.
3062 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3063 // TODO: why not write to a file instead of stdout to overcome this problem?
3064 /* TODO: rather than generating a text file now and zipping it later,
3065 it would be more efficient to redirect stdout to the zip entry
3066 directly, but the libziparchive doesn't support that option yet. */
3067 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3068 return ERROR;
3069 }
3070 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3071 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3072 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003073 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003074
3075 // Don't buffer stdout
3076 setvbuf(stdout, nullptr, _IONBF, 0);
3077
Rhed Jao5377d792020-07-16 17:37:39 +08003078 // Enable the parallel run if the client requests to output to a file.
3079 EnableParallelRunIfNeeded();
3080 // Using scope guard to make sure the dump pool can be shut down correctly.
3081 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3082 ShutdownDumpPool();
3083 });
3084
Felipe Leme608385d2016-02-01 10:35:38 -08003085 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3086 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003087 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003088 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003089
Gavin Corkery6968f552020-11-22 18:09:05 +00003090 bool is_dumpstate_restricted = options_->telephony_only
3091 || options_->wifi_only
3092 || options_->limited_only;
3093 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003094 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003095 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003096 }
3097 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003098
3099 if (!is_dumpstate_restricted) {
3100 // Snapshot the system trace now (if running) to avoid that dumpstate's
3101 // own activity pushes out interesting data from the trace ring buffer.
3102 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3103 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003104
3105 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3106 // from WMTRACE_DATA_DIR.
3107 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003108 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003109 onUiIntensiveBugreportDumpsFinished(calling_uid);
3110 MaybeCheckUserConsent(calling_uid, calling_package);
3111 if (options_->telephony_only) {
3112 DumpstateTelephonyOnly(calling_package);
3113 } else if (options_->wifi_only) {
3114 DumpstateWifiOnly();
3115 } else if (options_->limited_only) {
3116 DumpstateLimitedOnly();
3117 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003118 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003119 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003120 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003121 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003122 HandleUserConsentDenied();
3123 }
3124 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003125 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003126 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003127
Felipe Leme55b42a62015-11-10 17:39:08 -08003128 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003129 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003130
Abhijeet Kaure370d682019-10-01 16:49:30 +01003131 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003132 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003133
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003134 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003135 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01003136 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003137 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003138 if (status != Dumpstate::RunStatus::OK &&
3139 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3140 // Do an early return if there were errors. We make an exception for consent
3141 // timing out because it's possible the user got distracted. In this case the
3142 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003143 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003144 return status;
3145 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003146 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3147 MYLOGI(
3148 "Did not receive user consent yet."
3149 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003150 const String16 incidentcompanion("incidentcompanion");
3151 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3152 if (ics != nullptr) {
3153 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3154 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3155 consent_callback_.get());
3156 } else {
3157 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3158 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003159 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003160 }
3161
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003162 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003163 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003164 for (int i = 0; i < 3; i++) {
3165 Vibrate(75);
3166 usleep((75 + 50) * 1000);
3167 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003168 }
3169
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003170 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3171 progress_->GetInitialMax());
3172 progress_->Save();
3173 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003174
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003175 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003176
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003177 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003178 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003179 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003180 }
3181
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003182 tombstone_data_.clear();
3183 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003184
Nandana Duttd2f5f082019-01-18 17:13:52 +00003185 return (consent_callback_ != nullptr &&
3186 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3187 ? USER_CONSENT_TIMED_OUT
3188 : RunStatus::OK;
3189}
3190
Paul Chang0d2aad72020-02-13 20:04:03 +08003191void Dumpstate::MaybeTakeEarlyScreenshot() {
3192 if (!options_->do_screenshot || !do_early_screenshot_) {
3193 return;
3194 }
3195
3196 TakeScreenshot();
3197}
3198
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003199void Dumpstate::MaybeSnapshotSystemTrace() {
3200 // If a background system trace is happening and is marked as "suitable for
3201 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3202 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3203 // case that no trace is ongoing, this command is a no-op.
3204 // Note: this should not be enqueued as we need to freeze the trace before
3205 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3206 // the dumpstate's own activity which is irrelevant.
3207 int res = RunCommand(
3208 "SERIALIZE PERFETTO TRACE",
3209 {"perfetto", "--save-for-bugreport"},
3210 CommandOptions::WithTimeout(10)
3211 .DropRoot()
3212 .CloseAllFileDescriptorsOnExec()
3213 .Build());
3214 has_system_trace_ = res == 0;
3215 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3216 // file in the later stages.
3217}
3218
Yohei Yukawa95305b32021-03-09 07:54:27 -08003219void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003220 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3221 for (const auto& service : {"window", "input_method"}) {
3222 RunCommand(
3223 // Empty name because it's not intended to be classified as a bugreport section.
3224 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3225 "", {"cmd", service, "tracing", "save-for-bugreport"},
3226 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3227 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003228}
3229
Paul Changeb4b4642020-05-28 22:05:47 +08003230void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003231 if (calling_uid == AID_SHELL || !CalledByApi()) {
3232 return;
3233 }
3234 if (listener_ != nullptr) {
3235 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3236 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003237 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003238 }
3239}
3240
Jichao Lie89d9c12019-11-21 19:02:51 -08003241void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3242 if (calling_uid == AID_SHELL || !CalledByApi()) {
3243 // No need to get consent for shell triggered dumpstates, or not through
3244 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003245 return;
3246 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003247 consent_callback_ = new ConsentCallback();
3248 const String16 incidentcompanion("incidentcompanion");
3249 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003250 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003251 if (ics != nullptr) {
3252 MYLOGD("Checking user consent via incidentcompanion service\n");
3253 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003254 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003255 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003256 } else {
3257 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3258 }
3259}
3260
Nandana Dutt5c390032019-03-12 10:52:56 +00003261bool Dumpstate::IsUserConsentDenied() const {
3262 return ds.consent_callback_ != nullptr &&
3263 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3264}
3265
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003266bool Dumpstate::CalledByApi() const {
3267 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3268}
3269
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003270void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003271 android::os::UnlinkAndLogOnError(tmp_path_);
3272 android::os::UnlinkAndLogOnError(screenshot_path_);
3273 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003274 if (dump_traces_path != nullptr) {
3275 android::os::UnlinkAndLogOnError(dump_traces_path);
3276 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003277}
3278
Rhed Jao5377d792020-07-16 17:37:39 +08003279void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003280 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003281 return;
3282 }
3283 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003284 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003285}
3286
3287void Dumpstate::ShutdownDumpPool() {
3288 if (dump_pool_) {
3289 dump_pool_->shutdown();
3290 dump_pool_ = nullptr;
3291 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003292 if (zip_entry_tasks_) {
3293 zip_entry_tasks_->run(/* do_cancel = */true);
3294 zip_entry_tasks_ = nullptr;
3295 }
3296}
3297
3298void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3299 const std::string& entry_path) {
3300 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3301 if (!task_cancelled) {
3302 AddZipEntry(entry_name, entry_path);
3303 }
3304 android::os::UnlinkAndLogOnError(entry_path);
3305 };
3306 if (zip_entry_tasks_) {
3307 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3308 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3309 } else {
3310 // Invokes AddZipEntryAndCleanup immediately
3311 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3312 }
Rhed Jao5377d792020-07-16 17:37:39 +08003313}
3314
Nandana Duttd2f5f082019-01-18 17:13:52 +00003315Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3316 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003317 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003318 return USER_CONSENT_DENIED;
3319}
3320
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003321Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003322 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003323 // user consent (unless the caller is Shell).
3324 UserConsentResult consent_result;
3325 if (calling_uid == AID_SHELL) {
3326 consent_result = UserConsentResult::APPROVED;
3327 } else {
3328 consent_result = consent_callback_->getResult();
3329 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003330 if (consent_result == UserConsentResult::UNAVAILABLE) {
3331 // User has not responded yet.
3332 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003333 // Telephony is a fast report type, particularly on user builds where information may be
3334 // more aggressively limited. To give the user time to read the consent dialog, increase the
3335 // timeout.
3336 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3337 : USER_CONSENT_TIMEOUT_MS;
3338 if (elapsed_ms < timeout_ms) {
3339 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003340 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3341 sleep(delay_seconds);
3342 }
3343 consent_result = consent_callback_->getResult();
3344 }
3345 if (consent_result == UserConsentResult::DENIED) {
3346 // User has explicitly denied sharing with the app. To be safe delete the
3347 // internal bugreport & tmp files.
3348 return HandleUserConsentDenied();
3349 }
3350 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003351 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3352 if (copy_succeeded) {
3353 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003354 if (options_->do_screenshot &&
3355 options_->screenshot_fd.get() != -1 &&
3356 !options_->is_screenshot_copied) {
3357 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3358 options_->screenshot_fd.get());
3359 options_->is_screenshot_copied = copy_succeeded;
3360 if (copy_succeeded) {
3361 android::os::UnlinkAndLogOnError(screenshot_path_);
3362 }
3363 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003364 }
3365 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3366 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3367 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3368 // Since we do not have user consent to share the bugreport it does not get
3369 // copied over to the calling app but remains in the internal directory from
3370 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003371 std::string final_path = GetPath(".zip");
3372 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3373 if (copy_succeeded) {
3374 android::os::UnlinkAndLogOnError(path_);
3375 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003376 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3377 }
3378 // Unknown result; must be a programming error.
3379 MYLOGE("Unknown user consent result:%d\n", consent_result);
3380 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003381}
3382
Nandana Duttf02564e2019-02-15 15:24:24 +00003383Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003384 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3385 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3386 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003387 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003388 // When directly running dumpstate binary, the output is not expected to be written
3389 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003390 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003391
3392 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003393 // an app; they are irrelevant here because bugreport is triggered via command line.
3394 // Update Last ID before calling Run().
3395 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003396 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003397 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003398 return status;
3399}
3400
3401/* Main entry point for dumpstate binary. */
3402int run_main(int argc, char* argv[]) {
3403 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003404
3405 switch (status) {
3406 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003407 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003408 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003409 ShowUsage();
3410 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003411 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003412 fprintf(stderr, "Invalid combination of args\n");
3413 ShowUsage();
3414 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003415 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003416 FALLTHROUGH_INTENDED;
3417 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3418 FALLTHROUGH_INTENDED;
3419 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003420 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003421 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003422}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003423
3424// TODO(111441001): Default DumpOptions to sensible values.
3425Dumpstate::Dumpstate(const std::string& version)
3426 : pid_(getpid()),
3427 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003428 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003429 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003430 now_(time(nullptr)),
3431 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003432}
3433
3434Dumpstate& Dumpstate::GetInstance() {
3435 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3436 return singleton_;
3437}
3438
Rhed Jao5377d792020-07-16 17:37:39 +08003439DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3440 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3441 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003442 if (!title_.empty()) {
3443 started_ = Nanotime();
3444 }
3445}
3446
3447DurationReporter::~DurationReporter() {
3448 if (!title_.empty()) {
3449 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003450 if (elapsed >= .5f || verbose_) {
3451 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003452 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003453 if (!logcat_only_) {
3454 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003455 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3456 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003457 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003458 }
3459}
3460
3461const int32_t Progress::kDefaultMax = 5000;
3462
3463Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3464}
3465
3466Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3467 : Progress(initial_max, growth_factor, "") {
3468 progress_ = progress;
3469}
3470
3471Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3472 : initial_max_(initial_max),
3473 progress_(0),
3474 max_(initial_max),
3475 growth_factor_(growth_factor),
3476 n_runs_(0),
3477 average_max_(0),
3478 path_(path) {
3479 if (!path_.empty()) {
3480 Load();
3481 }
3482}
3483
3484void Progress::Load() {
3485 MYLOGD("Loading stats from %s\n", path_.c_str());
3486 std::string content;
3487 if (!android::base::ReadFileToString(path_, &content)) {
3488 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3489 return;
3490 }
3491 if (content.empty()) {
3492 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3493 return;
3494 }
3495 std::vector<std::string> lines = android::base::Split(content, "\n");
3496
3497 if (lines.size() < 1) {
3498 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3499 (int)lines.size(), max_);
3500 return;
3501 }
3502 char* ptr;
3503 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3504 average_max_ = strtol(ptr, nullptr, 10);
3505 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3506 average_max_ > STATS_MAX_AVERAGE) {
3507 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3508 initial_max_ = Progress::kDefaultMax;
3509 } else {
3510 initial_max_ = average_max_;
3511 }
3512 max_ = initial_max_;
3513
3514 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3515}
3516
3517void Progress::Save() {
3518 int32_t total = n_runs_ * average_max_ + progress_;
3519 int32_t runs = n_runs_ + 1;
3520 int32_t average = floor(((float)total) / runs);
3521 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3522 path_.c_str());
3523 if (path_.empty()) {
3524 return;
3525 }
3526
3527 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3528 if (!android::base::WriteStringToFile(content, path_)) {
3529 MYLOGE("Could not save stats on %s\n", path_.c_str());
3530 }
3531}
3532
3533int32_t Progress::Get() const {
3534 return progress_;
3535}
3536
3537bool Progress::Inc(int32_t delta_sec) {
3538 bool changed = false;
3539 if (delta_sec >= 0) {
3540 progress_ += delta_sec;
3541 if (progress_ > max_) {
3542 int32_t old_max = max_;
3543 max_ = floor((float)progress_ * growth_factor_);
3544 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3545 changed = true;
3546 }
3547 }
3548 return changed;
3549}
3550
3551int32_t Progress::GetMax() const {
3552 return max_;
3553}
3554
3555int32_t Progress::GetInitialMax() const {
3556 return initial_max_;
3557}
3558
3559void Progress::Dump(int fd, const std::string& prefix) const {
3560 const char* pr = prefix.c_str();
3561 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3562 dprintf(fd, "%smax: %d\n", pr, max_);
3563 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3564 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3565 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3566 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3567 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3568}
3569
3570bool Dumpstate::IsZipping() const {
3571 return zip_writer_ != nullptr;
3572}
3573
3574std::string Dumpstate::GetPath(const std::string& suffix) const {
3575 return GetPath(bugreport_internal_dir_, suffix);
3576}
3577
3578std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3579 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3580 name_.c_str(), suffix.c_str());
3581}
3582
3583void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3584 progress_ = std::move(progress);
3585}
3586
3587void for_each_userid(void (*func)(int), const char *header) {
3588 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3589 "for_each_userid(%s)", header);
3590 DurationReporter duration_reporter(title);
3591 if (PropertiesHelper::IsDryRun()) return;
3592
3593 DIR *d;
3594 struct dirent *de;
3595
3596 if (header) printf("\n------ %s ------\n", header);
3597 func(0);
3598
3599 if (!(d = opendir("/data/system/users"))) {
3600 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3601 return;
3602 }
3603
3604 while ((de = readdir(d))) {
3605 int userid;
3606 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3607 continue;
3608 }
3609 func(userid);
3610 }
3611
3612 closedir(d);
3613}
3614
3615static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3616 DIR *d;
3617 struct dirent *de;
3618
3619 if (!(d = opendir("/proc"))) {
3620 printf("Failed to open /proc (%s)\n", strerror(errno));
3621 return;
3622 }
3623
3624 if (header) printf("\n------ %s ------\n", header);
3625 while ((de = readdir(d))) {
3626 if (ds.IsUserConsentDenied()) {
3627 MYLOGE(
3628 "Returning early because user denied consent to share bugreport with calling app.");
3629 closedir(d);
3630 return;
3631 }
3632 int pid;
3633 int fd;
3634 char cmdpath[255];
3635 char cmdline[255];
3636
3637 if (!(pid = atoi(de->d_name))) {
3638 continue;
3639 }
3640
3641 memset(cmdline, 0, sizeof(cmdline));
3642
3643 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3644 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3645 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3646 close(fd);
3647 if (cmdline[0]) {
3648 helper(pid, cmdline, arg);
3649 continue;
3650 }
3651 }
3652
3653 // if no cmdline, a kernel thread has comm
3654 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3655 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3656 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3657 close(fd);
3658 if (cmdline[1]) {
3659 cmdline[0] = '[';
3660 size_t len = strcspn(cmdline, "\f\b\r\n");
3661 cmdline[len] = ']';
3662 cmdline[len+1] = '\0';
3663 }
3664 }
3665 if (!cmdline[0]) {
3666 strcpy(cmdline, "N/A");
3667 }
3668 helper(pid, cmdline, arg);
3669 }
3670
3671 closedir(d);
3672}
3673
3674static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3675 for_each_pid_func *func = (for_each_pid_func*) arg;
3676 func(pid, cmdline);
3677}
3678
3679void for_each_pid(for_each_pid_func func, const char *header) {
3680 std::string title = header == nullptr ? "for_each_pid"
3681 : android::base::StringPrintf("for_each_pid(%s)", header);
3682 DurationReporter duration_reporter(title);
3683 if (PropertiesHelper::IsDryRun()) return;
3684
3685 __for_each_pid(for_each_pid_helper, header, (void *) func);
3686}
3687
3688static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3689 DIR *d;
3690 struct dirent *de;
3691 char taskpath[255];
3692 for_each_tid_func *func = (for_each_tid_func *) arg;
3693
3694 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3695
3696 if (!(d = opendir(taskpath))) {
3697 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3698 return;
3699 }
3700
3701 func(pid, pid, cmdline);
3702
3703 while ((de = readdir(d))) {
3704 if (ds.IsUserConsentDenied()) {
3705 MYLOGE(
3706 "Returning early because user denied consent to share bugreport with calling app.");
3707 closedir(d);
3708 return;
3709 }
3710 int tid;
3711 int fd;
3712 char commpath[255];
3713 char comm[255];
3714
3715 if (!(tid = atoi(de->d_name))) {
3716 continue;
3717 }
3718
3719 if (tid == pid)
3720 continue;
3721
3722 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3723 memset(comm, 0, sizeof(comm));
3724 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3725 strcpy(comm, "N/A");
3726 } else {
3727 char *c;
3728 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3729 close(fd);
3730
3731 c = strrchr(comm, '\n');
3732 if (c) {
3733 *c = '\0';
3734 }
3735 }
3736 func(pid, tid, comm);
3737 }
3738
3739 closedir(d);
3740}
3741
3742void for_each_tid(for_each_tid_func func, const char *header) {
3743 std::string title = header == nullptr ? "for_each_tid"
3744 : android::base::StringPrintf("for_each_tid(%s)", header);
3745 DurationReporter duration_reporter(title);
3746
3747 if (PropertiesHelper::IsDryRun()) return;
3748
3749 __for_each_pid(for_each_tid_helper, header, (void *) func);
3750}
3751
3752void show_wchan(int pid, int tid, const char *name) {
3753 if (PropertiesHelper::IsDryRun()) return;
3754
3755 char path[255];
3756 char buffer[255];
3757 int fd, ret, save_errno;
3758 char name_buffer[255];
3759
3760 memset(buffer, 0, sizeof(buffer));
3761
3762 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3763 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3764 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3765 return;
3766 }
3767
3768 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3769 save_errno = errno;
3770 close(fd);
3771
3772 if (ret < 0) {
3773 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3774 return;
3775 }
3776
3777 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3778 pid == tid ? 0 : 3, "", name);
3779
3780 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3781
3782 return;
3783}
3784
3785// print time in centiseconds
3786static void snprcent(char *buffer, size_t len, size_t spc,
3787 unsigned long long time) {
3788 static long hz; // cache discovered hz
3789
3790 if (hz <= 0) {
3791 hz = sysconf(_SC_CLK_TCK);
3792 if (hz <= 0) {
3793 hz = 1000;
3794 }
3795 }
3796
3797 // convert to centiseconds
3798 time = (time * 100 + (hz / 2)) / hz;
3799
3800 char str[16];
3801
3802 snprintf(str, sizeof(str), " %llu.%02u",
3803 time / 100, (unsigned)(time % 100));
3804 size_t offset = strlen(buffer);
3805 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3806 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3807}
3808
3809// print permille as a percent
3810static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3811 char str[16];
3812
3813 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3814 size_t offset = strlen(buffer);
3815 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3816 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3817}
3818
3819void show_showtime(int pid, const char *name) {
3820 if (PropertiesHelper::IsDryRun()) return;
3821
3822 char path[255];
3823 char buffer[1023];
3824 int fd, ret, save_errno;
3825
3826 memset(buffer, 0, sizeof(buffer));
3827
3828 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3829 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3830 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3831 return;
3832 }
3833
3834 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3835 save_errno = errno;
3836 close(fd);
3837
3838 if (ret < 0) {
3839 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3840 return;
3841 }
3842
3843 // field 14 is utime
3844 // field 15 is stime
3845 // field 42 is iotime
3846 unsigned long long utime = 0, stime = 0, iotime = 0;
3847 if (sscanf(buffer,
3848 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3849 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3850 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3851 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3852 &utime, &stime, &iotime) != 3) {
3853 return;
3854 }
3855
3856 unsigned long long total = utime + stime;
3857 if (!total) {
3858 return;
3859 }
3860
3861 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3862 if (permille > 1000) {
3863 permille = 1000;
3864 }
3865
3866 // try to beautify and stabilize columns at <80 characters
3867 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3868 if ((name[0] != '[') || utime) {
3869 snprcent(buffer, sizeof(buffer), 57, utime);
3870 }
3871 snprcent(buffer, sizeof(buffer), 65, stime);
3872 if ((name[0] != '[') || iotime) {
3873 snprcent(buffer, sizeof(buffer), 73, iotime);
3874 }
3875 if (iotime) {
3876 snprdec(buffer, sizeof(buffer), 79, permille);
3877 }
3878 puts(buffer); // adds a trailing newline
3879
3880 return;
3881}
3882
3883void do_dmesg() {
3884 const char *title = "KERNEL LOG (dmesg)";
3885 DurationReporter duration_reporter(title);
3886 printf("------ %s ------\n", title);
3887
3888 if (PropertiesHelper::IsDryRun()) return;
3889
3890 /* Get size of kernel buffer */
3891 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3892 if (size <= 0) {
3893 printf("Unexpected klogctl return value: %d\n\n", size);
3894 return;
3895 }
3896 char *buf = (char *) malloc(size + 1);
3897 if (buf == nullptr) {
3898 printf("memory allocation failed\n\n");
3899 return;
3900 }
3901 int retval = klogctl(KLOG_READ_ALL, buf, size);
3902 if (retval < 0) {
3903 printf("klogctl failure\n\n");
3904 free(buf);
3905 return;
3906 }
3907 buf[retval] = '\0';
3908 printf("%s\n\n", buf);
3909 free(buf);
3910 return;
3911}
3912
3913void do_showmap(int pid, const char *name) {
3914 char title[255];
3915 char arg[255];
3916
3917 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3918 snprintf(arg, sizeof(arg), "%d", pid);
3919 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3920}
3921
3922int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3923 DurationReporter duration_reporter(title);
3924
3925 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3926
3927 UpdateProgress(WEIGHT_FILE);
3928
3929 return status;
3930}
3931
3932int read_file_as_long(const char *path, long int *output) {
3933 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3934 if (fd < 0) {
3935 int err = errno;
3936 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3937 return -1;
3938 }
3939 char buffer[50];
3940 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3941 if (bytes_read == -1) {
3942 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3943 return -2;
3944 }
3945 if (bytes_read == 0) {
3946 MYLOGE("File %s is empty\n", path);
3947 return -3;
3948 }
3949 *output = atoi(buffer);
3950 return 0;
3951}
3952
3953/* calls skip to gate calling dump_from_fd recursively
3954 * in the specified directory. dump_from_fd defaults to
3955 * dump_file_from_fd above when set to NULL. skip defaults
3956 * to false when set to NULL. dump_from_fd will always be
3957 * called with title NULL.
3958 */
3959int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3960 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3961 DurationReporter duration_reporter(title);
3962 DIR *dirp;
3963 struct dirent *d;
3964 char *newpath = nullptr;
3965 const char *slash = "/";
3966 int retval = 0;
3967
3968 if (!title.empty()) {
3969 printf("------ %s (%s) ------\n", title.c_str(), dir);
3970 }
3971 if (PropertiesHelper::IsDryRun()) return 0;
3972
3973 if (dir[strlen(dir) - 1] == '/') {
3974 ++slash;
3975 }
3976 dirp = opendir(dir);
3977 if (dirp == nullptr) {
3978 retval = -errno;
3979 MYLOGE("%s: %s\n", dir, strerror(errno));
3980 return retval;
3981 }
3982
3983 if (!dump_from_fd) {
3984 dump_from_fd = dump_file_from_fd;
3985 }
3986 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3987 if ((d->d_name[0] == '.')
3988 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3989 || (d->d_name[1] == '\0'))) {
3990 continue;
3991 }
3992 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3993 (d->d_type == DT_DIR) ? "/" : "");
3994 if (!newpath) {
3995 retval = -errno;
3996 continue;
3997 }
3998 if (skip && (*skip)(newpath)) {
3999 continue;
4000 }
4001 if (d->d_type == DT_DIR) {
4002 int ret = dump_files("", newpath, skip, dump_from_fd);
4003 if (ret < 0) {
4004 retval = ret;
4005 }
4006 continue;
4007 }
4008 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
4009 if (fd.get() < 0) {
4010 retval = -1;
4011 printf("*** %s: %s\n", newpath, strerror(errno));
4012 continue;
4013 }
4014 (*dump_from_fd)(nullptr, newpath, fd.get());
4015 }
4016 closedir(dirp);
4017 if (!title.empty()) {
4018 printf("\n");
4019 }
4020 return retval;
4021}
4022
4023/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
4024 * it's possible to avoid issues where opening the file itself can get
4025 * stuck.
4026 */
4027int dump_file_from_fd(const char *title, const char *path, int fd) {
4028 if (PropertiesHelper::IsDryRun()) return 0;
4029
4030 int flags = fcntl(fd, F_GETFL);
4031 if (flags == -1) {
4032 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
4033 return -1;
4034 } else if (!(flags & O_NONBLOCK)) {
4035 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
4036 return -1;
4037 }
4038 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
4039}
4040
4041int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004042 const CommandOptions& options, bool verbose_duration, int out_fd) {
4043 DurationReporter duration_reporter(title, false /* logcat_only */,
4044 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004045
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08004046 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004047
4048 /* TODO: for now we're simplifying the progress calculation by using the
4049 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
4050 * where its weight should be much higher proportionally to its timeout.
4051 * Ideally, it should use a options.EstimatedDuration() instead...*/
4052 UpdateProgress(options.Timeout());
4053
4054 return status;
4055}
4056
4057void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08004058 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004059 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
4060 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
4061 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08004062 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004063}
4064
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004065static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004066 int s = android_get_control_socket(service);
4067 if (s < 0) {
4068 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4069 return -1;
4070 }
4071 fcntl(s, F_SETFD, FD_CLOEXEC);
4072
4073 // Set backlog to 0 to make sure that queue size will be minimum.
4074 // In Linux, because the minimum queue will be 1, connect() will be blocked
4075 // if the other clients already called connect() and the connection request was not accepted.
4076 if (listen(s, 0) < 0) {
4077 MYLOGE("listen(control socket): %s\n", strerror(errno));
4078 return -1;
4079 }
4080
4081 struct sockaddr addr;
4082 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004083 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004084
4085 // Close socket just after accept(), to make sure that connect() by client will get error
4086 // when the socket is used by the other services.
4087 // There is still a race condition possibility between accept and close, but there is no way
4088 // to close-on-accept atomically.
4089 // See detail; b/123306389#comment25
4090 close(s);
4091
4092 if (fd < 0) {
4093 MYLOGE("accept(control socket): %s\n", strerror(errno));
4094 return -1;
4095 }
4096
4097 return fd;
4098}
4099
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004100// TODO: should call is_valid_output_file and/or be merged into it.
4101void create_parent_dirs(const char *path) {
4102 char *chp = const_cast<char *> (path);
4103
4104 /* skip initial slash */
4105 if (chp[0] == '/')
4106 chp++;
4107
4108 /* create leading directories, if necessary */
4109 struct stat dir_stat;
4110 while (chp && chp[0]) {
4111 chp = strchr(chp, '/');
4112 if (chp) {
4113 *chp = 0;
4114 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4115 MYLOGI("Creating directory %s\n", path);
4116 if (mkdir(path, 0770)) { /* drwxrwx--- */
4117 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4118 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4119 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4120 }
4121 }
4122 *chp++ = '/';
4123 }
4124 }
4125}
4126
4127bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4128 create_parent_dirs(path);
4129
4130 int fd = TEMP_FAILURE_RETRY(open(path,
4131 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4132 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4133 if (fd < 0) {
4134 MYLOGE("%s: %s\n", path, strerror(errno));
4135 return false;
4136 }
4137
4138 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4139 close(fd);
4140 return true;
4141}
4142
4143bool redirect_to_file(FILE* redirect, char* path) {
4144 return _redirect_to_file(redirect, path, O_TRUNC);
4145}
4146
4147bool redirect_to_existing_file(FILE* redirect, char* path) {
4148 return _redirect_to_file(redirect, path, O_APPEND);
4149}
4150
4151void dump_route_tables() {
4152 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4153 if (PropertiesHelper::IsDryRun()) return;
4154 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4155 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4156 FILE* fp = fopen(RT_TABLES_PATH, "re");
4157 if (!fp) {
4158 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4159 return;
4160 }
4161 char table[16];
4162 // Each line has an integer (the table number), a space, and a string (the table name). We only
4163 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4164 // Add a fixed max limit so this doesn't go awry.
4165 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4166 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4167 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4168 }
4169 fclose(fp);
4170}
4171
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004172void Dumpstate::UpdateProgress(int32_t delta_sec) {
4173 if (progress_ == nullptr) {
4174 MYLOGE("UpdateProgress: progress_ not set\n");
4175 return;
4176 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004177 // This function updates progress related members of the dumpstate and reports
4178 // progress percentage to the bugreport client. Since it could be called by
4179 // different dump tasks at the same time if the parallel run is enabled, a
4180 // mutex lock is necessary here to synchronize the call.
4181 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004182
4183 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004184 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004185
4186 // ...but only notifiy listeners when necessary.
4187 if (!options_->do_progress_updates) return;
4188
4189 int progress = progress_->Get();
4190 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004191 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004192
Nandana Dutt402a8392019-06-14 14:25:13 +01004193 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004194 return;
4195 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004196 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004197
4198 if (control_socket_fd_ >= 0) {
4199 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4200 fsync(control_socket_fd_);
4201 }
4202
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004203 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004204 if (percent % 10 == 0) {
4205 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004206 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004207 } else {
4208 // stderr is ignored on normal invocations, but useful when calling
4209 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004210 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004211 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004212
4213 listener_->onProgress(percent);
4214 }
4215}
4216
4217void Dumpstate::TakeScreenshot(const std::string& path) {
4218 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4219 int status =
4220 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4221 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4222 if (status == 0) {
4223 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4224 } else {
4225 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4226 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004227 if (listener_ != nullptr) {
4228 // Show a visual indication to indicate screenshot is taken via
4229 // IDumpstateListener.onScreenshotTaken()
4230 listener_->onScreenshotTaken(status == 0);
4231 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004232}
4233
4234bool is_dir(const char* pathname) {
4235 struct stat info;
4236 if (stat(pathname, &info) == -1) {
4237 return false;
4238 }
4239 return S_ISDIR(info.st_mode);
4240}
4241
4242time_t get_mtime(int fd, time_t default_mtime) {
4243 struct stat info;
4244 if (fstat(fd, &info) == -1) {
4245 return default_mtime;
4246 }
4247 return info.st_mtime;
4248}