blob: 8ccd940bcf6a36097d7328c24db20ef190863ddf [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
Chris Morinc2cba7a2022-02-01 17:06:50 -0800374 * order.
Narayan Kamath8f788292017-05-25 13:20:39 +0100375 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700376static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
Chris Morinc2cba7a2022-02-01 17:06:50 -0800377 const std::string& file_prefix) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100378 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100379
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700380 if (dump_dir == nullptr) {
381 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700382 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700383 }
384
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700385 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100386 struct dirent* entry = nullptr;
387 while ((entry = readdir(dump_dir.get()))) {
388 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100389 continue;
390 }
391
Narayan Kamathbd863722017-06-01 18:50:12 +0100392 const std::string base_name(entry->d_name);
393 if (base_name.find(file_prefix) != 0) {
394 continue;
395 }
396
397 const std::string abs_path = dir_path + base_name;
398 android::base::unique_fd fd(
399 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
400 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700401 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100402 break;
403 }
404
405 struct stat st = {};
406 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700407 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100408 continue;
409 }
410
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700411 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700412 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800413 if (!dump_data.empty()) {
414 std::sort(dump_data.begin(), dump_data.end(),
415 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
416 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100417
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700418 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100419}
420
Narayan Kamathbd863722017-06-01 18:50:12 +0100421static bool AddDumps(const std::vector<DumpData>::const_iterator start,
422 const std::vector<DumpData>::const_iterator end,
423 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100424 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100425 for (auto it = start; it != end; ++it) {
426 const std::string& name = it->name;
427 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100428 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100429
430 // Seek to the beginning of the file before dumping any data. A given
431 // DumpData entry might be dumped multiple times in the report.
432 //
433 // For example, the most recent ANR entry is dumped to the body of the
434 // main entry and it also shows up as a separate entry in the bugreport
435 // ZIP file.
436 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
437 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
438 strerror(errno));
439 }
440
Chris Morinc2cba7a2022-02-01 17:06:50 -0800441 if (add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800442 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100443 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100444 }
445 } else {
446 dump_file_from_fd(type_name, name.c_str(), fd);
447 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100448 }
449
450 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700451}
452
Felipe Leme635ca312016-01-05 14:23:02 -0800453// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700454void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800455 char path[PATH_MAX];
456
457 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
458 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700459 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800460 char linkname[PATH_MAX];
461 ssize_t r = readlink(path, linkname, PATH_MAX);
462 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800463 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800464 return;
465 }
466 linkname[r] = '\0';
467
468 if (mount_points.find(linkname) == mount_points.end()) {
469 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700470 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700471 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800472 mount_points.insert(linkname);
473 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800474 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800475 }
476 }
477}
478
479void add_mountinfo() {
Felipe Leme678727a2016-09-21 17:22:11 -0700480 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800481 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800482 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700483 for_each_pid(do_mountinfo, nullptr);
484 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800485}
486
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700487static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
488{
489 DIR *d;
490 struct dirent *de;
491 char path[PATH_MAX];
492
493 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700494 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700495 return;
496 }
497
498 while ((de = readdir(d))) {
499 if (de->d_type != DT_LNK) {
500 continue;
501 }
502 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700503 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700504 }
505
506 closedir(d);
507}
508
Mark Salyzyn326842f2015-04-30 09:49:41 -0700509static bool skip_not_stat(const char *path) {
510 static const char stat[] = "/stat";
511 size_t len = strlen(path);
512 if (path[len - 1] == '/') { /* Directory? */
513 return false;
514 }
515 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
516}
517
Felipe Leme4c2d6632016-09-28 14:32:00 -0700518static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800519 return false;
520}
521
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700522unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800524//
525// stat offsets
526// Name units description
527// ---- ----- -----------
528// read I/Os requests number of read I/Os processed
529#define __STAT_READ_IOS 0
530// read merges requests number of read I/Os merged with in-queue I/O
531#define __STAT_READ_MERGES 1
532// read sectors sectors number of sectors read
533#define __STAT_READ_SECTORS 2
534// read ticks milliseconds total wait time for read requests
535#define __STAT_READ_TICKS 3
536// write I/Os requests number of write I/Os processed
537#define __STAT_WRITE_IOS 4
538// write merges requests number of write I/Os merged with in-queue I/O
539#define __STAT_WRITE_MERGES 5
540// write sectors sectors number of sectors written
541#define __STAT_WRITE_SECTORS 6
542// write ticks milliseconds total wait time for write requests
543#define __STAT_WRITE_TICKS 7
544// in_flight requests number of I/Os currently in flight
545#define __STAT_IN_FLIGHT 8
546// io_ticks milliseconds total time this block device has been active
547#define __STAT_IO_TICKS 9
548// time_in_queue milliseconds total wait time for all requests
549#define __STAT_IN_QUEUE 10
550#define __STAT_NUMBER_FIELD 11
551//
552// read I/Os, write I/Os
553// =====================
554//
555// These values increment when an I/O request completes.
556//
557// read merges, write merges
558// =========================
559//
560// These values increment when an I/O request is merged with an
561// already-queued I/O request.
562//
563// read sectors, write sectors
564// ===========================
565//
566// These values count the number of sectors read from or written to this
567// block device. The "sectors" in question are the standard UNIX 512-byte
568// sectors, not any device- or filesystem-specific block size. The
569// counters are incremented when the I/O completes.
570#define SECTOR_SIZE 512
571//
572// read ticks, write ticks
573// =======================
574//
575// These values count the number of milliseconds that I/O requests have
576// waited on this block device. If there are multiple I/O requests waiting,
577// these values will increase at a rate greater than 1000/second; for
578// example, if 60 read requests wait for an average of 30 ms, the read_ticks
579// field will increase by 60*30 = 1800.
580//
581// in_flight
582// =========
583//
584// This value counts the number of I/O requests that have been issued to
585// the device driver but have not yet completed. It does not include I/O
586// requests that are in the queue but not yet issued to the device driver.
587//
588// io_ticks
589// ========
590//
591// This value counts the number of milliseconds during which the device has
592// had I/O requests queued.
593//
594// time_in_queue
595// =============
596//
597// This value counts the number of milliseconds that I/O requests have waited
598// on this block device. If there are multiple I/O requests waiting, this
599// value will increase as the product of the number of milliseconds times the
600// number of requests waiting (see "read ticks" above for an example).
601#define S_TO_MS 1000
602//
603
Mark Salyzyn326842f2015-04-30 09:49:41 -0700604static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800605 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700606 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700607 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700608 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700609 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700610 getline(&buffer, &i, fp);
611 fclose(fp);
612 if (!buffer) {
613 return -errno;
614 }
615 i = strlen(buffer);
616 while ((i > 0) && (buffer[i - 1] == '\n')) {
617 buffer[--i] = '\0';
618 }
619 if (!*buffer) {
620 free(buffer);
621 return 0;
622 }
623 z = true;
624 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800625 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700626 if (fields[i] != 0) {
627 z = false;
628 }
629 }
630 if (z) { /* never accessed */
631 free(buffer);
632 return 0;
633 }
634
Wei Wang509bb5d2017-06-09 14:42:12 -0700635 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
636 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700638
639 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
640 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
641 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700642 free(buffer);
643
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800644 if (fields[__STAT_IO_TICKS]) {
645 unsigned long read_perf = 0;
646 unsigned long read_ios = 0;
647 if (fields[__STAT_READ_TICKS]) {
648 unsigned long long divisor = fields[__STAT_READ_TICKS]
649 * fields[__STAT_IO_TICKS];
650 read_perf = ((unsigned long long)SECTOR_SIZE
651 * fields[__STAT_READ_SECTORS]
652 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
653 / divisor;
654 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
655 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
656 / divisor;
657 }
658
659 unsigned long write_perf = 0;
660 unsigned long write_ios = 0;
661 if (fields[__STAT_WRITE_TICKS]) {
662 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
663 * fields[__STAT_IO_TICKS];
664 write_perf = ((unsigned long long)SECTOR_SIZE
665 * fields[__STAT_WRITE_SECTORS]
666 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
667 / divisor;
668 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
669 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
670 / divisor;
671 }
672
673 unsigned queue = (fields[__STAT_IN_QUEUE]
674 + (fields[__STAT_IO_TICKS] >> 1))
675 / fields[__STAT_IO_TICKS];
676
677 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700678 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 -0800679 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700680 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 -0800681 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800682 }
683
684 /* bugreport timeout factor adjustment */
685 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
686 worst_write_perf = write_perf;
687 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700688 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700689 return 0;
690}
691
Yao Chenbe3bbc12018-01-17 16:31:10 -0800692static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
693
Tom Cherryf4472f32020-08-05 09:31:17 -0700694// Returns the actual readable size of the given buffer or -1 on error.
695static long logcat_buffer_readable_size(const std::string& buffer) {
696 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
697 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
698 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
699
700 return android_logger_get_log_readable_size(logger);
701}
702
703// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800704static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
705 unsigned long timeout_ms = 0;
706 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700707 long readable_size = logcat_buffer_readable_size(buffer);
708 if (readable_size > 0) {
709 // Engineering margin is ten-fold our guess.
710 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
711 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800712 }
713 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700714}
715
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800716// Opens a socket and returns its file descriptor.
717static int open_socket(const char* service);
718
Nandana Duttd2f5f082019-01-18 17:13:52 +0000719Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
720}
721
722android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
723 std::lock_guard<std::mutex> lock(lock_);
724 result_ = APPROVED;
725 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800726
727 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
728 // consent is granted.
729 if (ds.options_->is_screenshot_copied) {
730 return android::binder::Status::ok();
731 }
732
733 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
734 !ds.do_early_screenshot_) {
735 return android::binder::Status::ok();
736 }
737
738 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
739 ds.options_->screenshot_fd.get());
740 ds.options_->is_screenshot_copied = copy_succeeded;
741 if (copy_succeeded) {
742 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
743 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000744 return android::binder::Status::ok();
745}
746
747android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
748 std::lock_guard<std::mutex> lock(lock_);
749 result_ = DENIED;
750 MYLOGW("User denied consent to share bugreport\n");
751 return android::binder::Status::ok();
752}
753
754UserConsentResult Dumpstate::ConsentCallback::getResult() {
755 std::lock_guard<std::mutex> lock(lock_);
756 return result_;
757}
758
759uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800760 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000761}
762
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700763void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700764 std::string build, fingerprint, radio, bootloader, network;
765 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700766
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700767 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
768 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700769 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
770 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
771 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700772 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700773
Felipe Lemed8b94e52016-12-08 10:21:44 -0800774 printf("========================================================\n");
775 printf("== dumpstate: %s\n", date);
776 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700777
Felipe Lemed8b94e52016-12-08 10:21:44 -0800778 printf("\n");
779 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700780 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800781 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
782 printf("Bootloader: %s\n", bootloader.c_str());
783 printf("Radio: %s\n", radio.c_str());
784 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100785 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
786 if (module_metadata_version != 0) {
787 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
788 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100789 printf("SDK extension versions [r=%s s=%s]\n",
790 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
791 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700792
Felipe Lemed8b94e52016-12-08 10:21:44 -0800793 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800794 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800795 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800796 printf("Uptime: ");
797 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
798 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800799 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800800 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
801 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000802 options_->args.c_str(), options_->bugreport_mode_string.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800804}
805
Felipe Leme24b66ee2016-06-16 10:55:26 -0700806// List of file extensions that can cause a zip file attachment to be rejected by some email
807// service providers.
808static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
809 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
810 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
811 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
812};
813
Vishnu Naire97d6122018-01-18 13:58:56 -0800814status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
815 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700816 std::string valid_name = entry_name;
817
818 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700819 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700820 if (idx != std::string::npos) {
821 std::string extension = entry_name.substr(idx);
822 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
823 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
824 valid_name = entry_name + ".renamed";
825 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
826 }
827 }
828
Felipe Leme6fe9db62016-02-12 09:04:16 -0800829 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
830 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700831 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
832 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700833 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700834 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700835 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800836 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800837 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000838 bool finished_entry = false;
839 auto finish_entry = [this, &finished_entry] {
840 if (!finished_entry) {
841 // This should only be called when we're going to return an earlier error,
842 // which would've been logged. This may imply the file is already corrupt
843 // and any further logging from FinishEntry is more likely to mislead than
844 // not.
845 this->zip_writer_->FinishEntry();
846 }
847 };
848 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800849 auto start = std::chrono::steady_clock::now();
850 auto end = start + timeout;
851 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800852
Felipe Leme770410d2016-01-26 17:07:14 -0800853 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800854 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800855 if (timeout.count() > 0) {
856 // lambda to recalculate the timeout.
857 auto time_left_ms = [end]() {
858 auto now = std::chrono::steady_clock::now();
859 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
860 return std::max(diff.count(), 0LL);
861 };
862
863 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
864 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000865 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
866 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 return -errno;
868 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000869 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 entry_name.c_str(), strerror(errno), timeout.count());
871 return TIMED_OUT;
872 }
873 }
874
Zach Riggle22200402016-08-18 01:01:24 -0400875 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800876 if (bytes_read == 0) {
877 break;
878 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800879 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800881 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700882 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700884 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800885 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800886 }
887 }
888
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700889 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000890 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700891 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700892 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800893 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800894 }
895
Vishnu Naire97d6122018-01-18 13:58:56 -0800896 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800897}
898
Felipe Leme1d486fe2016-10-14 18:06:47 -0700899bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
900 android::base::unique_fd fd(
901 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700902 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800903 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800904 return false;
905 }
906
Vishnu Naire97d6122018-01-18 13:58:56 -0800907 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800908}
909
910/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700911static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800912 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913}
914
Felipe Leme1d486fe2016-10-14 18:06:47 -0700915void Dumpstate::AddDir(const std::string& dir, bool recursive) {
Felipe Leme678727a2016-09-21 17:22:11 -0700916 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800917 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700918 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800919}
920
Felipe Leme1d486fe2016-10-14 18:06:47 -0700921bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800922 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700923 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700924 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700925 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700926 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800927 return false;
928 }
929
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700930 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700931 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700932 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700933 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800934 return false;
935 }
936
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700937 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700938 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700939 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800940 return false;
941 }
942
943 return true;
944}
945
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800946static void DoKmsg() {
947 struct stat st;
948 if (!stat(PSTORE_LAST_KMSG, &st)) {
949 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
950 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
951 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
952 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
953 } else {
954 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
955 DumpFile("LAST KMSG", "/proc/last_kmsg");
956 }
957}
958
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800959static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800960 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800961 RunCommand(
962 "KERNEL LOG",
963 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
964 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
965}
966
Nandana Duttdb379fa2019-10-09 16:54:41 +0100967static void DoSystemLogcat(time_t since) {
968 char since_str[80];
969 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
970
971 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
972 RunCommand("SYSTEM LOG",
973 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
974 since_str},
975 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
976}
977
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800978static void DoRadioLogcat() {
979 unsigned long timeout_ms = logcat_timeout({"radio"});
980 RunCommand(
981 "RADIO LOG",
982 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
983 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
984}
985
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800986static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800987 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800988 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
989 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800990 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100991 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800992 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
993 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800994 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800995 RunCommand(
996 "EVENT LOG",
997 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +0100998 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -0800999 timeout_ms = logcat_timeout({"stats"});
1000 RunCommand(
1001 "STATS LOG",
1002 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001003 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001004 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001005
1006 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1007
1008 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001009 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1010 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001011}
1012
Mike Ma5c267872019-08-21 11:31:34 -07001013static void DumpIncidentReport() {
Mike Ma5c267872019-08-21 11:31:34 -07001014 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1015 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1016 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1017 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1018 if (fd < 0) {
1019 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1020 return;
1021 }
1022 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1023 bool empty = 0 == lseek(fd, 0, SEEK_END);
1024 if (!empty) {
1025 // Use a different name from "incident.proto"
1026 // /proto/incident.proto is reserved for incident service dump
1027 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001028 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1029 path);
1030 } else {
1031 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001032 }
Mike Ma5c267872019-08-21 11:31:34 -07001033}
1034
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001035static void MaybeAddSystemTraceToZip() {
1036 // This function copies into the .zip the system trace that was snapshotted
1037 // by the early call to MaybeSnapshotSystemTrace(), if any background
1038 // tracing was happening.
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001039 if (!ds.has_system_trace_) {
1040 // No background trace was happening at the time dumpstate was invoked.
1041 return;
1042 }
1043 ds.AddZipEntry(
1044 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1045 SYSTEM_TRACE_SNAPSHOT);
1046 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1047}
1048
Sunny Goyal35949782019-11-19 15:54:36 -08001049static void DumpVisibleWindowViews() {
Sunny Goyal35949782019-11-19 15:54:36 -08001050 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1051 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1052 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1053 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1054 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1055 if (fd < 0) {
1056 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1057 return;
1058 }
1059 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1060 CommandOptions::WithTimeout(120).Build());
1061 bool empty = 0 == lseek(fd, 0, SEEK_END);
1062 if (!empty) {
1063 ds.AddZipEntry("visible_windows.zip", path);
1064 } else {
1065 MYLOGW("Failed to dump visible windows\n");
1066 }
1067 unlink(path.c_str());
1068}
1069
Jayachandran Ca94c7172017-06-10 15:08:12 -07001070static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001071 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1072 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001073 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001074 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001075 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1076 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1077 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1078 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001079}
1080
David Andersond9ba4752018-12-11 18:26:59 -08001081static void DumpDynamicPartitionInfo() {
1082 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1083 return;
1084 }
1085
1086 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001087 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001088}
1089
Chris Morin5a50d482022-02-01 17:41:18 -08001090static void AddAnrTraceDir(const std::string& anr_traces_dir) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001091 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1092 anr_traces_dir.c_str());
1093
1094 // If we're here, dump_traces_path will always be a temporary file
1095 // (created with mkostemp or similar) that contains dumps taken earlier
1096 // on in the process.
1097 if (dump_traces_path != nullptr) {
Chris Morin5a50d482022-02-01 17:41:18 -08001098 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1099 dump_traces_path);
1100 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
Narayan Kamath8f788292017-05-25 13:20:39 +01001101
1102 const int ret = unlink(dump_traces_path);
1103 if (ret == -1) {
1104 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1105 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001106 }
1107 }
1108
Narayan Kamathbd863722017-06-01 18:50:12 +01001109 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001110 if (ds.anr_data_.size() > 0) {
Chris Morin5a50d482022-02-01 17:41:18 -08001111 // The "last" ANR will always be present in the body of the main entry.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001112 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Chris Morin5a50d482022-02-01 17:41:18 -08001113 "VM TRACES AT LAST ANR", false /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001114
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001115 // Historical ANRs are always included as separate entries in the bugreport zip file.
Chris Morin5a50d482022-02-01 17:41:18 -08001116 AddDumps(ds.anr_data_.begin(), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001117 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001118 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001119 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1120 }
1121}
1122
1123static void AddAnrTraceFiles() {
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001124 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001125
Chris Morin5a50d482022-02-01 17:41:18 -08001126 AddAnrTraceDir(anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001127
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001128 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1129
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001130 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001131 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001132 int i = 0;
1133 while (true) {
1134 const std::string slow_trace_path =
1135 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1136 if (stat(slow_trace_path.c_str(), &st)) {
1137 // No traces file at this index, done with the files.
1138 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001139 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001140 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1141 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001142 }
1143}
1144
Wei Wang509bb5d2017-06-09 14:42:12 -07001145static void DumpBlockStatFiles() {
1146 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001147
Wei Wang1dc1ef52017-06-12 11:28:37 -07001148 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1149
1150 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001151 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1152 return;
1153 }
1154
1155 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001156 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001157 if ((d->d_name[0] == '.')
1158 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1159 || (d->d_name[1] == '\0'))) {
1160 continue;
1161 }
1162 const std::string new_path =
1163 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1164 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1165 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1166 printf("\n");
1167 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001168 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001169}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001170
1171static void DumpPacketStats() {
1172 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001173}
1174
1175static void DumpIpAddrAndRules() {
1176 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1177 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1178 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1179 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1180 RunCommand("IP RULES", {"ip", "rule", "show"});
1181 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1182}
1183
Nandana Dutt5c390032019-03-12 10:52:56 +00001184static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1185 std::chrono::milliseconds timeout,
1186 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001187 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001188 sp<android::IServiceManager> sm = defaultServiceManager();
1189 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001190 Vector<String16> args;
1191 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001192 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1193 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001194 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001195 std::string path(title);
1196 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001197 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001198 if (PropertiesHelper::IsDryRun()) {
1199 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1200 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1201 } else {
1202 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1203 if (status == OK) {
1204 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1205 std::chrono::duration<double> elapsed_seconds;
1206 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1207 service == String16("meminfo")) {
1208 // Use a longer timeout for meminfo, since 30s is not always enough.
1209 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1210 /* as_proto = */ false, elapsed_seconds,
1211 bytes_written);
1212 } else {
1213 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1214 /* as_proto = */ false, elapsed_seconds,
1215 bytes_written);
1216 }
1217 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1218 bool dump_complete = (status == OK);
1219 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001220 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001221 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001222
1223 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1224 std::chrono::steady_clock::now() - start);
1225 if (elapsed_duration > timeout) {
1226 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1227 elapsed_duration.count());
1228 break;
1229 }
1230 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001231 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001232}
1233
Vishnu Nair64afc022018-02-01 15:29:34 -08001234static void RunDumpsysText(const std::string& title, int priority,
1235 std::chrono::milliseconds timeout,
1236 std::chrono::milliseconds service_timeout) {
1237 DurationReporter duration_reporter(title);
1238 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1239 fsync(STDOUT_FILENO);
1240 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1241}
1242
1243/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001244static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1245 std::chrono::milliseconds timeout,
1246 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001247 DurationReporter duration_reporter(title);
1248 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1249 fsync(STDOUT_FILENO);
1250 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1251 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001252
1253 RETURN_IF_USER_DENIED_CONSENT();
1254
1255 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1256 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001257}
1258
Nandana Dutt5c390032019-03-12 10:52:56 +00001259static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1260 std::chrono::milliseconds timeout,
1261 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001262 sp<android::IServiceManager> sm = defaultServiceManager();
1263 Dumpsys dumpsys(sm.get());
1264 Vector<String16> args;
1265 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1266 DurationReporter duration_reporter(title);
1267
1268 auto start = std::chrono::steady_clock::now();
1269 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1270 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001271 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001272 std::string path(kProtoPath);
1273 path.append(String8(service).c_str());
1274 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1275 path.append("_CRITICAL");
1276 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1277 path.append("_HIGH");
1278 }
1279 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001280 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001281 if (status == OK) {
1282 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1283 bool dumpTerminated = (status == OK);
1284 dumpsys.stopDumpThread(dumpTerminated);
1285 }
1286 ZipWriter::FileEntry file_entry;
1287 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001288
1289 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1290 std::chrono::steady_clock::now() - start);
1291 if (elapsed_duration > timeout) {
1292 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1293 elapsed_duration.count());
1294 break;
1295 }
1296 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001297 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001298}
1299
Nandana Dutta7db6342018-11-21 14:53:34 +00001300// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001301static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001302 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1303 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001304
1305 RETURN_IF_USER_DENIED_CONSENT();
1306
1307 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1308 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001309}
1310
1311// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001312static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001313 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1314 // high priority. Reduce timeout once they are able to dump in a shorter time or
1315 // moved to a parallel task.
1316 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1317 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001318
1319 RETURN_IF_USER_DENIED_CONSENT();
1320
1321 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1322 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001323}
1324
1325// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001326static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001327 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001328
1329 RETURN_IF_USER_DENIED_CONSENT();
1330
1331 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1332 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001333}
1334
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001335/*
1336 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1337 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1338 * if it's not running in the parallel task.
1339 */
1340static void DumpHals(int out_fd = STDOUT_FILENO) {
Yifan Hong30528a22020-08-07 18:24:06 -07001341 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001342 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1343 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001344
Steven Moreland44cd9482018-01-04 16:24:13 -08001345 using android::hidl::manager::V1_0::IServiceManager;
1346 using android::hardware::defaultServiceManager;
1347
1348 sp<IServiceManager> sm = defaultServiceManager();
1349 if (sm == nullptr) {
1350 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1351 return;
1352 }
1353
1354 auto ret = sm->list([&](const auto& interfaces) {
1355 for (const std::string& interface : interfaces) {
1356 std::string cleanName = interface;
1357 std::replace_if(cleanName.begin(),
1358 cleanName.end(),
1359 [](char c) {
1360 return !isalnum(c) &&
1361 std::string("@-_:.").find(c) == std::string::npos;
1362 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001363 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001364
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001365 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001366 {
1367 auto fd = android::base::unique_fd(
1368 TEMP_FAILURE_RETRY(open(path.c_str(),
1369 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1370 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1371 if (fd < 0) {
1372 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1373 continue;
1374 }
1375 RunCommandToFd(fd,
1376 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001377 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001378 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1379
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001380 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001381 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001382 if (!empty) {
1383 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1384 path);
1385 } else {
1386 unlink(path.c_str());
1387 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001388 }
1389 });
1390
1391 if (!ret.isOk()) {
1392 MYLOGE("Could not list hals from hwservicemanager.\n");
1393 }
1394}
1395
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001396static void DumpExternalFragmentationInfo() {
1397 struct stat st;
1398 if (stat("/proc/buddyinfo", &st) != 0) {
1399 MYLOGE("Unable to dump external fragmentation info\n");
1400 return;
1401 }
1402
1403 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1404 std::ifstream ifs("/proc/buddyinfo");
1405 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1406 for (std::string line; std::getline(ifs, line);) {
1407 std::smatch match_results;
1408 if (std::regex_match(line, match_results, unusable_index_regex)) {
1409 std::stringstream free_pages(std::string{match_results[3]});
1410 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1411 std::istream_iterator<int>());
1412
1413 int total_free_pages = 0;
1414 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1415 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1416 }
1417
1418 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1419 match_results[2].str().c_str());
1420
1421 int usable_free_pages = total_free_pages;
1422 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1423 auto unusable_index = (total_free_pages - usable_free_pages) /
1424 static_cast<double>(total_free_pages);
1425 printf(" %5.3f", unusable_index);
1426 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1427 }
1428
1429 printf("\n");
1430 }
1431 }
1432 printf("\n");
1433}
1434
mhasankd451a472020-05-26 18:02:39 -07001435static void DumpstateLimitedOnly() {
1436 // Trimmed-down version of dumpstate to only include a whitelisted
1437 // set of logs (system log, event log, and system server / system app
1438 // crashes, and networking logs). See b/136273873 and b/138459828
1439 // for context.
1440 DurationReporter duration_reporter("DUMPSTATE");
1441 unsigned long timeout_ms;
1442 // calculate timeout
1443 timeout_ms = logcat_timeout({"main", "system", "crash"});
1444 RunCommand("SYSTEM LOG",
1445 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1446 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1447 timeout_ms = logcat_timeout({"events"});
1448 RunCommand(
1449 "EVENT LOG",
1450 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1451 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1452
1453 printf("========================================================\n");
1454 printf("== Networking Service\n");
1455 printf("========================================================\n");
1456
1457 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1458 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001459 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1460 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001461
1462 printf("========================================================\n");
1463 printf("== Dropbox crashes\n");
1464 printf("========================================================\n");
1465
1466 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1467 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1468
1469 printf("========================================================\n");
1470 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1471 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1472 printf("========================================================\n");
1473 printf("== dumpstate: done (id %d)\n", ds.id_);
1474 printf("========================================================\n");
1475}
1476
Rhed Jaoe017f982020-07-21 17:58:41 +08001477/*
1478 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1479 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1480 * if it's not running in the parallel task.
1481 */
1482static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1483 dprintf(out_fd, "========================================================\n");
1484 dprintf(out_fd, "== Checkins\n");
1485 dprintf(out_fd, "========================================================\n");
1486
1487 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1488 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1489 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1490 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1491 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1492 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1493}
1494
1495/*
1496 * Runs dumpsys on activity service to dump all application activities, services
1497 * and providers in the device.
1498 *
1499 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1500 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1501 * if it's not running in the parallel task.
1502 */
1503static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1504 dprintf(out_fd, "========================================================\n");
1505 dprintf(out_fd, "== Running Application Activities\n");
1506 dprintf(out_fd, "========================================================\n");
1507
1508 // The following dumpsys internally collects output from running apps, so it can take a long
1509 // time. So let's extend the timeout.
1510
1511 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1512
1513 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1514
1515 dprintf(out_fd, "========================================================\n");
1516 dprintf(out_fd, "== Running Application Services (platform)\n");
1517 dprintf(out_fd, "========================================================\n");
1518
1519 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1520 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1521
1522 dprintf(out_fd, "========================================================\n");
1523 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1524 dprintf(out_fd, "========================================================\n");
1525
1526 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1527 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1528
1529 dprintf(out_fd, "========================================================\n");
1530 dprintf(out_fd, "== Running Application Providers (platform)\n");
1531 dprintf(out_fd, "========================================================\n");
1532
1533 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001534 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001535
1536 dprintf(out_fd, "========================================================\n");
1537 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1538 dprintf(out_fd, "========================================================\n");
1539
1540 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1541 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1542}
1543
Nandana Dutt5c390032019-03-12 10:52:56 +00001544// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1545// via the consent they are shown. Ignores other errors that occur while running various
1546// commands. The consent checking is currently done around long running tasks, which happen to
1547// be distributed fairly evenly throughout the function.
1548static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001549 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001550
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001551 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1552 if (ds.dump_pool_) {
1553 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1554 // drop root user. Restarts it with two threads for the parallel run.
1555 ds.dump_pool_->start(/* thread_counts = */2);
1556
1557 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1558 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1559 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaoe017f982020-07-21 17:58:41 +08001560 ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001561 }
1562
Nandana Dutt5c390032019-03-12 10:52:56 +00001563 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1564 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1565 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001566 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001567 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001568 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001569 DumpFile("MEMORY INFO", "/proc/meminfo");
1570 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001571 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001572
1573 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1574
Sunny Goyal35949782019-11-19 15:54:36 -08001575 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1576
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001577 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1578 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1579 DumpFile("SLAB INFO", "/proc/slabinfo");
1580 DumpFile("ZONEINFO", "/proc/zoneinfo");
1581 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1582 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001583 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001584
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001585 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1586 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001587
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001588 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001589 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001590
1591 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1592 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001593
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001594 if (ds.dump_pool_) {
1595 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1596 } else {
1597 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1598 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001599
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001600 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001601 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001602 struct stat s;
1603 if (stat("/proc/modules", &s) != 0) {
1604 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1605 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001606 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001607 RunCommand("MODULES INFO",
1608 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1609 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1610 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001611 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001612
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001613 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001614 DoKernelLogcat();
1615 } else {
1616 do_dmesg();
1617 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001618
Felipe Lemef0292972016-11-22 13:57:05 -08001619 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001620
1621 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1622
Jeff Brown1dc94e32014-09-11 14:15:27 -07001623 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001624 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001625
Jack Yu5a6b2e22020-08-14 18:13:35 +08001626 /* Dump Nfc NCI logs */
1627 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001628
Paul Chang0d2aad72020-02-13 20:04:03 +08001629 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001630 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001631 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001632 }
1633
Felipe Lemee184f662016-10-27 10:04:47 -07001634 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001635
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001636 MaybeAddSystemTraceToZip();
1637
Narayan Kamath8f788292017-05-25 13:20:39 +01001638 // NOTE: tombstones are always added as separate entries in the zip archive
1639 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001640 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001641 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001642 if (!tombstones_dumped) {
1643 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001644 }
1645
Jayachandran Ca94c7172017-06-10 15:08:12 -07001646 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001647
Chenbo Feng276a3b62018-08-07 11:44:49 -07001648 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1649
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001650 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001651
Jayachandran Ca94c7172017-06-10 15:08:12 -07001652 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001653
1654 dump_route_tables();
1655
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001656 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1657 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1658 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001659
Nandana Dutt5c390032019-03-12 10:52:56 +00001660 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001661
Chiachang Wang668ede42021-05-17 17:14:20 +08001662 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1663 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1664 // dump with priority parameters to dump high priority information.
1665 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1666 CommandOptions::WithTimeout(10).Build());
1667
Elliott Hughes23ccc622017-02-28 10:14:22 -08001668 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001669
Jin Qianf334d662017-10-10 14:41:37 -07001670 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001671
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001672 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001673
Colin Crossf45fa6b2012-03-26 12:38:26 -07001674 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001675 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1676 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1677
1678 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1679 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1680 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1681 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1682 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001683
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001684 /* Add window and surface trace files. */
1685 if (!PropertiesHelper::IsUserBuild()) {
1686 ds.AddDir(WMTRACE_DATA_DIR, false);
1687 }
1688
Yifan Hongd90cc652020-02-08 16:52:02 -08001689 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1690
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001691 if (ds.dump_pool_) {
1692 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1693 } else {
1694 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1695 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001696
Steven Moreland7440ddb2016-12-15 16:13:39 -08001697 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001698 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1699 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001700 // su does not exist on user builds, so try running without it.
1701 // This way any implementations of vril-dump that do not require
1702 // root can run on user builds.
1703 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001704 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001705 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001706 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001707 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001708 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001709 }
1710
Felipe Lemed8b94e52016-12-08 10:21:44 -08001711 printf("========================================================\n");
1712 printf("== Android Framework Services\n");
1713 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714
Nandana Dutt5c390032019-03-12 10:52:56 +00001715 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001716
Jack He91ff2fe2021-02-18 18:23:43 -08001717 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1718 ds.AddDir("/data/misc/bluetooth/logs", true);
1719
Rhed Jaoe017f982020-07-21 17:58:41 +08001720 if (ds.dump_pool_) {
1721 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
1722 } else {
1723 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1724 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001725
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001726 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001727
Adrian Roos8b397ab2017-04-04 16:35:44 -07001728 printf("========================================================\n");
1729 printf("== Dropbox crashes\n");
1730 printf("========================================================\n");
1731
1732 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1733 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1734
Felipe Lemed8b94e52016-12-08 10:21:44 -08001735 printf("========================================================\n");
1736 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1737 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1738 printf("========================================================\n");
1739 printf("== dumpstate: done (id %d)\n", ds.id_);
1740 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001741
1742 printf("========================================================\n");
1743 printf("== Obtaining statsd metadata\n");
1744 printf("========================================================\n");
1745 // This differs from the usual dumpsys stats, which is the stats report data.
1746 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001747
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001748 // Add linker configuration directory
1749 ds.AddDir(LINKERCONFIG_DIR, true);
1750
Li Li830179f2022-01-04 12:53:29 -08001751 /* Dump frozen cgroupfs */
1752 dump_frozen_cgroupfs();
Li Li2eedd412021-06-30 15:11:53 -07001753
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001754 if (ds.dump_pool_) {
1755 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1756 } else {
1757 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1758 DumpIncidentReport);
1759 }
Mike Ma5c267872019-08-21 11:31:34 -07001760
Nandana Dutt5c390032019-03-12 10:52:56 +00001761 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001762}
1763
Nandana Dutt5c390032019-03-12 10:52:56 +00001764/*
1765 * Dumps state for the default case; drops root after it's no longer necessary.
1766 *
1767 * Returns RunStatus::OK if everything went fine.
1768 * Returns RunStatus::ERROR if there was an error.
1769 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1770 * with the caller.
1771 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001772Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001773 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1774 // buffer.
1775 DoLogcat();
1776 // Capture timestamp after first logcat to use in next logcat
1777 time_t logcat_ts = time(nullptr);
1778
Nandana Dutt4be45d12018-09-26 15:04:23 +01001779 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao5377d792020-07-16 17:37:39 +08001780 if (dump_pool_) {
1781 RETURN_IF_USER_DENIED_CONSENT();
1782 // One thread is enough since we only need to enqueue DumpTraces here.
1783 dump_pool_->start(/* thread_counts = */1);
1784
1785 // DumpTraces takes long time, post it to the another thread in the
1786 // pool, if pool is available
1787 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1788 } else {
1789 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1790 &dump_traces_path);
1791 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001792
1793 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001794 if (!PropertiesHelper::IsDryRun()) {
Chris Morinc2cba7a2022-02-01 17:06:50 -08001795 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX);
1796 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX);
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001797 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001798
1799 ds.AddDir(RECOVERY_DIR, true);
1800 ds.AddDir(RECOVERY_DATA_DIR, true);
1801 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1802 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1803 if (!PropertiesHelper::IsUserBuild()) {
1804 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1805 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001806 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001807 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001808 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001809 add_mountinfo();
1810 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001811 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001812 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001813
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001814 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001815 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1816
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001817 // Dump IPsec stats. No keys are exposed here.
1818 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1819
Nandana Dutt4be45d12018-09-26 15:04:23 +01001820 // Run ss as root so we can see socket marks.
1821 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1822
1823 // Run iotop as root to show top 100 IO threads
1824 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1825
Erick Reyese68df822019-02-11 14:46:36 -08001826 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001827 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1828 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001829
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001830 DumpFile("PSI cpu", "/proc/pressure/cpu");
1831 DumpFile("PSI memory", "/proc/pressure/memory");
1832 DumpFile("PSI io", "/proc/pressure/io");
1833
Rhed Jao5377d792020-07-16 17:37:39 +08001834 if (dump_pool_) {
1835 RETURN_IF_USER_DENIED_CONSENT();
1836 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1837
1838 // Current running thread in the pool is the root user also. Shutdown
1839 // the pool and restart later to ensure all threads in the pool could
1840 // drop the root user.
1841 dump_pool_->shutdown();
1842 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001843 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001844 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001845 }
1846
Nandana Dutt5c390032019-03-12 10:52:56 +00001847 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001848 Dumpstate::RunStatus status = dumpstate();
1849 // Capture logcat since the last time we did it.
1850 DoSystemLogcat(logcat_ts);
1851 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001852}
1853
Rhed Jaob5685b32020-08-14 17:19:17 +08001854// Common states for telephony and wifi which are needed to be collected before
1855// dumpstate drop the root user.
1856static void DumpstateRadioAsRoot() {
1857 DumpIpTablesAsRoot();
1858 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1859}
1860
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001861// This method collects common dumpsys for telephony and wifi. Typically, wifi
1862// reports are fine to include all information, but telephony reports on user
1863// builds need to strip some content (see DumpstateTelephonyOnly).
1864static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001865 // We need to be picky about some stuff for telephony reports on user builds.
1866 if (!include_sensitive_info) {
1867 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1868 DoRadioLogcat();
1869 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001870 // DumpHals takes long time, post it to the another thread in the pool,
1871 // if pool is available.
1872 if (ds.dump_pool_) {
1873 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1874 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001875 // Contains various system properties and process startup info.
1876 do_dmesg();
1877 // Logs other than the radio buffer may contain package/component names and potential PII.
1878 DoLogcat();
1879 // Too broad for connectivity problems.
1880 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001881 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1882 if (ds.dump_pool_) {
1883 ds.dump_pool_->waitForTask(DUMP_HALS_TASK);
1884 } else {
1885 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1886 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001887 }
1888
Jayachandran Ca94c7172017-06-10 15:08:12 -07001889 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001890 DumpIpAddrAndRules();
1891 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001892 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1893 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001894}
1895
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001896// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1897// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1898// for what can be included on user builds: all reported information MUST directly relate to
1899// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1900// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1901// names are not), and MUST NOT contain logs of user application traffic.
1902// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001903static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001904 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001905
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001906 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001907
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001908 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001909
Rhed Jaob5685b32020-08-14 17:19:17 +08001910 DumpstateRadioAsRoot();
1911 if (!DropRootUser()) {
1912 return;
1913 }
1914
1915 // Starts thread pool after the root user is dropped, and two additional threads
1916 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1917 if (ds.dump_pool_) {
1918 ds.dump_pool_->start(/*thread_counts =*/2);
1919
1920 // DumpstateBoard takes long time, post it to the another thread in the pool,
1921 // if pool is available.
1922 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1923 }
1924
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001925 DumpstateRadioCommon(include_sensitive_info);
1926
1927 if (include_sensitive_info) {
1928 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1929 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1930 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1931 // way.
1932 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1933 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001934
1935 printf("========================================================\n");
1936 printf("== Android Framework Services\n");
1937 printf("========================================================\n");
1938
Vishnu Nair652cc802017-11-30 15:18:30 -08001939 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1940 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001941 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1942 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001943 if (include_sensitive_info) {
1944 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1945 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1946 SEC_TO_MSEC(10));
1947 } else {
1948 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1949 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1950 // give a higher timeout as well.
1951 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1952 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1953 }
1954 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001955 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1956 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001957 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001958 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1959 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001960 if (include_sensitive_info) {
1961 // Contains raw IP addresses, omit from reports on user builds.
1962 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1963 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1964 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1965 SEC_TO_MSEC(10));
1966 // Contains package/component names, omit from reports on user builds.
1967 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1968 SEC_TO_MSEC(10));
1969 // Contains package names, but should be relatively simple to remove them (also contains
1970 // UIDs already), omit from reports on user builds.
1971 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1972 SEC_TO_MSEC(10));
1973 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001974
1975 printf("========================================================\n");
1976 printf("== Running Application Services\n");
1977 printf("========================================================\n");
1978
1979 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1980
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001981 if (include_sensitive_info) {
1982 printf("========================================================\n");
1983 printf("== Running Application Services (non-platform)\n");
1984 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001985
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001986 // Contains package/component names and potential PII, omit from reports on user builds.
1987 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1988 // carrier_config dumpsys instead.
1989 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1990 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001991
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001992 printf("========================================================\n");
1993 printf("== Checkins\n");
1994 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001995
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001996 // Contains package/component names, omit from reports on user builds.
1997 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1998 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001999
2000 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002001 printf("== dumpstate: done (id %d)\n", ds.id_);
2002 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002003
2004 if (ds.dump_pool_) {
2005 ds.dump_pool_->waitForTask(DUMP_BOARD_TASK);
2006 } else {
2007 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2008 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002009}
2010
mukesh agrawal253dad42018-01-23 21:59:59 -08002011// This method collects dumpsys for wifi debugging only
2012static void DumpstateWifiOnly() {
2013 DurationReporter duration_reporter("DUMPSTATE");
2014
Rhed Jaob5685b32020-08-14 17:19:17 +08002015 DumpstateRadioAsRoot();
2016 if (!DropRootUser()) {
2017 return;
2018 }
2019
2020 // Starts thread pool after the root user is dropped. Only one additional
2021 // thread is needed for DumpHals in the DumpstateRadioCommon.
2022 if (ds.dump_pool_) {
2023 ds.dump_pool_->start(/*thread_counts =*/1);
2024 }
2025
mukesh agrawal253dad42018-01-23 21:59:59 -08002026 DumpstateRadioCommon();
2027
2028 printf("========================================================\n");
2029 printf("== Android Framework Services\n");
2030 printf("========================================================\n");
2031
2032 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2033 SEC_TO_MSEC(10));
2034 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2035 SEC_TO_MSEC(10));
2036
2037 printf("========================================================\n");
2038 printf("== dumpstate: done (id %d)\n", ds.id_);
2039 printf("========================================================\n");
2040}
2041
Nandana Duttcf419a72019-03-14 10:40:17 +00002042Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002043 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002044 const size_t buf_size = temp_file_pattern.length() + 1;
2045 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2046 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2047
2048 // Create a new, empty file to receive all trace dumps.
2049 //
2050 // TODO: This can be simplified once we remove support for the old style
2051 // dumps. We can have a file descriptor passed in to dump_traces instead
2052 // of creating a file, closing it and then reopening it again.
2053 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2054 if (fd < 0) {
2055 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002056 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002057 }
2058
2059 // Nobody should have access to this temporary file except dumpstate, but we
2060 // temporarily grant 'read' to 'others' here because this file is created
2061 // when tombstoned is still running as root, but dumped after dropping. This
2062 // can go away once support for old style dumping has.
2063 const int chmod_ret = fchmod(fd, 0666);
2064 if (chmod_ret < 0) {
2065 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002066 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002067 }
2068
2069 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2070 if (proc.get() == nullptr) {
2071 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002072 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002073 }
2074
2075 // Number of times process dumping has timed out. If we encounter too many
2076 // failures, we'll give up.
2077 int timeout_failures = 0;
2078 bool dalvik_found = false;
2079
2080 const std::set<int> hal_pids = get_interesting_hal_pids();
2081
2082 struct dirent* d;
2083 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002084 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002085 int pid = atoi(d->d_name);
2086 if (pid <= 0) {
2087 continue;
2088 }
2089
2090 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2091 std::string exe;
2092 if (!android::base::Readlink(link_name, &exe)) {
2093 continue;
2094 }
2095
2096 bool is_java_process;
2097 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2098 // Don't bother dumping backtraces for the zygote.
2099 if (IsZygote(pid)) {
2100 continue;
2101 }
2102
2103 dalvik_found = true;
2104 is_java_process = true;
2105 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2106 is_java_process = false;
2107 } else {
2108 // Probably a native process we don't care about, continue.
2109 continue;
2110 }
2111
2112 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2113 if (timeout_failures == 3) {
2114 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2115 break;
2116 }
2117
2118 const uint64_t start = Nanotime();
2119 const int ret = dump_backtrace_to_file_timeout(
2120 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2121 is_java_process ? 5 : 20, fd);
2122
2123 if (ret == -1) {
2124 // For consistency, the header and footer to this message match those
2125 // dumped by debuggerd in the success case.
2126 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2127 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2128 dprintf(fd, "---- end %d ----", pid);
2129 timeout_failures++;
2130 continue;
2131 }
2132
2133 // We've successfully dumped stack traces, reset the failure count
2134 // and write a summary of the elapsed time to the file and continue with the
2135 // next process.
2136 timeout_failures = 0;
2137
2138 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2139 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2140 }
2141
2142 if (!dalvik_found) {
2143 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2144 }
2145
Nandana Duttcf419a72019-03-14 10:40:17 +00002146 *path = file_name_buf.release();
2147 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002148}
2149
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002150static dumpstate_hal_hidl::DumpstateMode GetDumpstateHalModeHidl(
2151 const Dumpstate::BugreportMode bugreport_mode) {
2152 switch (bugreport_mode) {
2153 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2154 return dumpstate_hal_hidl::DumpstateMode::FULL;
2155 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2156 return dumpstate_hal_hidl::DumpstateMode::INTERACTIVE;
2157 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2158 return dumpstate_hal_hidl::DumpstateMode::REMOTE;
2159 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2160 return dumpstate_hal_hidl::DumpstateMode::WEAR;
2161 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2162 return dumpstate_hal_hidl::DumpstateMode::CONNECTIVITY;
2163 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2164 return dumpstate_hal_hidl::DumpstateMode::WIFI;
2165 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2166 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2167 }
2168 return dumpstate_hal_hidl::DumpstateMode::DEFAULT;
2169}
2170
2171static dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode GetDumpstateHalModeAidl(
2172 const Dumpstate::BugreportMode bugreport_mode) {
2173 switch (bugreport_mode) {
2174 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2175 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::FULL;
2176 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2177 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::INTERACTIVE;
2178 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2179 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::REMOTE;
2180 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2181 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WEAR;
2182 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2183 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::CONNECTIVITY;
2184 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2185 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::WIFI;
2186 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2187 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2188 }
2189 return dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode::DEFAULT;
2190}
2191
2192static void DoDumpstateBoardHidl(
2193 const sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_1_0,
2194 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2195 const Dumpstate::BugreportMode bugreport_mode,
2196 const size_t timeout_sec) {
2197
2198 using ScopedNativeHandle =
2199 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2200 ScopedNativeHandle handle(native_handle_create(static_cast<int>(dumpstate_fds.size()), 0),
2201 [](native_handle_t* handle) {
2202 // we don't close file handle's here
2203 // via native_handle_close(handle)
2204 // instead we let dumpstate_fds close the file handles when
2205 // dumpstate_fds gets destroyed
2206 native_handle_delete(handle);
2207 });
2208 if (handle == nullptr) {
2209 MYLOGE("Could not create native_handle for dumpstate HAL\n");
2210 return;
2211 }
2212
2213 for (size_t i = 0; i < dumpstate_fds.size(); i++) {
2214 handle.get()->data[i] = dumpstate_fds[i].get();
2215 }
2216
2217 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2218 // implement just 1.0.
2219 const char* descriptor_to_kill;
2220 using DumpstateBoardTask = std::packaged_task<bool()>;
2221 DumpstateBoardTask dumpstate_board_task;
2222 sp<dumpstate_hal_hidl::IDumpstateDevice> dumpstate_hal(
2223 dumpstate_hal_hidl::IDumpstateDevice::castFrom(dumpstate_hal_1_0));
2224 if (dumpstate_hal != nullptr) {
2225 MYLOGI("Using IDumpstateDevice v1.1 HIDL HAL");
2226
2227 dumpstate_hal_hidl::DumpstateMode dumpstate_hal_mode =
2228 GetDumpstateHalModeHidl(bugreport_mode);
2229
2230 descriptor_to_kill = dumpstate_hal_hidl::IDumpstateDevice::descriptor;
2231 dumpstate_board_task =
2232 DumpstateBoardTask([timeout_sec, dumpstate_hal_mode, dumpstate_hal, &handle]() -> bool {
2233 ::android::hardware::Return<dumpstate_hal_hidl::DumpstateStatus> status =
2234 dumpstate_hal->dumpstateBoard_1_1(handle.get(), dumpstate_hal_mode,
2235 SEC_TO_MSEC(timeout_sec));
2236 if (!status.isOk()) {
2237 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2238 return false;
2239 } else if (status != dumpstate_hal_hidl::DumpstateStatus::OK) {
2240 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n",
2241 dumpstate_hal_hidl::toString(status).c_str());
2242 return false;
2243 }
2244 return true;
2245 });
2246 } else {
2247 MYLOGI("Using IDumpstateDevice v1.0 HIDL HAL");
2248
2249 descriptor_to_kill = dumpstate_hal_hidl_1_0::IDumpstateDevice::descriptor;
2250 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal_1_0, &handle]() -> bool {
2251 ::android::hardware::Return<void> status =
2252 dumpstate_hal_1_0->dumpstateBoard(handle.get());
2253 if (!status.isOk()) {
2254 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2255 return false;
2256 }
2257 return true;
2258 });
2259 }
2260 auto result = dumpstate_board_task.get_future();
2261 std::thread(std::move(dumpstate_board_task)).detach();
2262
2263 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2264 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2265 if (!android::base::SetProperty(
2266 "ctl.interface_restart",
2267 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2268 MYLOGE("Couldn't restart dumpstate HAL\n");
2269 }
2270 }
2271 // Wait some time for init to kill dumpstate vendor HAL
2272 constexpr size_t killing_timeout_sec = 10;
2273 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2274 MYLOGE(
2275 "killing dumpstateBoard timed out after %zus, continue and "
2276 "there might be racing in content\n",
2277 killing_timeout_sec);
2278 }
2279}
2280
2281static void DoDumpstateBoardAidl(
2282 const std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal,
2283 const std::vector<::ndk::ScopedFileDescriptor>& dumpstate_fds,
2284 const Dumpstate::BugreportMode bugreport_mode, const size_t timeout_sec) {
2285 MYLOGI("Using IDumpstateDevice AIDL HAL");
2286
2287 const char* descriptor_to_kill;
2288 using DumpstateBoardTask = std::packaged_task<bool()>;
2289 DumpstateBoardTask dumpstate_board_task;
2290 dumpstate_hal_aidl::IDumpstateDevice::DumpstateMode dumpstate_hal_mode =
2291 GetDumpstateHalModeAidl(bugreport_mode);
2292
2293 descriptor_to_kill = dumpstate_hal_aidl::IDumpstateDevice::descriptor;
2294 dumpstate_board_task = DumpstateBoardTask([dumpstate_hal, &dumpstate_fds, dumpstate_hal_mode,
2295 timeout_sec]() -> bool {
2296 auto status = dumpstate_hal->dumpstateBoard(dumpstate_fds, dumpstate_hal_mode, timeout_sec);
2297
2298 if (!status.isOk()) {
2299 MYLOGE("dumpstateBoard failed: %s\n", status.getDescription().c_str());
2300 return false;
2301 }
2302 return true;
2303 });
2304 auto result = dumpstate_board_task.get_future();
2305 std::thread(std::move(dumpstate_board_task)).detach();
2306
2307 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2308 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate HAL\n", timeout_sec);
2309 if (!android::base::SetProperty(
2310 "ctl.interface_restart",
2311 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
2312 MYLOGE("Couldn't restart dumpstate HAL\n");
2313 }
2314 }
2315 // Wait some time for init to kill dumpstate vendor HAL
2316 constexpr size_t killing_timeout_sec = 10;
2317 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2318 MYLOGE(
2319 "killing dumpstateBoard timed out after %zus, continue and "
2320 "there might be racing in content\n",
2321 killing_timeout_sec);
2322 }
2323}
2324
2325static std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> GetDumpstateBoardAidlService() {
2326 const std::string aidl_instance_name =
2327 std::string(dumpstate_hal_aidl::IDumpstateDevice::descriptor) + "/default";
2328
2329 if (!AServiceManager_isDeclared(aidl_instance_name.c_str())) {
2330 return nullptr;
2331 }
2332
2333 ndk::SpAIBinder dumpstateBinder(AServiceManager_waitForService(aidl_instance_name.c_str()));
2334
2335 return dumpstate_hal_aidl::IDumpstateDevice::fromBinder(dumpstateBinder);
2336}
2337
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002338void Dumpstate::DumpstateBoard(int out_fd) {
2339 dprintf(out_fd, "========================================================\n");
2340 dprintf(out_fd, "== Board\n");
2341 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002342
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002343 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002344 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002345 * set to true and unmount it after invoking dumpstateBoard_* methods.
2346 * This is to enable debug builds to not have debugfs mounted during runtime.
2347 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002348 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002349 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002350 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002351 if (mount_debugfs) {
2352 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2353 AS_ROOT_20);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002354 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002355 }
2356
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002357 std::vector<std::string> paths;
2358 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002359 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002360 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2361 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002362 remover.emplace_back(android::base::make_scope_guard(
2363 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002364 }
Jie Song9fbfad02017-06-20 16:29:42 -07002365
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002366 // get dumpstate HAL AIDL implementation
2367 std::shared_ptr<dumpstate_hal_aidl::IDumpstateDevice> dumpstate_hal_handle_aidl(
2368 GetDumpstateBoardAidlService());
2369 if (dumpstate_hal_handle_aidl == nullptr) {
2370 MYLOGI("No IDumpstateDevice AIDL implementation\n");
2371 }
2372
2373 // get dumpstate HAL HIDL implementation, only if AIDL HAL implementation not found
2374 sp<dumpstate_hal_hidl_1_0::IDumpstateDevice> dumpstate_hal_handle_hidl_1_0 = nullptr;
2375 if (dumpstate_hal_handle_aidl == nullptr) {
2376 dumpstate_hal_handle_hidl_1_0 = dumpstate_hal_hidl_1_0::IDumpstateDevice::getService();
2377 if (dumpstate_hal_handle_hidl_1_0 == nullptr) {
2378 MYLOGI("No IDumpstateDevice HIDL implementation\n");
2379 }
2380 }
2381
2382 // if neither HIDL nor AIDL implementation found, then return
2383 if (dumpstate_hal_handle_hidl_1_0 == nullptr && dumpstate_hal_handle_aidl == nullptr) {
2384 MYLOGE("Could not find IDumpstateDevice implementation\n");
Wei Wang587eac92018-04-05 12:17:20 -07002385 return;
2386 }
2387
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002388 // this is used to hold the file descriptors and when this variable goes out of scope
2389 // the file descriptors are closed
2390 std::vector<::ndk::ScopedFileDescriptor> dumpstate_fds;
Wei Wang587eac92018-04-05 12:17:20 -07002391
Nandana Dutt5c390032019-03-12 10:52:56 +00002392 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002393 for (size_t i = 0; i < paths.size(); i++) {
2394 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2395
2396 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2397 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2398 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2399 if (fd < 0) {
2400 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2401 return;
2402 }
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002403
2404 dumpstate_fds.emplace_back(fd.release());
2405 // we call fd.release() here to make sure "fd" does not get closed
2406 // after "fd" goes out of scope after this block.
2407 // "fd" will be closed when "dumpstate_fds" goes out of scope
2408 // i.e. when we exit this function
Wei Wang587eac92018-04-05 12:17:20 -07002409 }
2410
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002411 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2412 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2413 // will kill the HAL and grab whatever it dumped in time.
2414 constexpr size_t timeout_sec = 30;
Wei Wang587eac92018-04-05 12:17:20 -07002415
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002416 if (dumpstate_hal_handle_aidl != nullptr) {
2417 DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
2418 timeout_sec);
2419 } else if (dumpstate_hal_handle_hidl_1_0 != nullptr) {
2420 // run HIDL HAL only if AIDL HAL not found
2421 DoDumpstateBoardHidl(dumpstate_hal_handle_hidl_1_0, dumpstate_fds, options_->bugreport_mode,
2422 timeout_sec);
Wei Wang587eac92018-04-05 12:17:20 -07002423 }
2424
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002425 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002426 auto keep_debugfs_mounted =
2427 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2428 if (keep_debugfs_mounted.empty())
2429 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002430 }
2431
Wei Wang587eac92018-04-05 12:17:20 -07002432 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2433 for (size_t i = 0; i < paths.size(); i++) {
2434 struct stat s;
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002435 if (fstat(dumpstate_fds[i].get(), &s) == -1) {
2436 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(), strerror(errno));
Wei Wang587eac92018-04-05 12:17:20 -07002437 file_sizes[i] = -1;
2438 continue;
2439 }
2440 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002441 }
2442
2443 for (size_t i = 0; i < paths.size(); i++) {
2444 if (file_sizes[i] == -1) {
2445 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002446 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002447 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002448 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002449 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002450 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002451 remover[i].Disable();
2452 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2453 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002454 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002455}
2456
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002457static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002458 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002459 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2460 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002461 " -h: display this help message\n"
2462 " -b: play sound file instead of vibrate, at beginning of job\n"
2463 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002464 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002465 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002466 " -s: write zipped file to control socket (for init)\n"
2467 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002468 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002469 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002470 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002471 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002472 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002473 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002474}
2475
Wei Liuf87959e2016-08-26 14:51:42 -07002476static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002477 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002478}
2479
Felipe Leme1d486fe2016-10-14 18:06:47 -07002480bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002481 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2482 if (zip_entry_tasks_) {
2483 zip_entry_tasks_->run(/* do_cancel = */false);
2484 }
2485
Felipe Leme9a523ae2016-10-20 15:10:33 -07002486 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002487 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002488 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002489 // Final timestamp
2490 char date[80];
2491 time_t the_real_now_please_stand_up = time(nullptr);
2492 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002493 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002494 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002495
Felipe Leme9a523ae2016-10-20 15:10:33 -07002496 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002497 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002498 return false;
2499 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002500 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002501 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002502 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002503 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002504
Felipe Leme0f3fb202016-06-10 17:10:53 -07002505 // Add log file (which contains stderr output) to zip...
2506 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002507 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002508 MYLOGE("Failed to add dumpstate log to .zip file\n");
2509 return false;
2510 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002511 // TODO: Should truncate the existing file.
2512 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002513 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2514 return false;
2515 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002516 fprintf(stderr, "\n");
2517
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002518 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002519 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002520 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002521 return false;
2522 }
2523
Felipe Leme1d486fe2016-10-14 18:06:47 -07002524 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2525 ds.zip_file.reset(nullptr);
2526
Felipe Lemee9d2c542016-11-15 11:48:26 -08002527 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002528 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002529
Felipe Leme1e9edc62015-12-21 16:02:13 -08002530 return true;
2531}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002532
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002533static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2534 // clang-format off
2535 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2536 "--receiver-foreground", "--receiver-include-background", "-a", action};
2537 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002538
2539 am.insert(am.end(), args.begin(), args.end());
2540
Felipe Leme8d2410e2017-02-08 09:46:08 -08002541 RunCommand("", am,
2542 CommandOptions::WithTimeout(20)
2543 .Log("Sending broadcast: '%s'\n")
2544 .Always()
2545 .DropRoot()
2546 .RedirectStderr()
2547 .Build());
2548}
2549
Felipe Leme35b8cf12017-02-10 15:47:29 -08002550static void Vibrate(int duration_ms) {
2551 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002552 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2553 "oneshot", std::to_string(duration_ms)};
2554 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002555 CommandOptions::WithTimeout(10)
2556 .Log("Vibrate: '%s'\n")
2557 .Always()
2558 .Build());
2559 // clang-format on
2560}
2561
Nandana Dutt979388e2018-11-30 16:48:55 +00002562static void MaybeResolveSymlink(std::string* path) {
2563 std::string resolved_path;
2564 if (android::base::Readlink(*path, &resolved_path)) {
2565 *path = resolved_path;
2566 }
2567}
2568
Nandana Dutt4be45d12018-09-26 15:04:23 +01002569/*
2570 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002571 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002572 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002573static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002574 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2575
Nandana Dutt4be45d12018-09-26 15:04:23 +01002576 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2577 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002578 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002579 char date[80];
2580 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2581 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002582
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002583 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002584 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002585 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002586 ds.base_name_ += "-wifi";
2587 }
2588
Paul Chang0d2aad72020-02-13 20:04:03 +08002589 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002590 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002591 }
2592 ds.tmp_path_ = ds.GetPath(".tmp");
2593 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2594
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002595 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002596 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002597 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002598 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002599 "Bugreport dir: [%s] "
2600 "Base name: [%s] "
2601 "Suffix: [%s] "
2602 "Log path: [%s] "
2603 "Temporary path: [%s] "
2604 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002605 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2606 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002607
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002608 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2609 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2610 create_parent_dirs(ds.path_.c_str());
2611 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2612 if (ds.zip_file == nullptr) {
2613 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2614 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002615 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002616 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2617 ds.AddTextZipEntry("version.txt", ds.version_);
2618 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002619}
2620
2621/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002622 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002623 * printing zipped file status, etc.
2624 */
2625static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002626 bool do_text_file = !ds.FinishZipFile();
2627 if (do_text_file) {
2628 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002629 }
mhasank2d75c442020-06-11 15:05:25 -07002630
2631 std::string final_path = ds.path_;
2632 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002633 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002634 android::os::CopyFileToFile(ds.path_, final_path);
2635 }
2636
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002637 if (ds.options_->stream_to_socket) {
2638 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2639 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002640 if (do_text_file) {
2641 dprintf(ds.control_socket_fd_,
2642 "FAIL:could not create zip file, check %s "
2643 "for more details\n",
2644 ds.log_path_.c_str());
2645 } else {
mhasank2d75c442020-06-11 15:05:25 -07002646 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002647 }
2648 }
2649}
2650
Nandana Dutt4be45d12018-09-26 15:04:23 +01002651
Nandana Dutt58d72e22018-11-16 10:30:48 +00002652static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2653 switch (mode) {
2654 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2655 return "BUGREPORT_FULL";
2656 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2657 return "BUGREPORT_INTERACTIVE";
2658 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2659 return "BUGREPORT_REMOTE";
2660 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2661 return "BUGREPORT_WEAR";
2662 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2663 return "BUGREPORT_TELEPHONY";
2664 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2665 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002666 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2667 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002668 }
2669}
2670
Paul Changf59c2b72020-03-10 02:08:55 +08002671static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2672 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002673 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2674 // default system screenshots.
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002675 options->bugreport_mode = mode;
2676 options->bugreport_mode_string = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002677 switch (mode) {
2678 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002679 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002680 break;
2681 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002682 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002683 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002684 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002685 break;
2686 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002687 options->do_vibrate = false;
2688 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002689 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002690 break;
2691 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002692 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002693 options->do_screenshot = is_screenshot_requested;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002694 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002695 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002696 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002697 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002698 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002699 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002700 break;
2701 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002702 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002703 options->do_screenshot = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002704 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002705 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2706 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002707 }
2708}
2709
Nandana Dutt58d72e22018-11-16 10:30:48 +00002710static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002711 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002712 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002713 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002714 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002715 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002716 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002717 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002718 options.telephony_only, options.wifi_only,
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002719 options.do_progress_updates, options.bugreport_fd.get(),
2720 options.bugreport_mode_string.c_str(),
2721 options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002722}
2723
Nandana Dutt54dbd672019-01-11 12:58:05 +00002724void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2725 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002726 const android::base::unique_fd& screenshot_fd_in,
2727 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002728 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2729 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2730 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002731
Paul Changf59c2b72020-03-10 02:08:55 +08002732 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002733}
2734
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002735Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2736 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002737 int c;
mhasankd451a472020-05-26 18:02:39 -07002738 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002739 switch (c) {
2740 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002741 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002742 case 's': stream_to_socket = true; break;
2743 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002744 case 'v': show_header_only = true; break;
2745 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002746 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002747 case 'P': do_progress_updates = true; break;
2748 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002749 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002750 case 'V':
2751 case 'd':
2752 case 'z':
2753 // compatibility no-op
2754 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002755 case 'w':
2756 // This was already processed
2757 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002758 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002759 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002760 break;
2761 default:
2762 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002763 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002764 break;
2765 // clang-format on
2766 }
2767 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002768
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002769 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002770 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002771 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002772 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002773 }
2774 }
2775
2776 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2777 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002778
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002779 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002780}
2781
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002782bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002783 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002784 return false;
2785 }
2786
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002787 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002788 return false;
2789 }
2790
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002791 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002792 return false;
2793 }
2794 return true;
2795}
2796
Nandana Dutt197661d2018-11-16 16:40:21 +00002797void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2798 options_ = std::move(options);
2799}
2800
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002801void Dumpstate::Initialize() {
2802 /* gets the sequential id */
2803 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2804 id_ = ++last_id;
2805 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2806}
2807
Nandana Duttd2f5f082019-01-18 17:13:52 +00002808Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2809 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002810 if (listener_ != nullptr) {
2811 switch (status) {
2812 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002813 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002814 break;
2815 case Dumpstate::RunStatus::HELP:
2816 break;
2817 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002818 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002819 break;
2820 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002821 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2822 break;
2823 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2824 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2825 break;
2826 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2827 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002828 break;
2829 }
2830 }
2831 return status;
2832}
2833
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002834void Dumpstate::Cancel() {
2835 CleanupTmpFiles();
2836 android::os::UnlinkAndLogOnError(log_path_);
2837 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2838 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2839 kDumpstateBoardFiles[i]);
2840 }
2841 tombstone_data_.clear();
2842 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002843
2844 // Instead of shutdown the pool, we delete temporary files directly since
2845 // shutdown blocking the call.
2846 if (dump_pool_) {
2847 dump_pool_->deleteTempFiles();
2848 }
2849 if (zip_entry_tasks_) {
2850 zip_entry_tasks_->run(/*do_cancel =*/ true);
2851 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002852}
2853
Nandana Dutt979388e2018-11-30 16:48:55 +00002854/*
2855 * Dumps relevant information to a bugreport based on the given options.
2856 *
2857 * The bugreport can be dumped to a file or streamed to a socket.
2858 *
2859 * How dumping to file works:
2860 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2861 * stderr is redirected a log file.
2862 *
2863 * The temporary bugreport is then populated via printfs, dumping contents of files and
2864 * output of commands to stdout.
2865 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002866 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002867 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002868 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002869 *
mhasank2d75c442020-06-11 15:05:25 -07002870 * Bugreports are first generated in a local directory and later copied to the caller's fd
2871 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002872 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002873Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2874 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002875 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002876 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002877 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002878 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002879 return RunStatus::INVALID_INPUT;
2880 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002881 /* set as high priority, and protect from OOM killer */
2882 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002883
Felipe Lemed071c682016-10-20 16:48:00 -07002884 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002885 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002886 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002887 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002888 } else {
2889 /* fallback to kernels <= 2.6.35 */
2890 oom_adj = fopen("/proc/self/oom_adj", "we");
2891 if (oom_adj) {
2892 fputs("-17", oom_adj);
2893 fclose(oom_adj);
2894 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002895 }
2896
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002897 if (version_ == VERSION_DEFAULT) {
2898 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002899 }
2900
Chris Morin5a50d482022-02-01 17:41:18 -08002901 if (version_ != VERSION_CURRENT) {
2902 MYLOGE("invalid version requested ('%s'); supported values are: ('%s', '%s')\n",
2903 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002904 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002905 }
2906
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002907 if (options_->show_header_only) {
2908 PrintHeader();
2909 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002910 }
2911
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002912 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2913 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002914
Felipe Leme7447d7c2016-11-03 18:12:22 -07002915 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002916 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002917 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002918 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002919
Sahana Raof35ed432019-07-12 10:47:52 +01002920 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2921 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2922 } else {
2923 // Wake lock will be released automatically on process death
2924 MYLOGD("Wake lock acquired.\n");
2925 }
2926
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002927 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002928
Felipe Lemef0292972016-11-22 13:57:05 -08002929 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002930 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2931 }
2932
Nandana Dutt235c6672019-11-14 15:22:32 +00002933 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
Kedar Chitnis9fd8c052021-11-16 09:09:22 +00002934 id_, options_->args.c_str(), options_->bugreport_mode_string.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002935
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002937
Christopher Ferrised9354f2014-10-01 17:35:01 -07002938 // If we are going to use a socket, do it as early as possible
2939 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002940 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002941 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002942 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002943 if (control_socket_fd_ == -1) {
2944 return ERROR;
2945 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002946 if (options_->progress_updates_to_socket) {
2947 options_->do_progress_updates = 1;
2948 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002949 }
2950
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002951 if (!PrepareToWriteToFile()) {
2952 return ERROR;
2953 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002954
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002955 // Interactive, wear & telephony modes are default to true.
2956 // and may enable from cli option or when using control socket
2957 if (options_->do_progress_updates) {
2958 // clang-format off
2959 std::vector<std::string> am_args = {
2960 "--receiver-permission", "android.permission.DUMP",
2961 };
2962 // clang-format on
2963 // Send STARTED broadcast for apps that listen to bugreport generation events
2964 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2965 if (options_->progress_updates_to_socket) {
2966 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002967 }
2968 }
2969
Nick Kralevichf3599b32016-01-25 15:05:16 -08002970 /* read /proc/cmdline before dropping root */
2971 FILE *cmdline = fopen("/proc/cmdline", "re");
2972 if (cmdline) {
2973 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2974 fclose(cmdline);
2975 }
2976
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002977 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002978 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002979 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002980
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002981 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002982 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2983 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002984 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002985 }
2986 }
2987
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002988 int dup_stdout_fd;
2989 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002990 // Redirect stderr to log_path_ for debugging.
2991 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2992 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2993 return ERROR;
2994 }
2995 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2996 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2997 strerror(errno));
2998 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002999
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003000 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
3001 // moved into zip file later, if zipping.
3002 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
3003 // TODO: why not write to a file instead of stdout to overcome this problem?
3004 /* TODO: rather than generating a text file now and zipping it later,
3005 it would be more efficient to redirect stdout to the zip entry
3006 directly, but the libziparchive doesn't support that option yet. */
3007 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
3008 return ERROR;
3009 }
3010 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
3011 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
3012 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003013 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08003014
3015 // Don't buffer stdout
3016 setvbuf(stdout, nullptr, _IONBF, 0);
3017
Rhed Jao5377d792020-07-16 17:37:39 +08003018 // Enable the parallel run if the client requests to output to a file.
3019 EnableParallelRunIfNeeded();
3020 // Using scope guard to make sure the dump pool can be shut down correctly.
3021 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
3022 ShutdownDumpPool();
3023 });
3024
Felipe Leme608385d2016-02-01 10:35:38 -08003025 // NOTE: there should be no stdout output until now, otherwise it would break the header.
3026 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08003027 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003028 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003029
Gavin Corkery6968f552020-11-22 18:09:05 +00003030 bool is_dumpstate_restricted = options_->telephony_only
3031 || options_->wifi_only
3032 || options_->limited_only;
3033 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08003034 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08003035 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00003036 }
3037 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003038
3039 if (!is_dumpstate_restricted) {
3040 // Snapshot the system trace now (if running) to avoid that dumpstate's
3041 // own activity pushes out interesting data from the trace ring buffer.
3042 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
3043 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08003044
3045 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
3046 // from WMTRACE_DATA_DIR.
3047 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003048 }
Gavin Corkery6968f552020-11-22 18:09:05 +00003049 onUiIntensiveBugreportDumpsFinished(calling_uid);
3050 MaybeCheckUserConsent(calling_uid, calling_package);
3051 if (options_->telephony_only) {
3052 DumpstateTelephonyOnly(calling_package);
3053 } else if (options_->wifi_only) {
3054 DumpstateWifiOnly();
3055 } else if (options_->limited_only) {
3056 DumpstateLimitedOnly();
3057 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01003058 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08003059 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00003060 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01003061 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00003062 HandleUserConsentDenied();
3063 }
3064 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08003065 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07003066 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07003067
Felipe Leme55b42a62015-11-10 17:39:08 -08003068 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003069 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07003070
Abhijeet Kaure370d682019-10-01 16:49:30 +01003071 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003072 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07003073
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003074 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00003075 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01003076 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003077 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003078 if (status != Dumpstate::RunStatus::OK &&
3079 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3080 // Do an early return if there were errors. We make an exception for consent
3081 // timing out because it's possible the user got distracted. In this case the
3082 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003083 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00003084 return status;
3085 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003086 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
3087 MYLOGI(
3088 "Did not receive user consent yet."
3089 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01003090 const String16 incidentcompanion("incidentcompanion");
3091 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
3092 if (ics != nullptr) {
3093 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3094 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3095 consent_callback_.get());
3096 } else {
3097 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3098 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003099 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003100 }
3101
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003102 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003103 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003104 for (int i = 0; i < 3; i++) {
3105 Vibrate(75);
3106 usleep((75 + 50) * 1000);
3107 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003108 }
3109
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003110 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3111 progress_->GetInitialMax());
3112 progress_->Save();
3113 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003114
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003115 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003116
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003117 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003118 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003119 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003120 }
3121
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003122 tombstone_data_.clear();
3123 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003124
Nandana Duttd2f5f082019-01-18 17:13:52 +00003125 return (consent_callback_ != nullptr &&
3126 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3127 ? USER_CONSENT_TIMED_OUT
3128 : RunStatus::OK;
3129}
3130
Paul Chang0d2aad72020-02-13 20:04:03 +08003131void Dumpstate::MaybeTakeEarlyScreenshot() {
3132 if (!options_->do_screenshot || !do_early_screenshot_) {
3133 return;
3134 }
3135
3136 TakeScreenshot();
3137}
3138
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003139void Dumpstate::MaybeSnapshotSystemTrace() {
3140 // If a background system trace is happening and is marked as "suitable for
3141 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3142 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3143 // case that no trace is ongoing, this command is a no-op.
3144 // Note: this should not be enqueued as we need to freeze the trace before
3145 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3146 // the dumpstate's own activity which is irrelevant.
3147 int res = RunCommand(
3148 "SERIALIZE PERFETTO TRACE",
3149 {"perfetto", "--save-for-bugreport"},
3150 CommandOptions::WithTimeout(10)
3151 .DropRoot()
3152 .CloseAllFileDescriptorsOnExec()
3153 .Build());
3154 has_system_trace_ = res == 0;
3155 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3156 // file in the later stages.
3157}
3158
Yohei Yukawa95305b32021-03-09 07:54:27 -08003159void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003160 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3161 for (const auto& service : {"window", "input_method"}) {
3162 RunCommand(
3163 // Empty name because it's not intended to be classified as a bugreport section.
3164 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3165 "", {"cmd", service, "tracing", "save-for-bugreport"},
3166 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3167 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003168}
3169
Paul Changeb4b4642020-05-28 22:05:47 +08003170void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003171 if (calling_uid == AID_SHELL || !CalledByApi()) {
3172 return;
3173 }
3174 if (listener_ != nullptr) {
3175 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3176 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003177 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003178 }
3179}
3180
Jichao Lie89d9c12019-11-21 19:02:51 -08003181void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3182 if (calling_uid == AID_SHELL || !CalledByApi()) {
3183 // No need to get consent for shell triggered dumpstates, or not through
3184 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003185 return;
3186 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003187 consent_callback_ = new ConsentCallback();
3188 const String16 incidentcompanion("incidentcompanion");
3189 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003190 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003191 if (ics != nullptr) {
3192 MYLOGD("Checking user consent via incidentcompanion service\n");
3193 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003194 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003195 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003196 } else {
3197 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3198 }
3199}
3200
Nandana Dutt5c390032019-03-12 10:52:56 +00003201bool Dumpstate::IsUserConsentDenied() const {
3202 return ds.consent_callback_ != nullptr &&
3203 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3204}
3205
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003206bool Dumpstate::CalledByApi() const {
3207 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3208}
3209
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003210void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003211 android::os::UnlinkAndLogOnError(tmp_path_);
3212 android::os::UnlinkAndLogOnError(screenshot_path_);
3213 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003214 if (dump_traces_path != nullptr) {
3215 android::os::UnlinkAndLogOnError(dump_traces_path);
3216 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003217}
3218
Rhed Jao5377d792020-07-16 17:37:39 +08003219void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003220 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003221 return;
3222 }
3223 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003224 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003225}
3226
3227void Dumpstate::ShutdownDumpPool() {
3228 if (dump_pool_) {
3229 dump_pool_->shutdown();
3230 dump_pool_ = nullptr;
3231 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003232 if (zip_entry_tasks_) {
3233 zip_entry_tasks_->run(/* do_cancel = */true);
3234 zip_entry_tasks_ = nullptr;
3235 }
3236}
3237
3238void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3239 const std::string& entry_path) {
3240 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3241 if (!task_cancelled) {
3242 AddZipEntry(entry_name, entry_path);
3243 }
3244 android::os::UnlinkAndLogOnError(entry_path);
3245 };
3246 if (zip_entry_tasks_) {
3247 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3248 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3249 } else {
3250 // Invokes AddZipEntryAndCleanup immediately
3251 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3252 }
Rhed Jao5377d792020-07-16 17:37:39 +08003253}
3254
Nandana Duttd2f5f082019-01-18 17:13:52 +00003255Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3256 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003257 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003258 return USER_CONSENT_DENIED;
3259}
3260
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003261Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003262 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003263 // user consent (unless the caller is Shell).
3264 UserConsentResult consent_result;
3265 if (calling_uid == AID_SHELL) {
3266 consent_result = UserConsentResult::APPROVED;
3267 } else {
3268 consent_result = consent_callback_->getResult();
3269 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003270 if (consent_result == UserConsentResult::UNAVAILABLE) {
3271 // User has not responded yet.
3272 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003273 // Telephony is a fast report type, particularly on user builds where information may be
3274 // more aggressively limited. To give the user time to read the consent dialog, increase the
3275 // timeout.
3276 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3277 : USER_CONSENT_TIMEOUT_MS;
3278 if (elapsed_ms < timeout_ms) {
3279 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003280 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3281 sleep(delay_seconds);
3282 }
3283 consent_result = consent_callback_->getResult();
3284 }
3285 if (consent_result == UserConsentResult::DENIED) {
3286 // User has explicitly denied sharing with the app. To be safe delete the
3287 // internal bugreport & tmp files.
3288 return HandleUserConsentDenied();
3289 }
3290 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003291 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3292 if (copy_succeeded) {
3293 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003294 if (options_->do_screenshot &&
3295 options_->screenshot_fd.get() != -1 &&
3296 !options_->is_screenshot_copied) {
3297 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3298 options_->screenshot_fd.get());
3299 options_->is_screenshot_copied = copy_succeeded;
3300 if (copy_succeeded) {
3301 android::os::UnlinkAndLogOnError(screenshot_path_);
3302 }
3303 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003304 }
3305 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3306 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3307 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3308 // Since we do not have user consent to share the bugreport it does not get
3309 // copied over to the calling app but remains in the internal directory from
3310 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003311 std::string final_path = GetPath(".zip");
3312 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3313 if (copy_succeeded) {
3314 android::os::UnlinkAndLogOnError(path_);
3315 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003316 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3317 }
3318 // Unknown result; must be a programming error.
3319 MYLOGE("Unknown user consent result:%d\n", consent_result);
3320 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003321}
3322
Nandana Duttf02564e2019-02-15 15:24:24 +00003323Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003324 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3325 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3326 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003327 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003328 // When directly running dumpstate binary, the output is not expected to be written
3329 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003330 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003331
3332 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003333 // an app; they are irrelevant here because bugreport is triggered via command line.
3334 // Update Last ID before calling Run().
3335 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003336 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003337 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003338 return status;
3339}
3340
3341/* Main entry point for dumpstate binary. */
3342int run_main(int argc, char* argv[]) {
3343 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003344
3345 switch (status) {
3346 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003347 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003348 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003349 ShowUsage();
3350 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003351 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003352 fprintf(stderr, "Invalid combination of args\n");
3353 ShowUsage();
3354 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003355 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003356 FALLTHROUGH_INTENDED;
3357 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3358 FALLTHROUGH_INTENDED;
3359 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003360 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003361 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003362}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003363
3364// TODO(111441001): Default DumpOptions to sensible values.
3365Dumpstate::Dumpstate(const std::string& version)
3366 : pid_(getpid()),
3367 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003368 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003369 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003370 now_(time(nullptr)),
3371 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003372}
3373
3374Dumpstate& Dumpstate::GetInstance() {
3375 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3376 return singleton_;
3377}
3378
Rhed Jao5377d792020-07-16 17:37:39 +08003379DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3380 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3381 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003382 if (!title_.empty()) {
3383 started_ = Nanotime();
3384 }
3385}
3386
3387DurationReporter::~DurationReporter() {
3388 if (!title_.empty()) {
3389 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003390 if (elapsed >= .5f || verbose_) {
3391 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003392 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003393 if (!logcat_only_) {
3394 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003395 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3396 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003397 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003398 }
3399}
3400
3401const int32_t Progress::kDefaultMax = 5000;
3402
3403Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3404}
3405
3406Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3407 : Progress(initial_max, growth_factor, "") {
3408 progress_ = progress;
3409}
3410
3411Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3412 : initial_max_(initial_max),
3413 progress_(0),
3414 max_(initial_max),
3415 growth_factor_(growth_factor),
3416 n_runs_(0),
3417 average_max_(0),
3418 path_(path) {
3419 if (!path_.empty()) {
3420 Load();
3421 }
3422}
3423
3424void Progress::Load() {
3425 MYLOGD("Loading stats from %s\n", path_.c_str());
3426 std::string content;
3427 if (!android::base::ReadFileToString(path_, &content)) {
3428 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3429 return;
3430 }
3431 if (content.empty()) {
3432 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3433 return;
3434 }
3435 std::vector<std::string> lines = android::base::Split(content, "\n");
3436
3437 if (lines.size() < 1) {
3438 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3439 (int)lines.size(), max_);
3440 return;
3441 }
3442 char* ptr;
3443 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3444 average_max_ = strtol(ptr, nullptr, 10);
3445 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3446 average_max_ > STATS_MAX_AVERAGE) {
3447 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3448 initial_max_ = Progress::kDefaultMax;
3449 } else {
3450 initial_max_ = average_max_;
3451 }
3452 max_ = initial_max_;
3453
3454 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3455}
3456
3457void Progress::Save() {
3458 int32_t total = n_runs_ * average_max_ + progress_;
3459 int32_t runs = n_runs_ + 1;
3460 int32_t average = floor(((float)total) / runs);
3461 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3462 path_.c_str());
3463 if (path_.empty()) {
3464 return;
3465 }
3466
3467 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3468 if (!android::base::WriteStringToFile(content, path_)) {
3469 MYLOGE("Could not save stats on %s\n", path_.c_str());
3470 }
3471}
3472
3473int32_t Progress::Get() const {
3474 return progress_;
3475}
3476
3477bool Progress::Inc(int32_t delta_sec) {
3478 bool changed = false;
3479 if (delta_sec >= 0) {
3480 progress_ += delta_sec;
3481 if (progress_ > max_) {
3482 int32_t old_max = max_;
3483 max_ = floor((float)progress_ * growth_factor_);
3484 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3485 changed = true;
3486 }
3487 }
3488 return changed;
3489}
3490
3491int32_t Progress::GetMax() const {
3492 return max_;
3493}
3494
3495int32_t Progress::GetInitialMax() const {
3496 return initial_max_;
3497}
3498
3499void Progress::Dump(int fd, const std::string& prefix) const {
3500 const char* pr = prefix.c_str();
3501 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3502 dprintf(fd, "%smax: %d\n", pr, max_);
3503 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3504 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3505 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3506 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3507 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3508}
3509
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003510std::string Dumpstate::GetPath(const std::string& suffix) const {
3511 return GetPath(bugreport_internal_dir_, suffix);
3512}
3513
3514std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3515 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3516 name_.c_str(), suffix.c_str());
3517}
3518
3519void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3520 progress_ = std::move(progress);
3521}
3522
3523void for_each_userid(void (*func)(int), const char *header) {
3524 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3525 "for_each_userid(%s)", header);
3526 DurationReporter duration_reporter(title);
3527 if (PropertiesHelper::IsDryRun()) return;
3528
3529 DIR *d;
3530 struct dirent *de;
3531
3532 if (header) printf("\n------ %s ------\n", header);
3533 func(0);
3534
3535 if (!(d = opendir("/data/system/users"))) {
3536 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3537 return;
3538 }
3539
3540 while ((de = readdir(d))) {
3541 int userid;
3542 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3543 continue;
3544 }
3545 func(userid);
3546 }
3547
3548 closedir(d);
3549}
3550
3551static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3552 DIR *d;
3553 struct dirent *de;
3554
3555 if (!(d = opendir("/proc"))) {
3556 printf("Failed to open /proc (%s)\n", strerror(errno));
3557 return;
3558 }
3559
3560 if (header) printf("\n------ %s ------\n", header);
3561 while ((de = readdir(d))) {
3562 if (ds.IsUserConsentDenied()) {
3563 MYLOGE(
3564 "Returning early because user denied consent to share bugreport with calling app.");
3565 closedir(d);
3566 return;
3567 }
3568 int pid;
3569 int fd;
3570 char cmdpath[255];
3571 char cmdline[255];
3572
3573 if (!(pid = atoi(de->d_name))) {
3574 continue;
3575 }
3576
3577 memset(cmdline, 0, sizeof(cmdline));
3578
3579 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3580 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3581 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3582 close(fd);
3583 if (cmdline[0]) {
3584 helper(pid, cmdline, arg);
3585 continue;
3586 }
3587 }
3588
3589 // if no cmdline, a kernel thread has comm
3590 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3591 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3592 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3593 close(fd);
3594 if (cmdline[1]) {
3595 cmdline[0] = '[';
3596 size_t len = strcspn(cmdline, "\f\b\r\n");
3597 cmdline[len] = ']';
3598 cmdline[len+1] = '\0';
3599 }
3600 }
3601 if (!cmdline[0]) {
3602 strcpy(cmdline, "N/A");
3603 }
3604 helper(pid, cmdline, arg);
3605 }
3606
3607 closedir(d);
3608}
3609
3610static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3611 for_each_pid_func *func = (for_each_pid_func*) arg;
3612 func(pid, cmdline);
3613}
3614
3615void for_each_pid(for_each_pid_func func, const char *header) {
3616 std::string title = header == nullptr ? "for_each_pid"
3617 : android::base::StringPrintf("for_each_pid(%s)", header);
3618 DurationReporter duration_reporter(title);
3619 if (PropertiesHelper::IsDryRun()) return;
3620
3621 __for_each_pid(for_each_pid_helper, header, (void *) func);
3622}
3623
3624static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3625 DIR *d;
3626 struct dirent *de;
3627 char taskpath[255];
3628 for_each_tid_func *func = (for_each_tid_func *) arg;
3629
3630 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3631
3632 if (!(d = opendir(taskpath))) {
3633 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3634 return;
3635 }
3636
3637 func(pid, pid, cmdline);
3638
3639 while ((de = readdir(d))) {
3640 if (ds.IsUserConsentDenied()) {
3641 MYLOGE(
3642 "Returning early because user denied consent to share bugreport with calling app.");
3643 closedir(d);
3644 return;
3645 }
3646 int tid;
3647 int fd;
3648 char commpath[255];
3649 char comm[255];
3650
3651 if (!(tid = atoi(de->d_name))) {
3652 continue;
3653 }
3654
3655 if (tid == pid)
3656 continue;
3657
3658 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3659 memset(comm, 0, sizeof(comm));
3660 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3661 strcpy(comm, "N/A");
3662 } else {
3663 char *c;
3664 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3665 close(fd);
3666
3667 c = strrchr(comm, '\n');
3668 if (c) {
3669 *c = '\0';
3670 }
3671 }
3672 func(pid, tid, comm);
3673 }
3674
3675 closedir(d);
3676}
3677
3678void for_each_tid(for_each_tid_func func, const char *header) {
3679 std::string title = header == nullptr ? "for_each_tid"
3680 : android::base::StringPrintf("for_each_tid(%s)", header);
3681 DurationReporter duration_reporter(title);
3682
3683 if (PropertiesHelper::IsDryRun()) return;
3684
3685 __for_each_pid(for_each_tid_helper, header, (void *) func);
3686}
3687
3688void show_wchan(int pid, int tid, const char *name) {
3689 if (PropertiesHelper::IsDryRun()) return;
3690
3691 char path[255];
3692 char buffer[255];
3693 int fd, ret, save_errno;
3694 char name_buffer[255];
3695
3696 memset(buffer, 0, sizeof(buffer));
3697
3698 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3699 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3700 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3701 return;
3702 }
3703
3704 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3705 save_errno = errno;
3706 close(fd);
3707
3708 if (ret < 0) {
3709 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3710 return;
3711 }
3712
3713 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3714 pid == tid ? 0 : 3, "", name);
3715
3716 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3717
3718 return;
3719}
3720
3721// print time in centiseconds
3722static void snprcent(char *buffer, size_t len, size_t spc,
3723 unsigned long long time) {
3724 static long hz; // cache discovered hz
3725
3726 if (hz <= 0) {
3727 hz = sysconf(_SC_CLK_TCK);
3728 if (hz <= 0) {
3729 hz = 1000;
3730 }
3731 }
3732
3733 // convert to centiseconds
3734 time = (time * 100 + (hz / 2)) / hz;
3735
3736 char str[16];
3737
3738 snprintf(str, sizeof(str), " %llu.%02u",
3739 time / 100, (unsigned)(time % 100));
3740 size_t offset = strlen(buffer);
3741 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3742 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3743}
3744
3745// print permille as a percent
3746static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3747 char str[16];
3748
3749 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3750 size_t offset = strlen(buffer);
3751 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3752 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3753}
3754
3755void show_showtime(int pid, const char *name) {
3756 if (PropertiesHelper::IsDryRun()) return;
3757
3758 char path[255];
3759 char buffer[1023];
3760 int fd, ret, save_errno;
3761
3762 memset(buffer, 0, sizeof(buffer));
3763
3764 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3765 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3766 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3767 return;
3768 }
3769
3770 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3771 save_errno = errno;
3772 close(fd);
3773
3774 if (ret < 0) {
3775 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3776 return;
3777 }
3778
3779 // field 14 is utime
3780 // field 15 is stime
3781 // field 42 is iotime
3782 unsigned long long utime = 0, stime = 0, iotime = 0;
3783 if (sscanf(buffer,
3784 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3785 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3786 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3787 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3788 &utime, &stime, &iotime) != 3) {
3789 return;
3790 }
3791
3792 unsigned long long total = utime + stime;
3793 if (!total) {
3794 return;
3795 }
3796
3797 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3798 if (permille > 1000) {
3799 permille = 1000;
3800 }
3801
3802 // try to beautify and stabilize columns at <80 characters
3803 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3804 if ((name[0] != '[') || utime) {
3805 snprcent(buffer, sizeof(buffer), 57, utime);
3806 }
3807 snprcent(buffer, sizeof(buffer), 65, stime);
3808 if ((name[0] != '[') || iotime) {
3809 snprcent(buffer, sizeof(buffer), 73, iotime);
3810 }
3811 if (iotime) {
3812 snprdec(buffer, sizeof(buffer), 79, permille);
3813 }
3814 puts(buffer); // adds a trailing newline
3815
3816 return;
3817}
3818
3819void do_dmesg() {
3820 const char *title = "KERNEL LOG (dmesg)";
3821 DurationReporter duration_reporter(title);
3822 printf("------ %s ------\n", title);
3823
3824 if (PropertiesHelper::IsDryRun()) return;
3825
3826 /* Get size of kernel buffer */
3827 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3828 if (size <= 0) {
3829 printf("Unexpected klogctl return value: %d\n\n", size);
3830 return;
3831 }
3832 char *buf = (char *) malloc(size + 1);
3833 if (buf == nullptr) {
3834 printf("memory allocation failed\n\n");
3835 return;
3836 }
3837 int retval = klogctl(KLOG_READ_ALL, buf, size);
3838 if (retval < 0) {
3839 printf("klogctl failure\n\n");
3840 free(buf);
3841 return;
3842 }
3843 buf[retval] = '\0';
3844 printf("%s\n\n", buf);
3845 free(buf);
3846 return;
3847}
3848
3849void do_showmap(int pid, const char *name) {
3850 char title[255];
3851 char arg[255];
3852
3853 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3854 snprintf(arg, sizeof(arg), "%d", pid);
3855 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3856}
3857
3858int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3859 DurationReporter duration_reporter(title);
3860
3861 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3862
3863 UpdateProgress(WEIGHT_FILE);
3864
3865 return status;
3866}
3867
3868int read_file_as_long(const char *path, long int *output) {
3869 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3870 if (fd < 0) {
3871 int err = errno;
3872 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3873 return -1;
3874 }
3875 char buffer[50];
3876 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3877 if (bytes_read == -1) {
3878 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3879 return -2;
3880 }
3881 if (bytes_read == 0) {
3882 MYLOGE("File %s is empty\n", path);
3883 return -3;
3884 }
3885 *output = atoi(buffer);
3886 return 0;
3887}
3888
3889/* calls skip to gate calling dump_from_fd recursively
3890 * in the specified directory. dump_from_fd defaults to
3891 * dump_file_from_fd above when set to NULL. skip defaults
3892 * to false when set to NULL. dump_from_fd will always be
3893 * called with title NULL.
3894 */
3895int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3896 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3897 DurationReporter duration_reporter(title);
3898 DIR *dirp;
3899 struct dirent *d;
3900 char *newpath = nullptr;
3901 const char *slash = "/";
3902 int retval = 0;
3903
3904 if (!title.empty()) {
3905 printf("------ %s (%s) ------\n", title.c_str(), dir);
3906 }
3907 if (PropertiesHelper::IsDryRun()) return 0;
3908
3909 if (dir[strlen(dir) - 1] == '/') {
3910 ++slash;
3911 }
3912 dirp = opendir(dir);
3913 if (dirp == nullptr) {
3914 retval = -errno;
3915 MYLOGE("%s: %s\n", dir, strerror(errno));
3916 return retval;
3917 }
3918
3919 if (!dump_from_fd) {
3920 dump_from_fd = dump_file_from_fd;
3921 }
3922 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3923 if ((d->d_name[0] == '.')
3924 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3925 || (d->d_name[1] == '\0'))) {
3926 continue;
3927 }
3928 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3929 (d->d_type == DT_DIR) ? "/" : "");
3930 if (!newpath) {
3931 retval = -errno;
3932 continue;
3933 }
3934 if (skip && (*skip)(newpath)) {
3935 continue;
3936 }
3937 if (d->d_type == DT_DIR) {
3938 int ret = dump_files("", newpath, skip, dump_from_fd);
3939 if (ret < 0) {
3940 retval = ret;
3941 }
3942 continue;
3943 }
3944 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3945 if (fd.get() < 0) {
3946 retval = -1;
3947 printf("*** %s: %s\n", newpath, strerror(errno));
3948 continue;
3949 }
3950 (*dump_from_fd)(nullptr, newpath, fd.get());
3951 }
3952 closedir(dirp);
3953 if (!title.empty()) {
3954 printf("\n");
3955 }
3956 return retval;
3957}
3958
3959/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3960 * it's possible to avoid issues where opening the file itself can get
3961 * stuck.
3962 */
3963int dump_file_from_fd(const char *title, const char *path, int fd) {
3964 if (PropertiesHelper::IsDryRun()) return 0;
3965
3966 int flags = fcntl(fd, F_GETFL);
3967 if (flags == -1) {
3968 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3969 return -1;
3970 } else if (!(flags & O_NONBLOCK)) {
3971 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3972 return -1;
3973 }
3974 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3975}
3976
3977int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003978 const CommandOptions& options, bool verbose_duration, int out_fd) {
3979 DurationReporter duration_reporter(title, false /* logcat_only */,
3980 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003981
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003982 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003983
3984 /* TODO: for now we're simplifying the progress calculation by using the
3985 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3986 * where its weight should be much higher proportionally to its timeout.
3987 * Ideally, it should use a options.EstimatedDuration() instead...*/
3988 UpdateProgress(options.Timeout());
3989
3990 return status;
3991}
3992
3993void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08003994 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003995 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3996 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3997 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08003998 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003999}
4000
Dieter Hsu105ad0c2020-09-29 15:23:33 +08004001static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004002 int s = android_get_control_socket(service);
4003 if (s < 0) {
4004 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
4005 return -1;
4006 }
4007 fcntl(s, F_SETFD, FD_CLOEXEC);
4008
4009 // Set backlog to 0 to make sure that queue size will be minimum.
4010 // In Linux, because the minimum queue will be 1, connect() will be blocked
4011 // if the other clients already called connect() and the connection request was not accepted.
4012 if (listen(s, 0) < 0) {
4013 MYLOGE("listen(control socket): %s\n", strerror(errno));
4014 return -1;
4015 }
4016
4017 struct sockaddr addr;
4018 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01004019 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004020
4021 // Close socket just after accept(), to make sure that connect() by client will get error
4022 // when the socket is used by the other services.
4023 // There is still a race condition possibility between accept and close, but there is no way
4024 // to close-on-accept atomically.
4025 // See detail; b/123306389#comment25
4026 close(s);
4027
4028 if (fd < 0) {
4029 MYLOGE("accept(control socket): %s\n", strerror(errno));
4030 return -1;
4031 }
4032
4033 return fd;
4034}
4035
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004036// TODO: should call is_valid_output_file and/or be merged into it.
4037void create_parent_dirs(const char *path) {
4038 char *chp = const_cast<char *> (path);
4039
4040 /* skip initial slash */
4041 if (chp[0] == '/')
4042 chp++;
4043
4044 /* create leading directories, if necessary */
4045 struct stat dir_stat;
4046 while (chp && chp[0]) {
4047 chp = strchr(chp, '/');
4048 if (chp) {
4049 *chp = 0;
4050 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
4051 MYLOGI("Creating directory %s\n", path);
4052 if (mkdir(path, 0770)) { /* drwxrwx--- */
4053 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
4054 } else if (chown(path, AID_SHELL, AID_SHELL)) {
4055 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
4056 }
4057 }
4058 *chp++ = '/';
4059 }
4060 }
4061}
4062
4063bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
4064 create_parent_dirs(path);
4065
4066 int fd = TEMP_FAILURE_RETRY(open(path,
4067 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
4068 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
4069 if (fd < 0) {
4070 MYLOGE("%s: %s\n", path, strerror(errno));
4071 return false;
4072 }
4073
4074 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
4075 close(fd);
4076 return true;
4077}
4078
4079bool redirect_to_file(FILE* redirect, char* path) {
4080 return _redirect_to_file(redirect, path, O_TRUNC);
4081}
4082
4083bool redirect_to_existing_file(FILE* redirect, char* path) {
4084 return _redirect_to_file(redirect, path, O_APPEND);
4085}
4086
4087void dump_route_tables() {
4088 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4089 if (PropertiesHelper::IsDryRun()) return;
4090 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4091 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4092 FILE* fp = fopen(RT_TABLES_PATH, "re");
4093 if (!fp) {
4094 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4095 return;
4096 }
4097 char table[16];
4098 // Each line has an integer (the table number), a space, and a string (the table name). We only
4099 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4100 // Add a fixed max limit so this doesn't go awry.
4101 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4102 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4103 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4104 }
4105 fclose(fp);
4106}
4107
Li Li830179f2022-01-04 12:53:29 -08004108void dump_frozen_cgroupfs(const char *dir, int level,
4109 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
4110 DIR *dirp;
4111 struct dirent *d;
4112 char *newpath = nullptr;
4113
4114 dirp = opendir(dir);
4115 if (dirp == nullptr) {
4116 MYLOGE("%s: %s\n", dir, strerror(errno));
4117 return;
4118 }
4119
4120 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
4121 if ((d->d_name[0] == '.')
4122 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
4123 || (d->d_name[1] == '\0'))) {
4124 continue;
4125 }
4126 if (d->d_type == DT_DIR) {
4127 asprintf(&newpath, "%s/%s/", dir, d->d_name);
4128 if (!newpath) {
4129 continue;
4130 }
4131 if (level == 0 && !strncmp(d->d_name, "uid_", 4)) {
4132 dump_frozen_cgroupfs(newpath, 1, dump_from_fd);
4133 } else if (level == 1 && !strncmp(d->d_name, "pid_", 4)) {
4134 char *freezer = nullptr;
4135 asprintf(&freezer, "%s/%s", newpath, "cgroup.freeze");
4136 if (freezer) {
4137 FILE* fp = fopen(freezer, "r");
4138 if (fp != NULL) {
4139 int frozen;
4140 fscanf(fp, "%d", &frozen);
4141 if (frozen > 0) {
4142 dump_files("", newpath, skip_none, dump_from_fd);
4143 }
4144 fclose(fp);
4145 }
4146 free(freezer);
4147 }
4148 }
4149 }
4150 }
4151 closedir(dirp);
4152}
4153
4154void dump_frozen_cgroupfs() {
Li Li830179f2022-01-04 12:53:29 -08004155 MYLOGD("Adding frozen processes from %s\n", CGROUPFS_DIR);
4156 DurationReporter duration_reporter("FROZEN CGROUPFS");
4157 if (PropertiesHelper::IsDryRun()) return;
4158 dump_frozen_cgroupfs(CGROUPFS_DIR, 0, _add_file_from_fd);
4159}
4160
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004161void Dumpstate::UpdateProgress(int32_t delta_sec) {
4162 if (progress_ == nullptr) {
4163 MYLOGE("UpdateProgress: progress_ not set\n");
4164 return;
4165 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004166 // This function updates progress related members of the dumpstate and reports
4167 // progress percentage to the bugreport client. Since it could be called by
4168 // different dump tasks at the same time if the parallel run is enabled, a
4169 // mutex lock is necessary here to synchronize the call.
4170 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004171
4172 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004173 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004174
4175 // ...but only notifiy listeners when necessary.
4176 if (!options_->do_progress_updates) return;
4177
4178 int progress = progress_->Get();
4179 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004180 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004181
Nandana Dutt402a8392019-06-14 14:25:13 +01004182 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004183 return;
4184 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004185 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004186
4187 if (control_socket_fd_ >= 0) {
4188 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4189 fsync(control_socket_fd_);
4190 }
4191
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004192 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004193 if (percent % 10 == 0) {
4194 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004195 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004196 } else {
4197 // stderr is ignored on normal invocations, but useful when calling
4198 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004199 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004200 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004201
4202 listener_->onProgress(percent);
4203 }
4204}
4205
4206void Dumpstate::TakeScreenshot(const std::string& path) {
4207 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4208 int status =
4209 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4210 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4211 if (status == 0) {
4212 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4213 } else {
4214 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4215 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004216 if (listener_ != nullptr) {
4217 // Show a visual indication to indicate screenshot is taken via
4218 // IDumpstateListener.onScreenshotTaken()
4219 listener_->onScreenshotTaken(status == 0);
4220 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004221}
4222
4223bool is_dir(const char* pathname) {
4224 struct stat info;
4225 if (stat(pathname, &info) == -1) {
4226 return false;
4227 }
4228 return S_ISDIR(info.st_mode);
4229}
4230
4231time_t get_mtime(int fd, time_t default_mtime) {
4232 struct stat info;
4233 if (fstat(fd, &info) == -1) {
4234 return default_mtime;
4235 }
4236 return info.st_mtime;
4237}