blob: eab72f48b0413df3c01560c9c376430e4b4fe4d2 [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
Felipe Leme96c2bbb2016-09-26 09:21:21 -070060#include <android-base/file.h>
61#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070062#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080063#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070064#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070065#include <android-base/unique_fd.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010066#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080067#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080068#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
69#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080070#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000071#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010072#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080073#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070074#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010075#include <cutils/sockets.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000076#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080077#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000078#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010079#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080080#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010081#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070082#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070083#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070084#include <private/android_filesystem_config.h>
85#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080086#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070087#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080088#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070089#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070090#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080091
Hunter Knepshield8540faf2020-02-04 19:47:20 -080092using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
93using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
94using ::android::hardware::dumpstate::V1_1::DumpstateMode;
95using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
96using ::android::hardware::dumpstate::V1_1::toString;
Vishnu Naire97d6122018-01-18 13:58:56 -080097using ::std::literals::chrono_literals::operator""ms;
98using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +080099using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -0800100
Felipe Leme47e9be22016-12-21 15:37:07 -0800101// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800102using android::defaultServiceManager;
103using android::Dumpsys;
104using android::INVALID_OPERATION;
105using android::IServiceManager;
106using android::OK;
107using android::sp;
108using android::status_t;
109using android::String16;
110using android::String8;
111using android::TIMED_OUT;
112using android::UNKNOWN_ERROR;
113using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000114using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000115using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800116using android::os::dumpstate::CommandOptions;
117using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800118using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800119using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800120using android::os::dumpstate::TaskQueue;
Felipe Leme47e9be22016-12-21 15:37:07 -0800121
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100122// Keep in sync with
123// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
124static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
125
126/* Most simple commands have 10 as timeout, so 5 is a good estimate */
127static const int32_t WEIGHT_FILE = 5;
128
129// TODO: temporary variables and functions used during C++ refactoring
130static Dumpstate& ds = Dumpstate::GetInstance();
131static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100132 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800133 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
134 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100135}
136
137// Reasonable value for max stats.
138static const int STATS_MAX_N_RUNS = 1000;
139static const long STATS_MAX_AVERAGE = 100000;
140
141CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
142
Nandana Duttd2f5f082019-01-18 17:13:52 +0000143typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
144
Colin Crossf45fa6b2012-03-26 12:38:26 -0700145/* read before root is shed */
146static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700147static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000148static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800149// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
150// it's often the case that they time out far too quickly for consent with such a hefty dialog for
151// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
152// roughly match full reports' durations.
153static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700154
Felipe Leme1d486fe2016-10-14 18:06:47 -0700155// TODO: variables and functions below should be part of dumpstate object
156
Felipe Leme635ca312016-01-05 14:23:02 -0800157static std::set<std::string> mount_points;
158void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800159
Todd Poynor2a83daa2013-11-22 15:44:22 -0800160#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700161#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700162#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800163
Felipe Lemee82a27d2016-01-05 13:35:44 -0800164#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700165#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700166#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700167#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800168#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100169#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
170#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800171#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900172#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800173#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700174#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800175#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900176#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700177#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Primiano Tuccifaaaafb2021-01-14 12:26:29 +0000178#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
Li Li2eedd412021-06-30 15:11:53 -0700179#define CGROUPFS_DIR "/sys/fs/cgroup"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700180
Narayan Kamath8f788292017-05-25 13:20:39 +0100181// TODO(narayan): Since this information has to be kept in sync
182// with tombstoned, we should just put it in a common header.
183//
184// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100185static const std::string TOMBSTONE_DIR = "/data/tombstones/";
186static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
187static const std::string ANR_DIR = "/data/anr/";
188static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700189
Felipe Lemee844a9d2016-09-21 15:01:39 -0700190// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000191
Nandana Dutt5c390032019-03-12 10:52:56 +0000192#define RETURN_IF_USER_DENIED_CONSENT() \
193 if (ds.IsUserConsentDenied()) { \
194 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
195 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
196 }
197
198// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
199// if consent is found to be denied.
200#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
201 RETURN_IF_USER_DENIED_CONSENT(); \
202 func_ptr(__VA_ARGS__); \
203 RETURN_IF_USER_DENIED_CONSENT();
204
Rhed Jao5377d792020-07-16 17:37:39 +0800205// Runs func_ptr, and logs a duration report after it's finished.
206#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
207 { \
208 DurationReporter duration_reporter_in_macro(log_title); \
209 func_ptr(__VA_ARGS__); \
210 }
211
212// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
213// is output after a slow function is finished.
214#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
215 RETURN_IF_USER_DENIED_CONSENT(); \
216 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
217 RETURN_IF_USER_DENIED_CONSENT();
218
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800219#define WAIT_TASK_WITH_CONSENT_CHECK(task_name, pool_ptr) \
220 RETURN_IF_USER_DENIED_CONSENT(); \
221 pool_ptr->waitForTask(task_name); \
222 RETURN_IF_USER_DENIED_CONSENT();
223
Sahana Raof35ed432019-07-12 10:47:52 +0100224static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
225
Rhed Jao5377d792020-07-16 17:37:39 +0800226// Names of parallel tasks, they are used for the DumpPool to identify the dump
227// task and the log title of the duration report.
228static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao3c2fdbd2020-07-20 17:46:29 +0800229static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
230static const std::string DUMP_HALS_TASK = "DUMP HALS";
231static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jaoe017f982020-07-21 17:58:41 +0800232static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao5377d792020-07-16 17:37:39 +0800233
Nandana Dutt979388e2018-11-30 16:48:55 +0000234namespace android {
235namespace os {
236namespace {
237
238static int Open(std::string path, int flags, mode_t mode = 0) {
239 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
240 if (fd == -1) {
241 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
242 }
243 return fd;
244}
245
mhasank2d75c442020-06-11 15:05:25 -0700246static int OpenForWrite(std::string path) {
247 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
248 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
249}
Nandana Dutt979388e2018-11-30 16:48:55 +0000250
251static int OpenForRead(std::string path) {
252 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
253}
254
255bool CopyFile(int in_fd, int out_fd) {
256 char buf[4096];
257 ssize_t byte_count;
258 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
259 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
260 return false;
261 }
262 }
263 return (byte_count != -1);
264}
265
266static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000267 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000268
269 // Obtain a handle to the source file.
270 android::base::unique_fd in_fd(OpenForRead(input_file));
271 if (out_fd != -1 && in_fd.get() != -1) {
272 if (CopyFile(in_fd.get(), out_fd)) {
273 return true;
274 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000275 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000276 }
277 return false;
278}
279
Nandana Duttd2f5f082019-01-18 17:13:52 +0000280static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000281 if (file.empty()) {
282 return false;
283 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000284 if (unlink(file.c_str())) {
285 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000286 return false;
287 }
288 return true;
289}
Nandana Dutt979388e2018-11-30 16:48:55 +0000290
Nikita Ioffea325a572019-05-16 19:49:47 +0100291int64_t GetModuleMetadataVersion() {
292 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
293 if (binder == nullptr) {
294 MYLOGE("Failed to retrieve package_native service");
295 return 0L;
296 }
297 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
298 std::string package_name;
299 auto status = package_service->getModuleMetadataPackageName(&package_name);
300 if (!status.isOk()) {
301 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
302 return 0L;
303 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100304 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100305 int64_t version_code;
306 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
307 &version_code);
308 if (!status.isOk()) {
309 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
310 return 0L;
311 }
312 return version_code;
313}
314
mhasank2d75c442020-06-11 15:05:25 -0700315static bool PathExists(const std::string& path) {
316 struct stat sb;
317 return stat(path.c_str(), &sb) == 0;
318}
319
320static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
321 if (input_file == output_file) {
322 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
323 output_file.c_str());
324 return false;
325 }
326 else if (PathExists(output_file)) {
327 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
328 return false;
329 }
330
331 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
332 android::base::unique_fd out_fd(OpenForWrite(output_file));
333 return CopyFileToFd(input_file, out_fd.get());
334}
335
Nandana Dutt979388e2018-11-30 16:48:55 +0000336} // namespace
337} // namespace os
338} // namespace android
339
Felipe Leme678727a2016-09-21 17:22:11 -0700340static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800341 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jaoe017f982020-07-21 17:58:41 +0800342 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
343 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
344}
345static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
346 int out_fd) {
347 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700348}
349static int DumpFile(const std::string& title, const std::string& path) {
350 return ds.DumpFile(title, path);
351}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800352
Felipe Lemee844a9d2016-09-21 15:01:39 -0700353// Relative directory (inside the zip) for all files copied as-is into the bugreport.
354static const std::string ZIP_ROOT_DIR = "FS";
355
Vishnu Naire97d6122018-01-18 13:58:56 -0800356static const std::string kProtoPath = "proto/";
357static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700358static const std::string kDumpstateBoardFiles[] = {
359 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700360 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700361};
362static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
363
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700364static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700365static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700366
Felipe Lemef0292972016-11-22 13:57:05 -0800367static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
368
Narayan Kamath8f788292017-05-25 13:20:39 +0100369/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100370 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800371 * The returned vector is sorted by the mtimes of the dumps with descending
372 * order. If |limit_by_mtime| is set, the vector only contains files that
373 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100374 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700375static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
376 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700377 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100378 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
379
Narayan Kamathbd863722017-06-01 18:50:12 +0100380 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100381
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700382 if (dump_dir == nullptr) {
383 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700384 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700385 }
386
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700387 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100388 struct dirent* entry = nullptr;
389 while ((entry = readdir(dump_dir.get()))) {
390 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100391 continue;
392 }
393
Narayan Kamathbd863722017-06-01 18:50:12 +0100394 const std::string base_name(entry->d_name);
395 if (base_name.find(file_prefix) != 0) {
396 continue;
397 }
398
399 const std::string abs_path = dir_path + base_name;
400 android::base::unique_fd fd(
401 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
402 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700403 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100404 break;
405 }
406
407 struct stat st = {};
408 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700409 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100410 continue;
411 }
412
Narayan Kamath3f31b632018-02-22 19:42:36 +0000413 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100414 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100415 continue;
416 }
417
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700418 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700419 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800420 if (!dump_data.empty()) {
421 std::sort(dump_data.begin(), dump_data.end(),
422 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
423 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100424
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700425 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100426}
427
Narayan Kamathbd863722017-06-01 18:50:12 +0100428static bool AddDumps(const std::vector<DumpData>::const_iterator start,
429 const std::vector<DumpData>::const_iterator end,
430 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100431 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100432 for (auto it = start; it != end; ++it) {
433 const std::string& name = it->name;
434 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100435 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100436
437 // Seek to the beginning of the file before dumping any data. A given
438 // DumpData entry might be dumped multiple times in the report.
439 //
440 // For example, the most recent ANR entry is dumped to the body of the
441 // main entry and it also shows up as a separate entry in the bugreport
442 // ZIP file.
443 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
444 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
445 strerror(errno));
446 }
447
Narayan Kamath8f788292017-05-25 13:20:39 +0100448 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800449 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100450 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100451 }
452 } else {
453 dump_file_from_fd(type_name, name.c_str(), fd);
454 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100455 }
456
457 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700458}
459
Felipe Leme635ca312016-01-05 14:23:02 -0800460// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700461void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800462 char path[PATH_MAX];
463
464 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
465 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700466 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800467 char linkname[PATH_MAX];
468 ssize_t r = readlink(path, linkname, PATH_MAX);
469 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800470 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800471 return;
472 }
473 linkname[r] = '\0';
474
475 if (mount_points.find(linkname) == mount_points.end()) {
476 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700477 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700478 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800479 mount_points.insert(linkname);
480 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800481 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800482 }
483 }
484}
485
486void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700487 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700488 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800489 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800490 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700491 for_each_pid(do_mountinfo, nullptr);
492 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800493}
494
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700495static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
496{
497 DIR *d;
498 struct dirent *de;
499 char path[PATH_MAX];
500
501 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700502 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700503 return;
504 }
505
506 while ((de = readdir(d))) {
507 if (de->d_type != DT_LNK) {
508 continue;
509 }
510 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700511 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700512 }
513
514 closedir(d);
515}
516
Mark Salyzyn326842f2015-04-30 09:49:41 -0700517static bool skip_not_stat(const char *path) {
518 static const char stat[] = "/stat";
519 size_t len = strlen(path);
520 if (path[len - 1] == '/') { /* Directory? */
521 return false;
522 }
523 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
524}
525
Felipe Leme4c2d6632016-09-28 14:32:00 -0700526static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800527 return false;
528}
529
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700530unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700531
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800532//
533// stat offsets
534// Name units description
535// ---- ----- -----------
536// read I/Os requests number of read I/Os processed
537#define __STAT_READ_IOS 0
538// read merges requests number of read I/Os merged with in-queue I/O
539#define __STAT_READ_MERGES 1
540// read sectors sectors number of sectors read
541#define __STAT_READ_SECTORS 2
542// read ticks milliseconds total wait time for read requests
543#define __STAT_READ_TICKS 3
544// write I/Os requests number of write I/Os processed
545#define __STAT_WRITE_IOS 4
546// write merges requests number of write I/Os merged with in-queue I/O
547#define __STAT_WRITE_MERGES 5
548// write sectors sectors number of sectors written
549#define __STAT_WRITE_SECTORS 6
550// write ticks milliseconds total wait time for write requests
551#define __STAT_WRITE_TICKS 7
552// in_flight requests number of I/Os currently in flight
553#define __STAT_IN_FLIGHT 8
554// io_ticks milliseconds total time this block device has been active
555#define __STAT_IO_TICKS 9
556// time_in_queue milliseconds total wait time for all requests
557#define __STAT_IN_QUEUE 10
558#define __STAT_NUMBER_FIELD 11
559//
560// read I/Os, write I/Os
561// =====================
562//
563// These values increment when an I/O request completes.
564//
565// read merges, write merges
566// =========================
567//
568// These values increment when an I/O request is merged with an
569// already-queued I/O request.
570//
571// read sectors, write sectors
572// ===========================
573//
574// These values count the number of sectors read from or written to this
575// block device. The "sectors" in question are the standard UNIX 512-byte
576// sectors, not any device- or filesystem-specific block size. The
577// counters are incremented when the I/O completes.
578#define SECTOR_SIZE 512
579//
580// read ticks, write ticks
581// =======================
582//
583// These values count the number of milliseconds that I/O requests have
584// waited on this block device. If there are multiple I/O requests waiting,
585// these values will increase at a rate greater than 1000/second; for
586// example, if 60 read requests wait for an average of 30 ms, the read_ticks
587// field will increase by 60*30 = 1800.
588//
589// in_flight
590// =========
591//
592// This value counts the number of I/O requests that have been issued to
593// the device driver but have not yet completed. It does not include I/O
594// requests that are in the queue but not yet issued to the device driver.
595//
596// io_ticks
597// ========
598//
599// This value counts the number of milliseconds during which the device has
600// had I/O requests queued.
601//
602// time_in_queue
603// =============
604//
605// This value counts the number of milliseconds that I/O requests have waited
606// on this block device. If there are multiple I/O requests waiting, this
607// value will increase as the product of the number of milliseconds times the
608// number of requests waiting (see "read ticks" above for an example).
609#define S_TO_MS 1000
610//
611
Mark Salyzyn326842f2015-04-30 09:49:41 -0700612static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800613 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700614 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700615 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700616 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700617 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700618 getline(&buffer, &i, fp);
619 fclose(fp);
620 if (!buffer) {
621 return -errno;
622 }
623 i = strlen(buffer);
624 while ((i > 0) && (buffer[i - 1] == '\n')) {
625 buffer[--i] = '\0';
626 }
627 if (!*buffer) {
628 free(buffer);
629 return 0;
630 }
631 z = true;
632 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800633 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 if (fields[i] != 0) {
635 z = false;
636 }
637 }
638 if (z) { /* never accessed */
639 free(buffer);
640 return 0;
641 }
642
Wei Wang509bb5d2017-06-09 14:42:12 -0700643 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
644 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700645 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700646
647 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
648 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
649 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700650 free(buffer);
651
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800652 if (fields[__STAT_IO_TICKS]) {
653 unsigned long read_perf = 0;
654 unsigned long read_ios = 0;
655 if (fields[__STAT_READ_TICKS]) {
656 unsigned long long divisor = fields[__STAT_READ_TICKS]
657 * fields[__STAT_IO_TICKS];
658 read_perf = ((unsigned long long)SECTOR_SIZE
659 * fields[__STAT_READ_SECTORS]
660 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
661 / divisor;
662 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
663 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
664 / divisor;
665 }
666
667 unsigned long write_perf = 0;
668 unsigned long write_ios = 0;
669 if (fields[__STAT_WRITE_TICKS]) {
670 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
671 * fields[__STAT_IO_TICKS];
672 write_perf = ((unsigned long long)SECTOR_SIZE
673 * fields[__STAT_WRITE_SECTORS]
674 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
675 / divisor;
676 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
677 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
678 / divisor;
679 }
680
681 unsigned queue = (fields[__STAT_IN_QUEUE]
682 + (fields[__STAT_IO_TICKS] >> 1))
683 / fields[__STAT_IO_TICKS];
684
685 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700686 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 -0800687 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700688 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 -0800689 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800690 }
691
692 /* bugreport timeout factor adjustment */
693 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
694 worst_write_perf = write_perf;
695 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700696 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700697 return 0;
698}
699
Yao Chenbe3bbc12018-01-17 16:31:10 -0800700static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
701
Tom Cherryf4472f32020-08-05 09:31:17 -0700702// Returns the actual readable size of the given buffer or -1 on error.
703static long logcat_buffer_readable_size(const std::string& buffer) {
704 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
705 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
706 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
707
708 return android_logger_get_log_readable_size(logger);
709}
710
711// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800712static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
713 unsigned long timeout_ms = 0;
714 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700715 long readable_size = logcat_buffer_readable_size(buffer);
716 if (readable_size > 0) {
717 // Engineering margin is ten-fold our guess.
718 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
719 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800720 }
721 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700722}
723
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800724// Opens a socket and returns its file descriptor.
725static int open_socket(const char* service);
726
Nandana Duttd2f5f082019-01-18 17:13:52 +0000727Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
728}
729
730android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
731 std::lock_guard<std::mutex> lock(lock_);
732 result_ = APPROVED;
733 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800734
735 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
736 // consent is granted.
737 if (ds.options_->is_screenshot_copied) {
738 return android::binder::Status::ok();
739 }
740
741 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
742 !ds.do_early_screenshot_) {
743 return android::binder::Status::ok();
744 }
745
746 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
747 ds.options_->screenshot_fd.get());
748 ds.options_->is_screenshot_copied = copy_succeeded;
749 if (copy_succeeded) {
750 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
751 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000752 return android::binder::Status::ok();
753}
754
755android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
756 std::lock_guard<std::mutex> lock(lock_);
757 result_ = DENIED;
758 MYLOGW("User denied consent to share bugreport\n");
759 return android::binder::Status::ok();
760}
761
762UserConsentResult Dumpstate::ConsentCallback::getResult() {
763 std::lock_guard<std::mutex> lock(lock_);
764 return result_;
765}
766
767uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800768 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000769}
770
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700771void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700772 std::string build, fingerprint, radio, bootloader, network;
773 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700774
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700775 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
776 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700777 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
778 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
779 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700780 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700781
Felipe Lemed8b94e52016-12-08 10:21:44 -0800782 printf("========================================================\n");
783 printf("== dumpstate: %s\n", date);
784 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700785
Felipe Lemed8b94e52016-12-08 10:21:44 -0800786 printf("\n");
787 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700788 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800789 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
790 printf("Bootloader: %s\n", bootloader.c_str());
791 printf("Radio: %s\n", radio.c_str());
792 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100793 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
794 if (module_metadata_version != 0) {
795 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
796 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100797 printf("SDK extension versions [r=%s s=%s]\n",
798 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
799 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700800
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800802 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800803 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800804 printf("Uptime: ");
805 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
806 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800807 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800808 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
809 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
810 options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800811 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800812}
813
Felipe Leme24b66ee2016-06-16 10:55:26 -0700814// List of file extensions that can cause a zip file attachment to be rejected by some email
815// service providers.
816static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
817 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
818 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
819 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
820};
821
Vishnu Naire97d6122018-01-18 13:58:56 -0800822status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
823 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700824 if (!IsZipping()) {
825 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
826 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800827 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800828 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700829 std::string valid_name = entry_name;
830
831 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700832 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700833 if (idx != std::string::npos) {
834 std::string extension = entry_name.substr(idx);
835 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
836 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
837 valid_name = entry_name + ".renamed";
838 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
839 }
840 }
841
Felipe Leme6fe9db62016-02-12 09:04:16 -0800842 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
843 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700844 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
845 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700846 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700847 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700848 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800849 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800850 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000851 bool finished_entry = false;
852 auto finish_entry = [this, &finished_entry] {
853 if (!finished_entry) {
854 // This should only be called when we're going to return an earlier error,
855 // which would've been logged. This may imply the file is already corrupt
856 // and any further logging from FinishEntry is more likely to mislead than
857 // not.
858 this->zip_writer_->FinishEntry();
859 }
860 };
861 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800862 auto start = std::chrono::steady_clock::now();
863 auto end = start + timeout;
864 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800865
Felipe Leme770410d2016-01-26 17:07:14 -0800866 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800867 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800868 if (timeout.count() > 0) {
869 // lambda to recalculate the timeout.
870 auto time_left_ms = [end]() {
871 auto now = std::chrono::steady_clock::now();
872 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
873 return std::max(diff.count(), 0LL);
874 };
875
876 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
877 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000878 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
879 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 return -errno;
881 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000882 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800883 entry_name.c_str(), strerror(errno), timeout.count());
884 return TIMED_OUT;
885 }
886 }
887
Zach Riggle22200402016-08-18 01:01:24 -0400888 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800889 if (bytes_read == 0) {
890 break;
891 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800892 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800893 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800894 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700895 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800896 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700897 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800898 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800899 }
900 }
901
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700902 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000903 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700904 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700905 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800906 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907 }
908
Vishnu Naire97d6122018-01-18 13:58:56 -0800909 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800910}
911
Felipe Leme1d486fe2016-10-14 18:06:47 -0700912bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
913 android::base::unique_fd fd(
914 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700915 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800916 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800917 return false;
918 }
919
Vishnu Naire97d6122018-01-18 13:58:56 -0800920 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800921}
922
923/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700924static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800925 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800926}
927
Felipe Leme1d486fe2016-10-14 18:06:47 -0700928void Dumpstate::AddDir(const std::string& dir, bool recursive) {
929 if (!IsZipping()) {
930 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800931 return;
932 }
Felipe Leme678727a2016-09-21 17:22:11 -0700933 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800934 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700935 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800936}
937
Felipe Leme1d486fe2016-10-14 18:06:47 -0700938bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
939 if (!IsZipping()) {
940 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
941 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800942 return false;
943 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800944 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700945 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700946 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700947 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700948 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800949 return false;
950 }
951
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700952 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700953 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700954 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700955 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800956 return false;
957 }
958
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700959 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700960 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700961 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800962 return false;
963 }
964
965 return true;
966}
967
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800968static void DoKmsg() {
969 struct stat st;
970 if (!stat(PSTORE_LAST_KMSG, &st)) {
971 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
972 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
973 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
974 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
975 } else {
976 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
977 DumpFile("LAST KMSG", "/proc/last_kmsg");
978 }
979}
980
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800981static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800982 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800983 RunCommand(
984 "KERNEL LOG",
985 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
986 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
987}
988
Nandana Duttdb379fa2019-10-09 16:54:41 +0100989static void DoSystemLogcat(time_t since) {
990 char since_str[80];
991 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
992
993 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
994 RunCommand("SYSTEM LOG",
995 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
996 since_str},
997 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
998}
999
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001000static void DoRadioLogcat() {
1001 unsigned long timeout_ms = logcat_timeout({"radio"});
1002 RunCommand(
1003 "RADIO LOG",
1004 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1005 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1006}
1007
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001008static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001009 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001010 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1011 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001012 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001013 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001014 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1015 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001016 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001017 RunCommand(
1018 "EVENT LOG",
1019 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001020 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001021 timeout_ms = logcat_timeout({"stats"});
1022 RunCommand(
1023 "STATS LOG",
1024 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001025 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001026 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001027
1028 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1029
1030 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001031 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1032 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001033}
1034
Mike Ma5c267872019-08-21 11:31:34 -07001035static void DumpIncidentReport() {
1036 if (!ds.IsZipping()) {
1037 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1038 return;
1039 }
Mike Ma5c267872019-08-21 11:31:34 -07001040 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1041 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1042 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1043 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1044 if (fd < 0) {
1045 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1046 return;
1047 }
1048 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1049 bool empty = 0 == lseek(fd, 0, SEEK_END);
1050 if (!empty) {
1051 // Use a different name from "incident.proto"
1052 // /proto/incident.proto is reserved for incident service dump
1053 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001054 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1055 path);
1056 } else {
1057 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001058 }
Mike Ma5c267872019-08-21 11:31:34 -07001059}
1060
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001061static void MaybeAddSystemTraceToZip() {
1062 // This function copies into the .zip the system trace that was snapshotted
1063 // by the early call to MaybeSnapshotSystemTrace(), if any background
1064 // tracing was happening.
1065 if (!ds.IsZipping()) {
1066 MYLOGD("Not dumping system trace because it's not a zipped bugreport\n");
1067 return;
1068 }
1069 if (!ds.has_system_trace_) {
1070 // No background trace was happening at the time dumpstate was invoked.
1071 return;
1072 }
1073 ds.AddZipEntry(
1074 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1075 SYSTEM_TRACE_SNAPSHOT);
1076 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1077}
1078
Sunny Goyal35949782019-11-19 15:54:36 -08001079static void DumpVisibleWindowViews() {
1080 if (!ds.IsZipping()) {
1081 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1082 return;
1083 }
1084 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1085 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1086 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1087 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1088 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1089 if (fd < 0) {
1090 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1091 return;
1092 }
1093 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1094 CommandOptions::WithTimeout(120).Build());
1095 bool empty = 0 == lseek(fd, 0, SEEK_END);
1096 if (!empty) {
1097 ds.AddZipEntry("visible_windows.zip", path);
1098 } else {
1099 MYLOGW("Failed to dump visible windows\n");
1100 }
1101 unlink(path.c_str());
1102}
1103
Jayachandran Ca94c7172017-06-10 15:08:12 -07001104static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001105 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1106 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001107 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001108 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001109 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1110 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1111 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1112 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001113}
1114
David Andersond9ba4752018-12-11 18:26:59 -08001115static void DumpDynamicPartitionInfo() {
1116 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1117 return;
1118 }
1119
1120 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001121 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001122}
1123
Narayan Kamath8f788292017-05-25 13:20:39 +01001124static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1125 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1126 anr_traces_dir.c_str());
1127
1128 // If we're here, dump_traces_path will always be a temporary file
1129 // (created with mkostemp or similar) that contains dumps taken earlier
1130 // on in the process.
1131 if (dump_traces_path != nullptr) {
1132 if (add_to_zip) {
1133 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1134 } else {
1135 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1136 dump_traces_path);
1137 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1138 }
1139
1140 const int ret = unlink(dump_traces_path);
1141 if (ret == -1) {
1142 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1143 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001144 }
1145 }
1146
Narayan Kamathbd863722017-06-01 18:50:12 +01001147 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001148 if (ds.anr_data_.size() > 0) {
1149 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001150 "VM TRACES AT LAST ANR", add_to_zip);
1151
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001152 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1153 // it will be present in the body of the main entry if |add_to_zip| == false.
1154 //
1155 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001156 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001157 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001158 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001159 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1160 }
1161}
1162
1163static void AddAnrTraceFiles() {
1164 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1165
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001166 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001167
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001168 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001169
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001170 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1171
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001172 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001173 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001174 int i = 0;
1175 while (true) {
1176 const std::string slow_trace_path =
1177 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1178 if (stat(slow_trace_path.c_str(), &st)) {
1179 // No traces file at this index, done with the files.
1180 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001181 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001182 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1183 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001184 }
1185}
1186
Wei Wang509bb5d2017-06-09 14:42:12 -07001187static void DumpBlockStatFiles() {
1188 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001189
Wei Wang1dc1ef52017-06-12 11:28:37 -07001190 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1191
1192 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001193 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1194 return;
1195 }
1196
1197 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001198 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001199 if ((d->d_name[0] == '.')
1200 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1201 || (d->d_name[1] == '\0'))) {
1202 continue;
1203 }
1204 const std::string new_path =
1205 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1206 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1207 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1208 printf("\n");
1209 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001210 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001211}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001212
1213static void DumpPacketStats() {
1214 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001215}
1216
1217static void DumpIpAddrAndRules() {
1218 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1219 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1220 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1221 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1222 RunCommand("IP RULES", {"ip", "rule", "show"});
1223 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1224}
1225
Nandana Dutt5c390032019-03-12 10:52:56 +00001226static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1227 std::chrono::milliseconds timeout,
1228 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001229 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001230 sp<android::IServiceManager> sm = defaultServiceManager();
1231 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001232 Vector<String16> args;
1233 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001234 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1235 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001236 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001237 std::string path(title);
1238 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001239 size_t bytes_written = 0;
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001240 if (PropertiesHelper::IsDryRun()) {
1241 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1242 dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
1243 } else {
1244 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
1245 if (status == OK) {
1246 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1247 std::chrono::duration<double> elapsed_seconds;
1248 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1249 service == String16("meminfo")) {
1250 // Use a longer timeout for meminfo, since 30s is not always enough.
1251 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1252 /* as_proto = */ false, elapsed_seconds,
1253 bytes_written);
1254 } else {
1255 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1256 /* as_proto = */ false, elapsed_seconds,
1257 bytes_written);
1258 }
1259 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1260 bool dump_complete = (status == OK);
1261 dumpsys.stopDumpThread(dump_complete);
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001262 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001263 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001264
1265 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1266 std::chrono::steady_clock::now() - start);
1267 if (elapsed_duration > timeout) {
1268 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1269 elapsed_duration.count());
1270 break;
1271 }
1272 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001273 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001274}
1275
Vishnu Nair64afc022018-02-01 15:29:34 -08001276static void RunDumpsysText(const std::string& title, int priority,
1277 std::chrono::milliseconds timeout,
1278 std::chrono::milliseconds service_timeout) {
1279 DurationReporter duration_reporter(title);
1280 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1281 fsync(STDOUT_FILENO);
1282 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1283}
1284
1285/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001286static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1287 std::chrono::milliseconds timeout,
1288 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001289 DurationReporter duration_reporter(title);
1290 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1291 fsync(STDOUT_FILENO);
1292 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1293 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001294
1295 RETURN_IF_USER_DENIED_CONSENT();
1296
1297 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1298 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001299}
1300
Nandana Dutt5c390032019-03-12 10:52:56 +00001301static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1302 std::chrono::milliseconds timeout,
1303 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001304 if (!ds.IsZipping()) {
1305 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001306 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001307 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001308 sp<android::IServiceManager> sm = defaultServiceManager();
1309 Dumpsys dumpsys(sm.get());
1310 Vector<String16> args;
1311 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1312 DurationReporter duration_reporter(title);
1313
1314 auto start = std::chrono::steady_clock::now();
1315 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1316 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001317 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001318 std::string path(kProtoPath);
1319 path.append(String8(service).c_str());
1320 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1321 path.append("_CRITICAL");
1322 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1323 path.append("_HIGH");
1324 }
1325 path.append(kProtoExt);
Steven Morelandcbd69fc2021-07-20 20:45:43 +00001326 status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001327 if (status == OK) {
1328 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1329 bool dumpTerminated = (status == OK);
1330 dumpsys.stopDumpThread(dumpTerminated);
1331 }
1332 ZipWriter::FileEntry file_entry;
1333 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001334
1335 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1336 std::chrono::steady_clock::now() - start);
1337 if (elapsed_duration > timeout) {
1338 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1339 elapsed_duration.count());
1340 break;
1341 }
1342 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001343 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001344}
1345
Nandana Dutta7db6342018-11-21 14:53:34 +00001346// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001347static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001348 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1349 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001350
1351 RETURN_IF_USER_DENIED_CONSENT();
1352
1353 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1354 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001355}
1356
1357// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001358static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001359 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1360 // high priority. Reduce timeout once they are able to dump in a shorter time or
1361 // moved to a parallel task.
1362 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1363 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001364
1365 RETURN_IF_USER_DENIED_CONSENT();
1366
1367 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1368 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001369}
1370
1371// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001372static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001373 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001374
1375 RETURN_IF_USER_DENIED_CONSENT();
1376
1377 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1378 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001379}
1380
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001381/*
1382 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1383 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1384 * if it's not running in the parallel task.
1385 */
1386static void DumpHals(int out_fd = STDOUT_FILENO) {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001387 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001388 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Steven Morelandd3646e02020-09-23 17:26:33 +00001389 CommandOptions::WithTimeout(60).AsRootIfAvailable().Build(),
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001390 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001391 return;
1392 }
Yifan Hong30528a22020-08-07 18:24:06 -07001393 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001394 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1395 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001396
Steven Moreland44cd9482018-01-04 16:24:13 -08001397 using android::hidl::manager::V1_0::IServiceManager;
1398 using android::hardware::defaultServiceManager;
1399
1400 sp<IServiceManager> sm = defaultServiceManager();
1401 if (sm == nullptr) {
1402 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1403 return;
1404 }
1405
1406 auto ret = sm->list([&](const auto& interfaces) {
1407 for (const std::string& interface : interfaces) {
1408 std::string cleanName = interface;
1409 std::replace_if(cleanName.begin(),
1410 cleanName.end(),
1411 [](char c) {
1412 return !isalnum(c) &&
1413 std::string("@-_:.").find(c) == std::string::npos;
1414 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001415 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001416
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001417 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001418 {
1419 auto fd = android::base::unique_fd(
1420 TEMP_FAILURE_RETRY(open(path.c_str(),
1421 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1422 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1423 if (fd < 0) {
1424 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1425 continue;
1426 }
1427 RunCommandToFd(fd,
1428 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001429 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001430 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1431
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001432 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001433 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001434 if (!empty) {
1435 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1436 path);
1437 } else {
1438 unlink(path.c_str());
1439 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001440 }
1441 });
1442
1443 if (!ret.isOk()) {
1444 MYLOGE("Could not list hals from hwservicemanager.\n");
1445 }
1446}
1447
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001448static void DumpExternalFragmentationInfo() {
1449 struct stat st;
1450 if (stat("/proc/buddyinfo", &st) != 0) {
1451 MYLOGE("Unable to dump external fragmentation info\n");
1452 return;
1453 }
1454
1455 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1456 std::ifstream ifs("/proc/buddyinfo");
1457 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1458 for (std::string line; std::getline(ifs, line);) {
1459 std::smatch match_results;
1460 if (std::regex_match(line, match_results, unusable_index_regex)) {
1461 std::stringstream free_pages(std::string{match_results[3]});
1462 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1463 std::istream_iterator<int>());
1464
1465 int total_free_pages = 0;
1466 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1467 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1468 }
1469
1470 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1471 match_results[2].str().c_str());
1472
1473 int usable_free_pages = total_free_pages;
1474 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1475 auto unusable_index = (total_free_pages - usable_free_pages) /
1476 static_cast<double>(total_free_pages);
1477 printf(" %5.3f", unusable_index);
1478 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1479 }
1480
1481 printf("\n");
1482 }
1483 }
1484 printf("\n");
1485}
1486
mhasankd451a472020-05-26 18:02:39 -07001487static void DumpstateLimitedOnly() {
1488 // Trimmed-down version of dumpstate to only include a whitelisted
1489 // set of logs (system log, event log, and system server / system app
1490 // crashes, and networking logs). See b/136273873 and b/138459828
1491 // for context.
1492 DurationReporter duration_reporter("DUMPSTATE");
1493 unsigned long timeout_ms;
1494 // calculate timeout
1495 timeout_ms = logcat_timeout({"main", "system", "crash"});
1496 RunCommand("SYSTEM LOG",
1497 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1498 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1499 timeout_ms = logcat_timeout({"events"});
1500 RunCommand(
1501 "EVENT LOG",
1502 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1503 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1504
1505 printf("========================================================\n");
1506 printf("== Networking Service\n");
1507 printf("========================================================\n");
1508
1509 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1510 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001511 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1512 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001513
1514 printf("========================================================\n");
1515 printf("== Dropbox crashes\n");
1516 printf("========================================================\n");
1517
1518 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1519 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1520
1521 printf("========================================================\n");
1522 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1523 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1524 printf("========================================================\n");
1525 printf("== dumpstate: done (id %d)\n", ds.id_);
1526 printf("========================================================\n");
1527}
1528
Rhed Jaoe017f982020-07-21 17:58:41 +08001529/*
1530 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1531 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1532 * if it's not running in the parallel task.
1533 */
1534static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1535 dprintf(out_fd, "========================================================\n");
1536 dprintf(out_fd, "== Checkins\n");
1537 dprintf(out_fd, "========================================================\n");
1538
1539 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1540 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1541 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1542 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1543 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1544 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1545}
1546
1547/*
1548 * Runs dumpsys on activity service to dump all application activities, services
1549 * and providers in the device.
1550 *
1551 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1552 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1553 * if it's not running in the parallel task.
1554 */
1555static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1556 dprintf(out_fd, "========================================================\n");
1557 dprintf(out_fd, "== Running Application Activities\n");
1558 dprintf(out_fd, "========================================================\n");
1559
1560 // The following dumpsys internally collects output from running apps, so it can take a long
1561 // time. So let's extend the timeout.
1562
1563 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1564
1565 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1566
1567 dprintf(out_fd, "========================================================\n");
1568 dprintf(out_fd, "== Running Application Services (platform)\n");
1569 dprintf(out_fd, "========================================================\n");
1570
1571 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1572 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1573
1574 dprintf(out_fd, "========================================================\n");
1575 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1576 dprintf(out_fd, "========================================================\n");
1577
1578 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1579 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1580
1581 dprintf(out_fd, "========================================================\n");
1582 dprintf(out_fd, "== Running Application Providers (platform)\n");
1583 dprintf(out_fd, "========================================================\n");
1584
1585 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001586 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jaoe017f982020-07-21 17:58:41 +08001587
1588 dprintf(out_fd, "========================================================\n");
1589 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1590 dprintf(out_fd, "========================================================\n");
1591
1592 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1593 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1594}
1595
Nandana Dutt5c390032019-03-12 10:52:56 +00001596// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1597// via the consent they are shown. Ignores other errors that occur while running various
1598// commands. The consent checking is currently done around long running tasks, which happen to
1599// be distributed fairly evenly throughout the function.
1600static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001601 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001602
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001603 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1604 if (ds.dump_pool_) {
1605 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1606 // drop root user. Restarts it with two threads for the parallel run.
1607 ds.dump_pool_->start(/* thread_counts = */2);
1608
1609 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1610 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1611 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jaoe017f982020-07-21 17:58:41 +08001612 ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001613 }
1614
Nandana Dutt5c390032019-03-12 10:52:56 +00001615 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1616 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1617 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001618 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001619 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001620 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001621 DumpFile("MEMORY INFO", "/proc/meminfo");
1622 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001623 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001624
1625 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1626
Sunny Goyal35949782019-11-19 15:54:36 -08001627 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1628
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001629 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1630 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1631 DumpFile("SLAB INFO", "/proc/slabinfo");
1632 DumpFile("ZONEINFO", "/proc/zoneinfo");
1633 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1634 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001635 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001636
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001637 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1638 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001639
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001640 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001641 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001642
1643 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1644 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001645
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001646 if (ds.dump_pool_) {
1647 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1648 } else {
1649 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1650 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001651
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001652 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001653 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001654 struct stat s;
1655 if (stat("/proc/modules", &s) != 0) {
1656 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1657 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001658 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001659 RunCommand("MODULES INFO",
1660 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1661 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1662 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001663 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001664
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001665 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001666 DoKernelLogcat();
1667 } else {
1668 do_dmesg();
1669 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001670
Felipe Lemef0292972016-11-22 13:57:05 -08001671 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001672
1673 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1674
Jeff Brown1dc94e32014-09-11 14:15:27 -07001675 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001676 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001677
Jack Yu5a6b2e22020-08-14 18:13:35 +08001678 /* Dump Nfc NCI logs */
1679 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001680
Paul Chang0d2aad72020-02-13 20:04:03 +08001681 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001682 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001683 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001684 }
1685
Felipe Lemee184f662016-10-27 10:04:47 -07001686 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001687
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001688 MaybeAddSystemTraceToZip();
1689
Narayan Kamath8f788292017-05-25 13:20:39 +01001690 // NOTE: tombstones are always added as separate entries in the zip archive
1691 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001692 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001693 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001694 if (!tombstones_dumped) {
1695 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001696 }
1697
Jayachandran Ca94c7172017-06-10 15:08:12 -07001698 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001699
Chenbo Feng276a3b62018-08-07 11:44:49 -07001700 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1701
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001702 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001703
Jayachandran Ca94c7172017-06-10 15:08:12 -07001704 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001705
1706 dump_route_tables();
1707
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001708 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1709 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1710 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001711
Nandana Dutt5c390032019-03-12 10:52:56 +00001712 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001713
Chiachang Wang668ede42021-05-17 17:14:20 +08001714 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1715 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1716 // dump with priority parameters to dump high priority information.
1717 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1718 CommandOptions::WithTimeout(10).Build());
1719
Elliott Hughes23ccc622017-02-28 10:14:22 -08001720 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001721
Jin Qianf334d662017-10-10 14:41:37 -07001722 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001723
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001724 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001725
Colin Crossf45fa6b2012-03-26 12:38:26 -07001726 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001727 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1728 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1729
1730 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1731 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1732 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1733 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1734 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001735
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001736 /* Add window and surface trace files. */
1737 if (!PropertiesHelper::IsUserBuild()) {
1738 ds.AddDir(WMTRACE_DATA_DIR, false);
1739 }
1740
Yifan Hongd90cc652020-02-08 16:52:02 -08001741 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1742
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001743 if (ds.dump_pool_) {
1744 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1745 } else {
1746 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1747 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001748
Steven Moreland7440ddb2016-12-15 16:13:39 -08001749 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001750 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1751 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001752 // su does not exist on user builds, so try running without it.
1753 // This way any implementations of vril-dump that do not require
1754 // root can run on user builds.
1755 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001756 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001757 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001758 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001760 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001761 }
1762
Felipe Lemed8b94e52016-12-08 10:21:44 -08001763 printf("========================================================\n");
1764 printf("== Android Framework Services\n");
1765 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001766
Nandana Dutt5c390032019-03-12 10:52:56 +00001767 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001768
Jack He91ff2fe2021-02-18 18:23:43 -08001769 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1770 ds.AddDir("/data/misc/bluetooth/logs", true);
1771
Rhed Jaoe017f982020-07-21 17:58:41 +08001772 if (ds.dump_pool_) {
1773 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
1774 } else {
1775 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1776 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001777
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001778 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001779
Adrian Roos8b397ab2017-04-04 16:35:44 -07001780 printf("========================================================\n");
1781 printf("== Dropbox crashes\n");
1782 printf("========================================================\n");
1783
1784 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1785 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1786
Felipe Lemed8b94e52016-12-08 10:21:44 -08001787 printf("========================================================\n");
1788 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1789 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1790 printf("========================================================\n");
1791 printf("== dumpstate: done (id %d)\n", ds.id_);
1792 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001793
1794 printf("========================================================\n");
1795 printf("== Obtaining statsd metadata\n");
1796 printf("========================================================\n");
1797 // This differs from the usual dumpsys stats, which is the stats report data.
1798 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001799
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001800 // Add linker configuration directory
1801 ds.AddDir(LINKERCONFIG_DIR, true);
1802
Li Li2eedd412021-06-30 15:11:53 -07001803 /* Dump cgroupfs */
1804 ds.AddDir(CGROUPFS_DIR, true);
1805
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001806 if (ds.dump_pool_) {
1807 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1808 } else {
1809 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1810 DumpIncidentReport);
1811 }
Mike Ma5c267872019-08-21 11:31:34 -07001812
Nandana Dutt5c390032019-03-12 10:52:56 +00001813 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001814}
1815
Nandana Dutt5c390032019-03-12 10:52:56 +00001816/*
1817 * Dumps state for the default case; drops root after it's no longer necessary.
1818 *
1819 * Returns RunStatus::OK if everything went fine.
1820 * Returns RunStatus::ERROR if there was an error.
1821 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1822 * with the caller.
1823 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001824Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001825 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1826 // buffer.
1827 DoLogcat();
1828 // Capture timestamp after first logcat to use in next logcat
1829 time_t logcat_ts = time(nullptr);
1830
Nandana Dutt4be45d12018-09-26 15:04:23 +01001831 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao5377d792020-07-16 17:37:39 +08001832 if (dump_pool_) {
1833 RETURN_IF_USER_DENIED_CONSENT();
1834 // One thread is enough since we only need to enqueue DumpTraces here.
1835 dump_pool_->start(/* thread_counts = */1);
1836
1837 // DumpTraces takes long time, post it to the another thread in the
1838 // pool, if pool is available
1839 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1840 } else {
1841 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1842 &dump_traces_path);
1843 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001844
1845 /* Run some operations that require root. */
Gavin Corkeryf18d1832021-08-25 17:23:40 +01001846 if (!PropertiesHelper::IsDryRun()) {
1847 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1848 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1849 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001850
1851 ds.AddDir(RECOVERY_DIR, true);
1852 ds.AddDir(RECOVERY_DATA_DIR, true);
1853 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1854 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1855 if (!PropertiesHelper::IsUserBuild()) {
1856 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1857 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001858 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001859 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001860 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001861 add_mountinfo();
1862 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001863 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001864 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001865
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001866 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001867 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1868
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001869 // Dump IPsec stats. No keys are exposed here.
1870 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1871
Nandana Dutt4be45d12018-09-26 15:04:23 +01001872 // Run ss as root so we can see socket marks.
1873 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1874
1875 // Run iotop as root to show top 100 IO threads
1876 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1877
Erick Reyese68df822019-02-11 14:46:36 -08001878 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001879 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1880 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001881
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001882 DumpFile("PSI cpu", "/proc/pressure/cpu");
1883 DumpFile("PSI memory", "/proc/pressure/memory");
1884 DumpFile("PSI io", "/proc/pressure/io");
1885
Rhed Jao5377d792020-07-16 17:37:39 +08001886 if (dump_pool_) {
1887 RETURN_IF_USER_DENIED_CONSENT();
1888 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1889
1890 // Current running thread in the pool is the root user also. Shutdown
1891 // the pool and restart later to ensure all threads in the pool could
1892 // drop the root user.
1893 dump_pool_->shutdown();
1894 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001895 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001896 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001897 }
1898
Nandana Dutt5c390032019-03-12 10:52:56 +00001899 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001900 Dumpstate::RunStatus status = dumpstate();
1901 // Capture logcat since the last time we did it.
1902 DoSystemLogcat(logcat_ts);
1903 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001904}
1905
Rhed Jaob5685b32020-08-14 17:19:17 +08001906// Common states for telephony and wifi which are needed to be collected before
1907// dumpstate drop the root user.
1908static void DumpstateRadioAsRoot() {
1909 DumpIpTablesAsRoot();
1910 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1911}
1912
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001913// This method collects common dumpsys for telephony and wifi. Typically, wifi
1914// reports are fine to include all information, but telephony reports on user
1915// builds need to strip some content (see DumpstateTelephonyOnly).
1916static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001917 // We need to be picky about some stuff for telephony reports on user builds.
1918 if (!include_sensitive_info) {
1919 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1920 DoRadioLogcat();
1921 } else {
Rhed Jaob5685b32020-08-14 17:19:17 +08001922 // DumpHals takes long time, post it to the another thread in the pool,
1923 // if pool is available.
1924 if (ds.dump_pool_) {
1925 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1926 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001927 // Contains various system properties and process startup info.
1928 do_dmesg();
1929 // Logs other than the radio buffer may contain package/component names and potential PII.
1930 DoLogcat();
1931 // Too broad for connectivity problems.
1932 DoKmsg();
Rhed Jaob5685b32020-08-14 17:19:17 +08001933 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1934 if (ds.dump_pool_) {
1935 ds.dump_pool_->waitForTask(DUMP_HALS_TASK);
1936 } else {
1937 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1938 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001939 }
1940
Jayachandran Ca94c7172017-06-10 15:08:12 -07001941 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001942 DumpIpAddrAndRules();
1943 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001944 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1945 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001946}
1947
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001948// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1949// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1950// for what can be included on user builds: all reported information MUST directly relate to
1951// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1952// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1953// names are not), and MUST NOT contain logs of user application traffic.
1954// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001955static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001956 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001957
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001958 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001959
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001960 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001961
Rhed Jaob5685b32020-08-14 17:19:17 +08001962 DumpstateRadioAsRoot();
1963 if (!DropRootUser()) {
1964 return;
1965 }
1966
1967 // Starts thread pool after the root user is dropped, and two additional threads
1968 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1969 if (ds.dump_pool_) {
1970 ds.dump_pool_->start(/*thread_counts =*/2);
1971
1972 // DumpstateBoard takes long time, post it to the another thread in the pool,
1973 // if pool is available.
1974 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1975 }
1976
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001977 DumpstateRadioCommon(include_sensitive_info);
1978
1979 if (include_sensitive_info) {
1980 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1981 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1982 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1983 // way.
1984 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1985 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001986
1987 printf("========================================================\n");
1988 printf("== Android Framework Services\n");
1989 printf("========================================================\n");
1990
Vishnu Nair652cc802017-11-30 15:18:30 -08001991 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1992 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001993 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1994 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001995 if (include_sensitive_info) {
1996 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1997 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1998 SEC_TO_MSEC(10));
1999 } else {
2000 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
2001 // running dumpsys activity service all-non-platform below. Due to the increased output, we
2002 // give a higher timeout as well.
2003 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
2004 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
2005 }
2006 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002007 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2008 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07002009 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08002010 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
2011 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002012 if (include_sensitive_info) {
2013 // Contains raw IP addresses, omit from reports on user builds.
2014 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2015 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2016 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2017 SEC_TO_MSEC(10));
2018 // Contains package/component names, omit from reports on user builds.
2019 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2020 SEC_TO_MSEC(10));
2021 // Contains package names, but should be relatively simple to remove them (also contains
2022 // UIDs already), omit from reports on user builds.
2023 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2024 SEC_TO_MSEC(10));
2025 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002026
2027 printf("========================================================\n");
2028 printf("== Running Application Services\n");
2029 printf("========================================================\n");
2030
2031 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2032
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002033 if (include_sensitive_info) {
2034 printf("========================================================\n");
2035 printf("== Running Application Services (non-platform)\n");
2036 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002037
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002038 // Contains package/component names and potential PII, omit from reports on user builds.
2039 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2040 // carrier_config dumpsys instead.
2041 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2042 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002043
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002044 printf("========================================================\n");
2045 printf("== Checkins\n");
2046 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002047
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002048 // Contains package/component names, omit from reports on user builds.
2049 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2050 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002051
2052 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002053 printf("== dumpstate: done (id %d)\n", ds.id_);
2054 printf("========================================================\n");
Rhed Jaob5685b32020-08-14 17:19:17 +08002055
2056 if (ds.dump_pool_) {
2057 ds.dump_pool_->waitForTask(DUMP_BOARD_TASK);
2058 } else {
2059 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2060 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002061}
2062
mukesh agrawal253dad42018-01-23 21:59:59 -08002063// This method collects dumpsys for wifi debugging only
2064static void DumpstateWifiOnly() {
2065 DurationReporter duration_reporter("DUMPSTATE");
2066
Rhed Jaob5685b32020-08-14 17:19:17 +08002067 DumpstateRadioAsRoot();
2068 if (!DropRootUser()) {
2069 return;
2070 }
2071
2072 // Starts thread pool after the root user is dropped. Only one additional
2073 // thread is needed for DumpHals in the DumpstateRadioCommon.
2074 if (ds.dump_pool_) {
2075 ds.dump_pool_->start(/*thread_counts =*/1);
2076 }
2077
mukesh agrawal253dad42018-01-23 21:59:59 -08002078 DumpstateRadioCommon();
2079
2080 printf("========================================================\n");
2081 printf("== Android Framework Services\n");
2082 printf("========================================================\n");
2083
2084 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2085 SEC_TO_MSEC(10));
2086 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2087 SEC_TO_MSEC(10));
2088
2089 printf("========================================================\n");
2090 printf("== dumpstate: done (id %d)\n", ds.id_);
2091 printf("========================================================\n");
2092}
2093
Nandana Duttcf419a72019-03-14 10:40:17 +00002094Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002095 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002096 const size_t buf_size = temp_file_pattern.length() + 1;
2097 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2098 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2099
2100 // Create a new, empty file to receive all trace dumps.
2101 //
2102 // TODO: This can be simplified once we remove support for the old style
2103 // dumps. We can have a file descriptor passed in to dump_traces instead
2104 // of creating a file, closing it and then reopening it again.
2105 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2106 if (fd < 0) {
2107 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002108 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002109 }
2110
2111 // Nobody should have access to this temporary file except dumpstate, but we
2112 // temporarily grant 'read' to 'others' here because this file is created
2113 // when tombstoned is still running as root, but dumped after dropping. This
2114 // can go away once support for old style dumping has.
2115 const int chmod_ret = fchmod(fd, 0666);
2116 if (chmod_ret < 0) {
2117 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002118 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002119 }
2120
2121 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2122 if (proc.get() == nullptr) {
2123 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002124 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002125 }
2126
2127 // Number of times process dumping has timed out. If we encounter too many
2128 // failures, we'll give up.
2129 int timeout_failures = 0;
2130 bool dalvik_found = false;
2131
2132 const std::set<int> hal_pids = get_interesting_hal_pids();
2133
2134 struct dirent* d;
2135 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002136 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002137 int pid = atoi(d->d_name);
2138 if (pid <= 0) {
2139 continue;
2140 }
2141
2142 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2143 std::string exe;
2144 if (!android::base::Readlink(link_name, &exe)) {
2145 continue;
2146 }
2147
2148 bool is_java_process;
2149 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2150 // Don't bother dumping backtraces for the zygote.
2151 if (IsZygote(pid)) {
2152 continue;
2153 }
2154
2155 dalvik_found = true;
2156 is_java_process = true;
2157 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2158 is_java_process = false;
2159 } else {
2160 // Probably a native process we don't care about, continue.
2161 continue;
2162 }
2163
2164 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2165 if (timeout_failures == 3) {
2166 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2167 break;
2168 }
2169
2170 const uint64_t start = Nanotime();
2171 const int ret = dump_backtrace_to_file_timeout(
2172 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2173 is_java_process ? 5 : 20, fd);
2174
2175 if (ret == -1) {
2176 // For consistency, the header and footer to this message match those
2177 // dumped by debuggerd in the success case.
2178 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2179 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2180 dprintf(fd, "---- end %d ----", pid);
2181 timeout_failures++;
2182 continue;
2183 }
2184
2185 // We've successfully dumped stack traces, reset the failure count
2186 // and write a summary of the elapsed time to the file and continue with the
2187 // next process.
2188 timeout_failures = 0;
2189
2190 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2191 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2192 }
2193
2194 if (!dalvik_found) {
2195 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2196 }
2197
Nandana Duttcf419a72019-03-14 10:40:17 +00002198 *path = file_name_buf.release();
2199 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002200}
2201
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002202void Dumpstate::DumpstateBoard(int out_fd) {
2203 dprintf(out_fd, "========================================================\n");
2204 dprintf(out_fd, "== Board\n");
2205 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002206
Felipe Leme6f674ae2016-11-18 17:10:33 -08002207 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002208 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002209 return;
2210 }
2211
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002212 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002213 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002214 * set to true and unmount it after invoking dumpstateBoard_* methods.
2215 * This is to enable debug builds to not have debugfs mounted during runtime.
2216 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002217 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002218 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002219 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002220 if (mount_debugfs) {
2221 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2222 AS_ROOT_20);
2223 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"},
2224 AS_ROOT_20);
2225 }
2226
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002227 std::vector<std::string> paths;
2228 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002229 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002230 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2231 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002232 remover.emplace_back(android::base::make_scope_guard(
2233 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002234 }
Jie Song9fbfad02017-06-20 16:29:42 -07002235
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002236 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2237 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002238 MYLOGE("No IDumpstateDevice implementation\n");
2239 return;
2240 }
2241
2242 using ScopedNativeHandle =
2243 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2244 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2245 [](native_handle_t* handle) {
2246 native_handle_close(handle);
2247 native_handle_delete(handle);
2248 });
2249 if (handle == nullptr) {
2250 MYLOGE("Could not create native_handle\n");
2251 return;
2252 }
2253
Nandana Dutt5c390032019-03-12 10:52:56 +00002254 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002255 for (size_t i = 0; i < paths.size(); i++) {
2256 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2257
2258 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2259 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2260 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2261 if (fd < 0) {
2262 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2263 return;
2264 }
2265 handle.get()->data[i] = fd.release();
2266 }
2267
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002268 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2269 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2270 // will kill the HAL and grab whatever it dumped in time.
2271 constexpr size_t timeout_sec = 30;
2272 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2273 // implement just 1.0.
2274 const char* descriptor_to_kill;
2275 using DumpstateBoardTask = std::packaged_task<bool()>;
2276 DumpstateBoardTask dumpstate_board_task;
2277 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2278 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2279 if (dumpstate_device_1_1 != nullptr) {
2280 MYLOGI("Using IDumpstateDevice v1.1");
2281 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2282 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2283 ::android::hardware::Return<DumpstateStatus> status =
2284 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2285 SEC_TO_MSEC(timeout_sec));
2286 if (!status.isOk()) {
2287 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2288 return false;
2289 } else if (status != DumpstateStatus::OK) {
2290 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2291 return false;
2292 }
2293 return true;
2294 });
2295 } else {
2296 MYLOGI("Using IDumpstateDevice v1.0");
2297 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2298 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2299 ::android::hardware::Return<void> status =
2300 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002301 if (!status.isOk()) {
2302 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002303 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002304 }
Wei Wang587eac92018-04-05 12:17:20 -07002305 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002306 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002307 }
2308 auto result = dumpstate_board_task.get_future();
2309 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002310
Wei Wang587eac92018-04-05 12:17:20 -07002311 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2312 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002313 if (!android::base::SetProperty(
2314 "ctl.interface_restart",
2315 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002316 MYLOGE("Couldn't restart dumpstate HAL\n");
2317 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002318 }
Wei Wang587eac92018-04-05 12:17:20 -07002319 // Wait some time for init to kill dumpstate vendor HAL
2320 constexpr size_t killing_timeout_sec = 10;
2321 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2322 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2323 "there might be racing in content\n", killing_timeout_sec);
2324 }
2325
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002326 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002327 auto keep_debugfs_mounted =
2328 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2329 if (keep_debugfs_mounted.empty())
2330 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002331 }
2332
Wei Wang587eac92018-04-05 12:17:20 -07002333 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2334 for (size_t i = 0; i < paths.size(); i++) {
2335 struct stat s;
2336 if (fstat(handle.get()->data[i], &s) == -1) {
2337 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2338 strerror(errno));
2339 file_sizes[i] = -1;
2340 continue;
2341 }
2342 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002343 }
2344
2345 for (size_t i = 0; i < paths.size(); i++) {
2346 if (file_sizes[i] == -1) {
2347 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002348 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002349 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002350 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002351 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002352 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002353 remover[i].Disable();
2354 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2355 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002356 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002357}
2358
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002359static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002360 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002361 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2362 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002363 " -h: display this help message\n"
2364 " -b: play sound file instead of vibrate, at beginning of job\n"
2365 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002366 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002367 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002368 " -s: write zipped file to control socket (for init)\n"
2369 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002370 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002371 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002372 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002373 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002374 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002375 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002376}
2377
Wei Liuf87959e2016-08-26 14:51:42 -07002378static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002379 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002380}
2381
Felipe Leme1d486fe2016-10-14 18:06:47 -07002382bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002383 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2384 if (zip_entry_tasks_) {
2385 zip_entry_tasks_->run(/* do_cancel = */false);
2386 }
2387
Felipe Leme9a523ae2016-10-20 15:10:33 -07002388 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002389 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002390 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002391 // Final timestamp
2392 char date[80];
2393 time_t the_real_now_please_stand_up = time(nullptr);
2394 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002395 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002396 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002397
Felipe Leme9a523ae2016-10-20 15:10:33 -07002398 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002399 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002400 return false;
2401 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002402 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002403 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002404 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002405 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002406
Felipe Leme0f3fb202016-06-10 17:10:53 -07002407 // Add log file (which contains stderr output) to zip...
2408 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002409 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002410 MYLOGE("Failed to add dumpstate log to .zip file\n");
2411 return false;
2412 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002413 // TODO: Should truncate the existing file.
2414 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002415 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2416 return false;
2417 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002418 fprintf(stderr, "\n");
2419
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002420 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002421 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002422 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002423 return false;
2424 }
2425
Felipe Leme1d486fe2016-10-14 18:06:47 -07002426 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2427 ds.zip_file.reset(nullptr);
2428
Felipe Lemee9d2c542016-11-15 11:48:26 -08002429 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002430 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002431
Felipe Leme1e9edc62015-12-21 16:02:13 -08002432 return true;
2433}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002434
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002435static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2436 // clang-format off
2437 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2438 "--receiver-foreground", "--receiver-include-background", "-a", action};
2439 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002440
2441 am.insert(am.end(), args.begin(), args.end());
2442
Felipe Leme8d2410e2017-02-08 09:46:08 -08002443 RunCommand("", am,
2444 CommandOptions::WithTimeout(20)
2445 .Log("Sending broadcast: '%s'\n")
2446 .Always()
2447 .DropRoot()
2448 .RedirectStderr()
2449 .Build());
2450}
2451
Felipe Leme35b8cf12017-02-10 15:47:29 -08002452static void Vibrate(int duration_ms) {
2453 // clang-format off
Lais Andrade51156962021-02-22 19:21:35 +00002454 std::vector<std::string> args = {"cmd", "vibrator_manager", "synced", "-f", "-d", "dumpstate",
2455 "oneshot", std::to_string(duration_ms)};
2456 RunCommand("", args,
Felipe Leme35b8cf12017-02-10 15:47:29 -08002457 CommandOptions::WithTimeout(10)
2458 .Log("Vibrate: '%s'\n")
2459 .Always()
2460 .Build());
2461 // clang-format on
2462}
2463
Nandana Dutt979388e2018-11-30 16:48:55 +00002464static void MaybeResolveSymlink(std::string* path) {
2465 std::string resolved_path;
2466 if (android::base::Readlink(*path, &resolved_path)) {
2467 *path = resolved_path;
2468 }
2469}
2470
Nandana Dutt4be45d12018-09-26 15:04:23 +01002471/*
2472 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002473 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002474 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002475static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002476 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2477
Nandana Dutt4be45d12018-09-26 15:04:23 +01002478 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2479 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002480 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002481 char date[80];
2482 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2483 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002484
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002485 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002486 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002487 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002488 ds.base_name_ += "-wifi";
2489 }
2490
Paul Chang0d2aad72020-02-13 20:04:03 +08002491 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002492 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002493 }
2494 ds.tmp_path_ = ds.GetPath(".tmp");
2495 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2496
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002497 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002498 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002499 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002500 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002501 "Bugreport dir: [%s] "
2502 "Base name: [%s] "
2503 "Suffix: [%s] "
2504 "Log path: [%s] "
2505 "Temporary path: [%s] "
2506 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002507 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2508 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002509
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002510 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2511 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2512 create_parent_dirs(ds.path_.c_str());
2513 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2514 if (ds.zip_file == nullptr) {
2515 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2516 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002517 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002518 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2519 ds.AddTextZipEntry("version.txt", ds.version_);
2520 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002521}
2522
2523/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002524 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002525 * printing zipped file status, etc.
2526 */
2527static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002528 bool do_text_file = !ds.FinishZipFile();
2529 if (do_text_file) {
2530 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002531 }
mhasank2d75c442020-06-11 15:05:25 -07002532
2533 std::string final_path = ds.path_;
2534 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002535 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002536 android::os::CopyFileToFile(ds.path_, final_path);
2537 }
2538
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002539 if (ds.options_->stream_to_socket) {
2540 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2541 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002542 if (do_text_file) {
2543 dprintf(ds.control_socket_fd_,
2544 "FAIL:could not create zip file, check %s "
2545 "for more details\n",
2546 ds.log_path_.c_str());
2547 } else {
mhasank2d75c442020-06-11 15:05:25 -07002548 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002549 }
2550 }
2551}
2552
Nandana Dutt4be45d12018-09-26 15:04:23 +01002553
Nandana Dutt58d72e22018-11-16 10:30:48 +00002554static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2555 switch (mode) {
2556 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2557 return "BUGREPORT_FULL";
2558 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2559 return "BUGREPORT_INTERACTIVE";
2560 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2561 return "BUGREPORT_REMOTE";
2562 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2563 return "BUGREPORT_WEAR";
2564 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2565 return "BUGREPORT_TELEPHONY";
2566 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2567 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002568 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2569 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002570 }
2571}
2572
Paul Changf59c2b72020-03-10 02:08:55 +08002573static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2574 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002575 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2576 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002577 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002578 switch (mode) {
2579 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002580 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002581 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002582 break;
2583 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002584 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002585 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002586 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002587 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002588 break;
2589 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002590 options->do_vibrate = false;
2591 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002592 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002593 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002594 break;
2595 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002596 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002597 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002598 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002599 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002600 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002601 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002602 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002603 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002604 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002605 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002606 break;
2607 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002608 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002609 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002610 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002611 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002612 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2613 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002614 }
2615}
2616
Nandana Dutt58d72e22018-11-16 10:30:48 +00002617static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002618 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002619 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao25f50e02020-08-20 00:10:32 +08002620 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002621 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002622 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002623 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002624 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao25f50e02020-08-20 00:10:32 +08002625 options.telephony_only, options.wifi_only,
mhasankd451a472020-05-26 18:02:39 -07002626 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2627 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002628}
2629
Nandana Dutt54dbd672019-01-11 12:58:05 +00002630void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2631 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002632 const android::base::unique_fd& screenshot_fd_in,
2633 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002634 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2635 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2636 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002637
Paul Changf59c2b72020-03-10 02:08:55 +08002638 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002639}
2640
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002641Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2642 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002643 int c;
mhasankd451a472020-05-26 18:02:39 -07002644 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002645 switch (c) {
2646 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002647 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002648 case 's': stream_to_socket = true; break;
2649 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002650 case 'v': show_header_only = true; break;
2651 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002652 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002653 case 'P': do_progress_updates = true; break;
2654 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002655 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002656 case 'V':
2657 case 'd':
2658 case 'z':
2659 // compatibility no-op
2660 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002661 case 'w':
2662 // This was already processed
2663 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002664 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002665 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002666 break;
2667 default:
2668 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002669 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002670 break;
2671 // clang-format on
2672 }
2673 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002674
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002675 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002676 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002677 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002678 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002679 }
2680 }
2681
2682 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2683 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002684
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002685 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002686}
2687
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002688bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002689 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002690 return false;
2691 }
2692
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002693 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002694 return false;
2695 }
2696
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002697 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002698 return false;
2699 }
2700 return true;
2701}
2702
Nandana Dutt197661d2018-11-16 16:40:21 +00002703void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2704 options_ = std::move(options);
2705}
2706
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002707void Dumpstate::Initialize() {
2708 /* gets the sequential id */
2709 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2710 id_ = ++last_id;
2711 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2712}
2713
Nandana Duttd2f5f082019-01-18 17:13:52 +00002714Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2715 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002716 if (listener_ != nullptr) {
2717 switch (status) {
2718 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002719 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002720 break;
2721 case Dumpstate::RunStatus::HELP:
2722 break;
2723 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002724 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002725 break;
2726 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002727 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2728 break;
2729 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2730 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2731 break;
2732 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2733 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002734 break;
2735 }
2736 }
2737 return status;
2738}
2739
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002740void Dumpstate::Cancel() {
2741 CleanupTmpFiles();
2742 android::os::UnlinkAndLogOnError(log_path_);
2743 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2744 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2745 kDumpstateBoardFiles[i]);
2746 }
2747 tombstone_data_.clear();
2748 anr_data_.clear();
Rhed Jao0daac912020-08-21 14:48:20 +08002749
2750 // Instead of shutdown the pool, we delete temporary files directly since
2751 // shutdown blocking the call.
2752 if (dump_pool_) {
2753 dump_pool_->deleteTempFiles();
2754 }
2755 if (zip_entry_tasks_) {
2756 zip_entry_tasks_->run(/*do_cancel =*/ true);
2757 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002758}
2759
Nandana Dutt979388e2018-11-30 16:48:55 +00002760/*
2761 * Dumps relevant information to a bugreport based on the given options.
2762 *
2763 * The bugreport can be dumped to a file or streamed to a socket.
2764 *
2765 * How dumping to file works:
2766 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2767 * stderr is redirected a log file.
2768 *
2769 * The temporary bugreport is then populated via printfs, dumping contents of files and
2770 * output of commands to stdout.
2771 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002772 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002773 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002774 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002775 *
mhasank2d75c442020-06-11 15:05:25 -07002776 * Bugreports are first generated in a local directory and later copied to the caller's fd
2777 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002778 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002779Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2780 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002781 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002782 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002783 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002784 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002785 return RunStatus::INVALID_INPUT;
2786 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002787 /* set as high priority, and protect from OOM killer */
2788 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002789
Felipe Lemed071c682016-10-20 16:48:00 -07002790 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002791 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002792 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002793 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002794 } else {
2795 /* fallback to kernels <= 2.6.35 */
2796 oom_adj = fopen("/proc/self/oom_adj", "we");
2797 if (oom_adj) {
2798 fputs("-17", oom_adj);
2799 fclose(oom_adj);
2800 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002801 }
2802
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002803 if (version_ == VERSION_DEFAULT) {
2804 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002805 }
2806
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002807 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002808 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002809 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002810 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002811 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002812 }
2813
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002814 if (options_->show_header_only) {
2815 PrintHeader();
2816 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002817 }
2818
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002819 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2820 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002821
Felipe Leme7447d7c2016-11-03 18:12:22 -07002822 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002823 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002824 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002825 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002826
Sahana Raof35ed432019-07-12 10:47:52 +01002827 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2828 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2829 } else {
2830 // Wake lock will be released automatically on process death
2831 MYLOGD("Wake lock acquired.\n");
2832 }
2833
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002834 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002835
Felipe Lemef0292972016-11-22 13:57:05 -08002836 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002837 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2838 }
2839
Nandana Dutt235c6672019-11-14 15:22:32 +00002840 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2841 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002842
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002843 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002844
Christopher Ferrised9354f2014-10-01 17:35:01 -07002845 // If we are going to use a socket, do it as early as possible
2846 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002847 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002848 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002849 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002850 if (control_socket_fd_ == -1) {
2851 return ERROR;
2852 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002853 if (options_->progress_updates_to_socket) {
2854 options_->do_progress_updates = 1;
2855 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002856 }
2857
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002858 if (!PrepareToWriteToFile()) {
2859 return ERROR;
2860 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002861
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002862 // Interactive, wear & telephony modes are default to true.
2863 // and may enable from cli option or when using control socket
2864 if (options_->do_progress_updates) {
2865 // clang-format off
2866 std::vector<std::string> am_args = {
2867 "--receiver-permission", "android.permission.DUMP",
2868 };
2869 // clang-format on
2870 // Send STARTED broadcast for apps that listen to bugreport generation events
2871 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2872 if (options_->progress_updates_to_socket) {
2873 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002874 }
2875 }
2876
Nick Kralevichf3599b32016-01-25 15:05:16 -08002877 /* read /proc/cmdline before dropping root */
2878 FILE *cmdline = fopen("/proc/cmdline", "re");
2879 if (cmdline) {
2880 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2881 fclose(cmdline);
2882 }
2883
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002884 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002885 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002886 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002887
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002888 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002889 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2890 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002891 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002892 }
2893 }
2894
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002895 int dup_stdout_fd;
2896 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002897 // Redirect stderr to log_path_ for debugging.
2898 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2899 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2900 return ERROR;
2901 }
2902 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2903 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2904 strerror(errno));
2905 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002906
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002907 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2908 // moved into zip file later, if zipping.
2909 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2910 // TODO: why not write to a file instead of stdout to overcome this problem?
2911 /* TODO: rather than generating a text file now and zipping it later,
2912 it would be more efficient to redirect stdout to the zip entry
2913 directly, but the libziparchive doesn't support that option yet. */
2914 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2915 return ERROR;
2916 }
2917 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2918 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2919 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002920 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002921
2922 // Don't buffer stdout
2923 setvbuf(stdout, nullptr, _IONBF, 0);
2924
Rhed Jao5377d792020-07-16 17:37:39 +08002925 // Enable the parallel run if the client requests to output to a file.
2926 EnableParallelRunIfNeeded();
2927 // Using scope guard to make sure the dump pool can be shut down correctly.
2928 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2929 ShutdownDumpPool();
2930 });
2931
Felipe Leme608385d2016-02-01 10:35:38 -08002932 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2933 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002934 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002935 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002936
Gavin Corkery6968f552020-11-22 18:09:05 +00002937 bool is_dumpstate_restricted = options_->telephony_only
2938 || options_->wifi_only
2939 || options_->limited_only;
2940 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002941 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002942 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00002943 }
2944 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00002945
2946 if (!is_dumpstate_restricted) {
2947 // Snapshot the system trace now (if running) to avoid that dumpstate's
2948 // own activity pushes out interesting data from the trace ring buffer.
2949 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
2950 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08002951
2952 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
2953 // from WMTRACE_DATA_DIR.
2954 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00002955 }
Gavin Corkery6968f552020-11-22 18:09:05 +00002956 onUiIntensiveBugreportDumpsFinished(calling_uid);
2957 MaybeCheckUserConsent(calling_uid, calling_package);
2958 if (options_->telephony_only) {
2959 DumpstateTelephonyOnly(calling_package);
2960 } else if (options_->wifi_only) {
2961 DumpstateWifiOnly();
2962 } else if (options_->limited_only) {
2963 DumpstateLimitedOnly();
2964 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002965 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002966 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002967 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002968 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002969 HandleUserConsentDenied();
2970 }
2971 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002972 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002973 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002974
Felipe Leme55b42a62015-11-10 17:39:08 -08002975 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002976 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002977
Abhijeet Kaure370d682019-10-01 16:49:30 +01002978 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002979 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002980
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002981 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002982 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002983 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002984 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002985 if (status != Dumpstate::RunStatus::OK &&
2986 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2987 // Do an early return if there were errors. We make an exception for consent
2988 // timing out because it's possible the user got distracted. In this case the
2989 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002990 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002991 return status;
2992 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002993 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2994 MYLOGI(
2995 "Did not receive user consent yet."
2996 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002997 const String16 incidentcompanion("incidentcompanion");
2998 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2999 if (ics != nullptr) {
3000 MYLOGD("Canceling user consent request via incidentcompanion service\n");
3001 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
3002 consent_callback_.get());
3003 } else {
3004 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
3005 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00003006 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003007 }
3008
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003009 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003010 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09003011 for (int i = 0; i < 3; i++) {
3012 Vibrate(75);
3013 usleep((75 + 50) * 1000);
3014 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08003015 }
3016
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003017 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3018 progress_->GetInitialMax());
3019 progress_->Save();
3020 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003021
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003022 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003023
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003024 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003025 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003026 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003027 }
3028
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003029 tombstone_data_.clear();
3030 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003031
Nandana Duttd2f5f082019-01-18 17:13:52 +00003032 return (consent_callback_ != nullptr &&
3033 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3034 ? USER_CONSENT_TIMED_OUT
3035 : RunStatus::OK;
3036}
3037
Paul Chang0d2aad72020-02-13 20:04:03 +08003038void Dumpstate::MaybeTakeEarlyScreenshot() {
3039 if (!options_->do_screenshot || !do_early_screenshot_) {
3040 return;
3041 }
3042
3043 TakeScreenshot();
3044}
3045
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003046void Dumpstate::MaybeSnapshotSystemTrace() {
3047 // If a background system trace is happening and is marked as "suitable for
3048 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3049 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3050 // case that no trace is ongoing, this command is a no-op.
3051 // Note: this should not be enqueued as we need to freeze the trace before
3052 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3053 // the dumpstate's own activity which is irrelevant.
3054 int res = RunCommand(
3055 "SERIALIZE PERFETTO TRACE",
3056 {"perfetto", "--save-for-bugreport"},
3057 CommandOptions::WithTimeout(10)
3058 .DropRoot()
3059 .CloseAllFileDescriptorsOnExec()
3060 .Build());
3061 has_system_trace_ = res == 0;
3062 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3063 // file in the later stages.
3064}
3065
Yohei Yukawa95305b32021-03-09 07:54:27 -08003066void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003067 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3068 for (const auto& service : {"window", "input_method"}) {
3069 RunCommand(
3070 // Empty name because it's not intended to be classified as a bugreport section.
3071 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3072 "", {"cmd", service, "tracing", "save-for-bugreport"},
3073 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3074 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003075}
3076
Paul Changeb4b4642020-05-28 22:05:47 +08003077void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003078 if (calling_uid == AID_SHELL || !CalledByApi()) {
3079 return;
3080 }
3081 if (listener_ != nullptr) {
3082 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3083 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08003084 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003085 }
3086}
3087
Jichao Lie89d9c12019-11-21 19:02:51 -08003088void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3089 if (calling_uid == AID_SHELL || !CalledByApi()) {
3090 // No need to get consent for shell triggered dumpstates, or not through
3091 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003092 return;
3093 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003094 consent_callback_ = new ConsentCallback();
3095 const String16 incidentcompanion("incidentcompanion");
3096 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003097 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003098 if (ics != nullptr) {
3099 MYLOGD("Checking user consent via incidentcompanion service\n");
3100 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003101 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003102 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003103 } else {
3104 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3105 }
3106}
3107
Nandana Dutt5c390032019-03-12 10:52:56 +00003108bool Dumpstate::IsUserConsentDenied() const {
3109 return ds.consent_callback_ != nullptr &&
3110 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3111}
3112
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003113bool Dumpstate::CalledByApi() const {
3114 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3115}
3116
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003117void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003118 android::os::UnlinkAndLogOnError(tmp_path_);
3119 android::os::UnlinkAndLogOnError(screenshot_path_);
3120 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003121 if (dump_traces_path != nullptr) {
3122 android::os::UnlinkAndLogOnError(dump_traces_path);
3123 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003124}
3125
Rhed Jao5377d792020-07-16 17:37:39 +08003126void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003127 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao5377d792020-07-16 17:37:39 +08003128 return;
3129 }
3130 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003131 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08003132}
3133
3134void Dumpstate::ShutdownDumpPool() {
3135 if (dump_pool_) {
3136 dump_pool_->shutdown();
3137 dump_pool_ = nullptr;
3138 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003139 if (zip_entry_tasks_) {
3140 zip_entry_tasks_->run(/* do_cancel = */true);
3141 zip_entry_tasks_ = nullptr;
3142 }
3143}
3144
3145void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3146 const std::string& entry_path) {
3147 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3148 if (!task_cancelled) {
3149 AddZipEntry(entry_name, entry_path);
3150 }
3151 android::os::UnlinkAndLogOnError(entry_path);
3152 };
3153 if (zip_entry_tasks_) {
3154 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3155 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3156 } else {
3157 // Invokes AddZipEntryAndCleanup immediately
3158 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3159 }
Rhed Jao5377d792020-07-16 17:37:39 +08003160}
3161
Nandana Duttd2f5f082019-01-18 17:13:52 +00003162Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3163 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003164 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003165 return USER_CONSENT_DENIED;
3166}
3167
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003168Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003169 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003170 // user consent (unless the caller is Shell).
3171 UserConsentResult consent_result;
3172 if (calling_uid == AID_SHELL) {
3173 consent_result = UserConsentResult::APPROVED;
3174 } else {
3175 consent_result = consent_callback_->getResult();
3176 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003177 if (consent_result == UserConsentResult::UNAVAILABLE) {
3178 // User has not responded yet.
3179 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003180 // Telephony is a fast report type, particularly on user builds where information may be
3181 // more aggressively limited. To give the user time to read the consent dialog, increase the
3182 // timeout.
3183 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3184 : USER_CONSENT_TIMEOUT_MS;
3185 if (elapsed_ms < timeout_ms) {
3186 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003187 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3188 sleep(delay_seconds);
3189 }
3190 consent_result = consent_callback_->getResult();
3191 }
3192 if (consent_result == UserConsentResult::DENIED) {
3193 // User has explicitly denied sharing with the app. To be safe delete the
3194 // internal bugreport & tmp files.
3195 return HandleUserConsentDenied();
3196 }
3197 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003198 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3199 if (copy_succeeded) {
3200 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003201 if (options_->do_screenshot &&
3202 options_->screenshot_fd.get() != -1 &&
3203 !options_->is_screenshot_copied) {
3204 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3205 options_->screenshot_fd.get());
3206 options_->is_screenshot_copied = copy_succeeded;
3207 if (copy_succeeded) {
3208 android::os::UnlinkAndLogOnError(screenshot_path_);
3209 }
3210 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003211 }
3212 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3213 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3214 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3215 // Since we do not have user consent to share the bugreport it does not get
3216 // copied over to the calling app but remains in the internal directory from
3217 // where the user can manually pull it.
Paul Changce644212021-05-11 16:06:45 +08003218 std::string final_path = GetPath(".zip");
3219 bool copy_succeeded = android::os::CopyFileToFile(path_, final_path);
3220 if (copy_succeeded) {
3221 android::os::UnlinkAndLogOnError(path_);
3222 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003223 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3224 }
3225 // Unknown result; must be a programming error.
3226 MYLOGE("Unknown user consent result:%d\n", consent_result);
3227 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003228}
3229
Nandana Duttf02564e2019-02-15 15:24:24 +00003230Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003231 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3232 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3233 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003234 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003235 // When directly running dumpstate binary, the output is not expected to be written
3236 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003237 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003238
3239 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003240 // an app; they are irrelevant here because bugreport is triggered via command line.
3241 // Update Last ID before calling Run().
3242 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003243 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003244 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003245 return status;
3246}
3247
3248/* Main entry point for dumpstate binary. */
3249int run_main(int argc, char* argv[]) {
3250 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003251
3252 switch (status) {
3253 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003254 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003255 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003256 ShowUsage();
3257 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003258 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003259 fprintf(stderr, "Invalid combination of args\n");
3260 ShowUsage();
3261 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003262 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003263 FALLTHROUGH_INTENDED;
3264 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3265 FALLTHROUGH_INTENDED;
3266 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003267 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003268 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003269}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003270
3271// TODO(111441001): Default DumpOptions to sensible values.
3272Dumpstate::Dumpstate(const std::string& version)
3273 : pid_(getpid()),
3274 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003275 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003276 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003277 now_(time(nullptr)),
3278 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003279}
3280
3281Dumpstate& Dumpstate::GetInstance() {
3282 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3283 return singleton_;
3284}
3285
Rhed Jao5377d792020-07-16 17:37:39 +08003286DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3287 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3288 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003289 if (!title_.empty()) {
3290 started_ = Nanotime();
3291 }
3292}
3293
3294DurationReporter::~DurationReporter() {
3295 if (!title_.empty()) {
3296 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003297 if (elapsed >= .5f || verbose_) {
3298 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003299 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003300 if (!logcat_only_) {
3301 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003302 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3303 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003304 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003305 }
3306}
3307
3308const int32_t Progress::kDefaultMax = 5000;
3309
3310Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3311}
3312
3313Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3314 : Progress(initial_max, growth_factor, "") {
3315 progress_ = progress;
3316}
3317
3318Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3319 : initial_max_(initial_max),
3320 progress_(0),
3321 max_(initial_max),
3322 growth_factor_(growth_factor),
3323 n_runs_(0),
3324 average_max_(0),
3325 path_(path) {
3326 if (!path_.empty()) {
3327 Load();
3328 }
3329}
3330
3331void Progress::Load() {
3332 MYLOGD("Loading stats from %s\n", path_.c_str());
3333 std::string content;
3334 if (!android::base::ReadFileToString(path_, &content)) {
3335 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3336 return;
3337 }
3338 if (content.empty()) {
3339 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3340 return;
3341 }
3342 std::vector<std::string> lines = android::base::Split(content, "\n");
3343
3344 if (lines.size() < 1) {
3345 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3346 (int)lines.size(), max_);
3347 return;
3348 }
3349 char* ptr;
3350 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3351 average_max_ = strtol(ptr, nullptr, 10);
3352 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3353 average_max_ > STATS_MAX_AVERAGE) {
3354 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3355 initial_max_ = Progress::kDefaultMax;
3356 } else {
3357 initial_max_ = average_max_;
3358 }
3359 max_ = initial_max_;
3360
3361 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3362}
3363
3364void Progress::Save() {
3365 int32_t total = n_runs_ * average_max_ + progress_;
3366 int32_t runs = n_runs_ + 1;
3367 int32_t average = floor(((float)total) / runs);
3368 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3369 path_.c_str());
3370 if (path_.empty()) {
3371 return;
3372 }
3373
3374 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3375 if (!android::base::WriteStringToFile(content, path_)) {
3376 MYLOGE("Could not save stats on %s\n", path_.c_str());
3377 }
3378}
3379
3380int32_t Progress::Get() const {
3381 return progress_;
3382}
3383
3384bool Progress::Inc(int32_t delta_sec) {
3385 bool changed = false;
3386 if (delta_sec >= 0) {
3387 progress_ += delta_sec;
3388 if (progress_ > max_) {
3389 int32_t old_max = max_;
3390 max_ = floor((float)progress_ * growth_factor_);
3391 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3392 changed = true;
3393 }
3394 }
3395 return changed;
3396}
3397
3398int32_t Progress::GetMax() const {
3399 return max_;
3400}
3401
3402int32_t Progress::GetInitialMax() const {
3403 return initial_max_;
3404}
3405
3406void Progress::Dump(int fd, const std::string& prefix) const {
3407 const char* pr = prefix.c_str();
3408 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3409 dprintf(fd, "%smax: %d\n", pr, max_);
3410 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3411 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3412 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3413 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3414 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3415}
3416
3417bool Dumpstate::IsZipping() const {
3418 return zip_writer_ != nullptr;
3419}
3420
3421std::string Dumpstate::GetPath(const std::string& suffix) const {
3422 return GetPath(bugreport_internal_dir_, suffix);
3423}
3424
3425std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3426 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3427 name_.c_str(), suffix.c_str());
3428}
3429
3430void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3431 progress_ = std::move(progress);
3432}
3433
3434void for_each_userid(void (*func)(int), const char *header) {
3435 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3436 "for_each_userid(%s)", header);
3437 DurationReporter duration_reporter(title);
3438 if (PropertiesHelper::IsDryRun()) return;
3439
3440 DIR *d;
3441 struct dirent *de;
3442
3443 if (header) printf("\n------ %s ------\n", header);
3444 func(0);
3445
3446 if (!(d = opendir("/data/system/users"))) {
3447 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3448 return;
3449 }
3450
3451 while ((de = readdir(d))) {
3452 int userid;
3453 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3454 continue;
3455 }
3456 func(userid);
3457 }
3458
3459 closedir(d);
3460}
3461
3462static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3463 DIR *d;
3464 struct dirent *de;
3465
3466 if (!(d = opendir("/proc"))) {
3467 printf("Failed to open /proc (%s)\n", strerror(errno));
3468 return;
3469 }
3470
3471 if (header) printf("\n------ %s ------\n", header);
3472 while ((de = readdir(d))) {
3473 if (ds.IsUserConsentDenied()) {
3474 MYLOGE(
3475 "Returning early because user denied consent to share bugreport with calling app.");
3476 closedir(d);
3477 return;
3478 }
3479 int pid;
3480 int fd;
3481 char cmdpath[255];
3482 char cmdline[255];
3483
3484 if (!(pid = atoi(de->d_name))) {
3485 continue;
3486 }
3487
3488 memset(cmdline, 0, sizeof(cmdline));
3489
3490 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3491 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3492 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3493 close(fd);
3494 if (cmdline[0]) {
3495 helper(pid, cmdline, arg);
3496 continue;
3497 }
3498 }
3499
3500 // if no cmdline, a kernel thread has comm
3501 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3502 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3503 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3504 close(fd);
3505 if (cmdline[1]) {
3506 cmdline[0] = '[';
3507 size_t len = strcspn(cmdline, "\f\b\r\n");
3508 cmdline[len] = ']';
3509 cmdline[len+1] = '\0';
3510 }
3511 }
3512 if (!cmdline[0]) {
3513 strcpy(cmdline, "N/A");
3514 }
3515 helper(pid, cmdline, arg);
3516 }
3517
3518 closedir(d);
3519}
3520
3521static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3522 for_each_pid_func *func = (for_each_pid_func*) arg;
3523 func(pid, cmdline);
3524}
3525
3526void for_each_pid(for_each_pid_func func, const char *header) {
3527 std::string title = header == nullptr ? "for_each_pid"
3528 : android::base::StringPrintf("for_each_pid(%s)", header);
3529 DurationReporter duration_reporter(title);
3530 if (PropertiesHelper::IsDryRun()) return;
3531
3532 __for_each_pid(for_each_pid_helper, header, (void *) func);
3533}
3534
3535static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3536 DIR *d;
3537 struct dirent *de;
3538 char taskpath[255];
3539 for_each_tid_func *func = (for_each_tid_func *) arg;
3540
3541 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3542
3543 if (!(d = opendir(taskpath))) {
3544 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3545 return;
3546 }
3547
3548 func(pid, pid, cmdline);
3549
3550 while ((de = readdir(d))) {
3551 if (ds.IsUserConsentDenied()) {
3552 MYLOGE(
3553 "Returning early because user denied consent to share bugreport with calling app.");
3554 closedir(d);
3555 return;
3556 }
3557 int tid;
3558 int fd;
3559 char commpath[255];
3560 char comm[255];
3561
3562 if (!(tid = atoi(de->d_name))) {
3563 continue;
3564 }
3565
3566 if (tid == pid)
3567 continue;
3568
3569 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3570 memset(comm, 0, sizeof(comm));
3571 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3572 strcpy(comm, "N/A");
3573 } else {
3574 char *c;
3575 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3576 close(fd);
3577
3578 c = strrchr(comm, '\n');
3579 if (c) {
3580 *c = '\0';
3581 }
3582 }
3583 func(pid, tid, comm);
3584 }
3585
3586 closedir(d);
3587}
3588
3589void for_each_tid(for_each_tid_func func, const char *header) {
3590 std::string title = header == nullptr ? "for_each_tid"
3591 : android::base::StringPrintf("for_each_tid(%s)", header);
3592 DurationReporter duration_reporter(title);
3593
3594 if (PropertiesHelper::IsDryRun()) return;
3595
3596 __for_each_pid(for_each_tid_helper, header, (void *) func);
3597}
3598
3599void show_wchan(int pid, int tid, const char *name) {
3600 if (PropertiesHelper::IsDryRun()) return;
3601
3602 char path[255];
3603 char buffer[255];
3604 int fd, ret, save_errno;
3605 char name_buffer[255];
3606
3607 memset(buffer, 0, sizeof(buffer));
3608
3609 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3610 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3611 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3612 return;
3613 }
3614
3615 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3616 save_errno = errno;
3617 close(fd);
3618
3619 if (ret < 0) {
3620 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3621 return;
3622 }
3623
3624 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3625 pid == tid ? 0 : 3, "", name);
3626
3627 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3628
3629 return;
3630}
3631
3632// print time in centiseconds
3633static void snprcent(char *buffer, size_t len, size_t spc,
3634 unsigned long long time) {
3635 static long hz; // cache discovered hz
3636
3637 if (hz <= 0) {
3638 hz = sysconf(_SC_CLK_TCK);
3639 if (hz <= 0) {
3640 hz = 1000;
3641 }
3642 }
3643
3644 // convert to centiseconds
3645 time = (time * 100 + (hz / 2)) / hz;
3646
3647 char str[16];
3648
3649 snprintf(str, sizeof(str), " %llu.%02u",
3650 time / 100, (unsigned)(time % 100));
3651 size_t offset = strlen(buffer);
3652 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3653 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3654}
3655
3656// print permille as a percent
3657static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3658 char str[16];
3659
3660 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3661 size_t offset = strlen(buffer);
3662 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3663 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3664}
3665
3666void show_showtime(int pid, const char *name) {
3667 if (PropertiesHelper::IsDryRun()) return;
3668
3669 char path[255];
3670 char buffer[1023];
3671 int fd, ret, save_errno;
3672
3673 memset(buffer, 0, sizeof(buffer));
3674
3675 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3676 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3677 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3678 return;
3679 }
3680
3681 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3682 save_errno = errno;
3683 close(fd);
3684
3685 if (ret < 0) {
3686 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3687 return;
3688 }
3689
3690 // field 14 is utime
3691 // field 15 is stime
3692 // field 42 is iotime
3693 unsigned long long utime = 0, stime = 0, iotime = 0;
3694 if (sscanf(buffer,
3695 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3696 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3697 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3698 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3699 &utime, &stime, &iotime) != 3) {
3700 return;
3701 }
3702
3703 unsigned long long total = utime + stime;
3704 if (!total) {
3705 return;
3706 }
3707
3708 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3709 if (permille > 1000) {
3710 permille = 1000;
3711 }
3712
3713 // try to beautify and stabilize columns at <80 characters
3714 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3715 if ((name[0] != '[') || utime) {
3716 snprcent(buffer, sizeof(buffer), 57, utime);
3717 }
3718 snprcent(buffer, sizeof(buffer), 65, stime);
3719 if ((name[0] != '[') || iotime) {
3720 snprcent(buffer, sizeof(buffer), 73, iotime);
3721 }
3722 if (iotime) {
3723 snprdec(buffer, sizeof(buffer), 79, permille);
3724 }
3725 puts(buffer); // adds a trailing newline
3726
3727 return;
3728}
3729
3730void do_dmesg() {
3731 const char *title = "KERNEL LOG (dmesg)";
3732 DurationReporter duration_reporter(title);
3733 printf("------ %s ------\n", title);
3734
3735 if (PropertiesHelper::IsDryRun()) return;
3736
3737 /* Get size of kernel buffer */
3738 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3739 if (size <= 0) {
3740 printf("Unexpected klogctl return value: %d\n\n", size);
3741 return;
3742 }
3743 char *buf = (char *) malloc(size + 1);
3744 if (buf == nullptr) {
3745 printf("memory allocation failed\n\n");
3746 return;
3747 }
3748 int retval = klogctl(KLOG_READ_ALL, buf, size);
3749 if (retval < 0) {
3750 printf("klogctl failure\n\n");
3751 free(buf);
3752 return;
3753 }
3754 buf[retval] = '\0';
3755 printf("%s\n\n", buf);
3756 free(buf);
3757 return;
3758}
3759
3760void do_showmap(int pid, const char *name) {
3761 char title[255];
3762 char arg[255];
3763
3764 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3765 snprintf(arg, sizeof(arg), "%d", pid);
3766 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3767}
3768
3769int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3770 DurationReporter duration_reporter(title);
3771
3772 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3773
3774 UpdateProgress(WEIGHT_FILE);
3775
3776 return status;
3777}
3778
3779int read_file_as_long(const char *path, long int *output) {
3780 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3781 if (fd < 0) {
3782 int err = errno;
3783 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3784 return -1;
3785 }
3786 char buffer[50];
3787 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3788 if (bytes_read == -1) {
3789 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3790 return -2;
3791 }
3792 if (bytes_read == 0) {
3793 MYLOGE("File %s is empty\n", path);
3794 return -3;
3795 }
3796 *output = atoi(buffer);
3797 return 0;
3798}
3799
3800/* calls skip to gate calling dump_from_fd recursively
3801 * in the specified directory. dump_from_fd defaults to
3802 * dump_file_from_fd above when set to NULL. skip defaults
3803 * to false when set to NULL. dump_from_fd will always be
3804 * called with title NULL.
3805 */
3806int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3807 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3808 DurationReporter duration_reporter(title);
3809 DIR *dirp;
3810 struct dirent *d;
3811 char *newpath = nullptr;
3812 const char *slash = "/";
3813 int retval = 0;
3814
3815 if (!title.empty()) {
3816 printf("------ %s (%s) ------\n", title.c_str(), dir);
3817 }
3818 if (PropertiesHelper::IsDryRun()) return 0;
3819
3820 if (dir[strlen(dir) - 1] == '/') {
3821 ++slash;
3822 }
3823 dirp = opendir(dir);
3824 if (dirp == nullptr) {
3825 retval = -errno;
3826 MYLOGE("%s: %s\n", dir, strerror(errno));
3827 return retval;
3828 }
3829
3830 if (!dump_from_fd) {
3831 dump_from_fd = dump_file_from_fd;
3832 }
3833 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3834 if ((d->d_name[0] == '.')
3835 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3836 || (d->d_name[1] == '\0'))) {
3837 continue;
3838 }
3839 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3840 (d->d_type == DT_DIR) ? "/" : "");
3841 if (!newpath) {
3842 retval = -errno;
3843 continue;
3844 }
3845 if (skip && (*skip)(newpath)) {
3846 continue;
3847 }
3848 if (d->d_type == DT_DIR) {
3849 int ret = dump_files("", newpath, skip, dump_from_fd);
3850 if (ret < 0) {
3851 retval = ret;
3852 }
3853 continue;
3854 }
3855 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3856 if (fd.get() < 0) {
3857 retval = -1;
3858 printf("*** %s: %s\n", newpath, strerror(errno));
3859 continue;
3860 }
3861 (*dump_from_fd)(nullptr, newpath, fd.get());
3862 }
3863 closedir(dirp);
3864 if (!title.empty()) {
3865 printf("\n");
3866 }
3867 return retval;
3868}
3869
3870/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3871 * it's possible to avoid issues where opening the file itself can get
3872 * stuck.
3873 */
3874int dump_file_from_fd(const char *title, const char *path, int fd) {
3875 if (PropertiesHelper::IsDryRun()) return 0;
3876
3877 int flags = fcntl(fd, F_GETFL);
3878 if (flags == -1) {
3879 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3880 return -1;
3881 } else if (!(flags & O_NONBLOCK)) {
3882 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3883 return -1;
3884 }
3885 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3886}
3887
3888int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003889 const CommandOptions& options, bool verbose_duration, int out_fd) {
3890 DurationReporter duration_reporter(title, false /* logcat_only */,
3891 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003892
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003893 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003894
3895 /* TODO: for now we're simplifying the progress calculation by using the
3896 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3897 * where its weight should be much higher proportionally to its timeout.
3898 * Ideally, it should use a options.EstimatedDuration() instead...*/
3899 UpdateProgress(options.Timeout());
3900
3901 return status;
3902}
3903
3904void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jaoe017f982020-07-21 17:58:41 +08003905 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003906 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3907 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3908 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jaoe017f982020-07-21 17:58:41 +08003909 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003910}
3911
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003912static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003913 int s = android_get_control_socket(service);
3914 if (s < 0) {
3915 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3916 return -1;
3917 }
3918 fcntl(s, F_SETFD, FD_CLOEXEC);
3919
3920 // Set backlog to 0 to make sure that queue size will be minimum.
3921 // In Linux, because the minimum queue will be 1, connect() will be blocked
3922 // if the other clients already called connect() and the connection request was not accepted.
3923 if (listen(s, 0) < 0) {
3924 MYLOGE("listen(control socket): %s\n", strerror(errno));
3925 return -1;
3926 }
3927
3928 struct sockaddr addr;
3929 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003930 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003931
3932 // Close socket just after accept(), to make sure that connect() by client will get error
3933 // when the socket is used by the other services.
3934 // There is still a race condition possibility between accept and close, but there is no way
3935 // to close-on-accept atomically.
3936 // See detail; b/123306389#comment25
3937 close(s);
3938
3939 if (fd < 0) {
3940 MYLOGE("accept(control socket): %s\n", strerror(errno));
3941 return -1;
3942 }
3943
3944 return fd;
3945}
3946
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003947// TODO: should call is_valid_output_file and/or be merged into it.
3948void create_parent_dirs(const char *path) {
3949 char *chp = const_cast<char *> (path);
3950
3951 /* skip initial slash */
3952 if (chp[0] == '/')
3953 chp++;
3954
3955 /* create leading directories, if necessary */
3956 struct stat dir_stat;
3957 while (chp && chp[0]) {
3958 chp = strchr(chp, '/');
3959 if (chp) {
3960 *chp = 0;
3961 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3962 MYLOGI("Creating directory %s\n", path);
3963 if (mkdir(path, 0770)) { /* drwxrwx--- */
3964 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3965 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3966 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3967 }
3968 }
3969 *chp++ = '/';
3970 }
3971 }
3972}
3973
3974bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3975 create_parent_dirs(path);
3976
3977 int fd = TEMP_FAILURE_RETRY(open(path,
3978 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3979 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3980 if (fd < 0) {
3981 MYLOGE("%s: %s\n", path, strerror(errno));
3982 return false;
3983 }
3984
3985 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3986 close(fd);
3987 return true;
3988}
3989
3990bool redirect_to_file(FILE* redirect, char* path) {
3991 return _redirect_to_file(redirect, path, O_TRUNC);
3992}
3993
3994bool redirect_to_existing_file(FILE* redirect, char* path) {
3995 return _redirect_to_file(redirect, path, O_APPEND);
3996}
3997
3998void dump_route_tables() {
3999 DurationReporter duration_reporter("DUMP ROUTE TABLES");
4000 if (PropertiesHelper::IsDryRun()) return;
4001 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
4002 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
4003 FILE* fp = fopen(RT_TABLES_PATH, "re");
4004 if (!fp) {
4005 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
4006 return;
4007 }
4008 char table[16];
4009 // Each line has an integer (the table number), a space, and a string (the table name). We only
4010 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
4011 // Add a fixed max limit so this doesn't go awry.
4012 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
4013 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
4014 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
4015 }
4016 fclose(fp);
4017}
4018
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004019void Dumpstate::UpdateProgress(int32_t delta_sec) {
4020 if (progress_ == nullptr) {
4021 MYLOGE("UpdateProgress: progress_ not set\n");
4022 return;
4023 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08004024 // This function updates progress related members of the dumpstate and reports
4025 // progress percentage to the bugreport client. Since it could be called by
4026 // different dump tasks at the same time if the parallel run is enabled, a
4027 // mutex lock is necessary here to synchronize the call.
4028 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004029
4030 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01004031 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004032
4033 // ...but only notifiy listeners when necessary.
4034 if (!options_->do_progress_updates) return;
4035
4036 int progress = progress_->Get();
4037 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01004038 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004039
Nandana Dutt402a8392019-06-14 14:25:13 +01004040 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004041 return;
4042 }
Nandana Dutt402a8392019-06-14 14:25:13 +01004043 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004044
4045 if (control_socket_fd_ >= 0) {
4046 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4047 fsync(control_socket_fd_);
4048 }
4049
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004050 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004051 if (percent % 10 == 0) {
4052 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004053 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004054 } else {
4055 // stderr is ignored on normal invocations, but useful when calling
4056 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004057 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004058 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004059
4060 listener_->onProgress(percent);
4061 }
4062}
4063
4064void Dumpstate::TakeScreenshot(const std::string& path) {
4065 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4066 int status =
4067 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4068 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4069 if (status == 0) {
4070 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4071 } else {
4072 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4073 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004074 if (listener_ != nullptr) {
4075 // Show a visual indication to indicate screenshot is taken via
4076 // IDumpstateListener.onScreenshotTaken()
4077 listener_->onScreenshotTaken(status == 0);
4078 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004079}
4080
4081bool is_dir(const char* pathname) {
4082 struct stat info;
4083 if (stat(pathname, &info) == -1) {
4084 return false;
4085 }
4086 return S_ISDIR(info.st_mode);
4087}
4088
4089time_t get_mtime(int fd, time_t default_mtime) {
4090 struct stat info;
4091 if (fstat(fd, &info) == -1) {
4092 return default_mtime;
4093 }
4094 return info.st_mtime;
4095}