blob: 8f466ca57e1fc3ab9ee9fe59478193ae8db3bd08 [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 Jao1c855122020-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 Jao1c855122020-07-16 17:37:39 +0800118using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800119using android::os::dumpstate::PropertiesHelper;
Rhed Jao4875aa62020-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 Jao4875aa62020-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 Juravle78a0d842020-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"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700179
Narayan Kamath8f788292017-05-25 13:20:39 +0100180// TODO(narayan): Since this information has to be kept in sync
181// with tombstoned, we should just put it in a common header.
182//
183// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100184static const std::string TOMBSTONE_DIR = "/data/tombstones/";
185static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
186static const std::string ANR_DIR = "/data/anr/";
187static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700188
Felipe Lemee844a9d2016-09-21 15:01:39 -0700189// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000190
Nandana Dutt5c390032019-03-12 10:52:56 +0000191#define RETURN_IF_USER_DENIED_CONSENT() \
192 if (ds.IsUserConsentDenied()) { \
193 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
194 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
195 }
196
197// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
198// if consent is found to be denied.
199#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
200 RETURN_IF_USER_DENIED_CONSENT(); \
201 func_ptr(__VA_ARGS__); \
202 RETURN_IF_USER_DENIED_CONSENT();
203
Rhed Jao1c855122020-07-16 17:37:39 +0800204// Runs func_ptr, and logs a duration report after it's finished.
205#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
206 { \
207 DurationReporter duration_reporter_in_macro(log_title); \
208 func_ptr(__VA_ARGS__); \
209 }
210
211// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
212// is output after a slow function is finished.
213#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
214 RETURN_IF_USER_DENIED_CONSENT(); \
215 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
216 RETURN_IF_USER_DENIED_CONSENT();
217
Rhed Jao4875aa62020-07-20 17:46:29 +0800218#define WAIT_TASK_WITH_CONSENT_CHECK(task_name, pool_ptr) \
219 RETURN_IF_USER_DENIED_CONSENT(); \
220 pool_ptr->waitForTask(task_name); \
221 RETURN_IF_USER_DENIED_CONSENT();
222
Sahana Raof35ed432019-07-12 10:47:52 +0100223static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
224
Rhed Jao1c855122020-07-16 17:37:39 +0800225// Names of parallel tasks, they are used for the DumpPool to identify the dump
226// task and the log title of the duration report.
227static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao4875aa62020-07-20 17:46:29 +0800228static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
229static const std::string DUMP_HALS_TASK = "DUMP HALS";
230static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jao6b1ea2d2020-07-21 17:58:41 +0800231static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao1c855122020-07-16 17:37:39 +0800232
Nandana Dutt979388e2018-11-30 16:48:55 +0000233namespace android {
234namespace os {
235namespace {
236
237static int Open(std::string path, int flags, mode_t mode = 0) {
238 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
239 if (fd == -1) {
240 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
241 }
242 return fd;
243}
244
mhasank2d75c442020-06-11 15:05:25 -0700245static int OpenForWrite(std::string path) {
246 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
247 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
248}
Nandana Dutt979388e2018-11-30 16:48:55 +0000249
250static int OpenForRead(std::string path) {
251 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
252}
253
254bool CopyFile(int in_fd, int out_fd) {
255 char buf[4096];
256 ssize_t byte_count;
257 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
258 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
259 return false;
260 }
261 }
262 return (byte_count != -1);
263}
264
265static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000266 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000267
268 // Obtain a handle to the source file.
269 android::base::unique_fd in_fd(OpenForRead(input_file));
270 if (out_fd != -1 && in_fd.get() != -1) {
271 if (CopyFile(in_fd.get(), out_fd)) {
272 return true;
273 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000274 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000275 }
276 return false;
277}
278
Nandana Duttd2f5f082019-01-18 17:13:52 +0000279static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000280 if (file.empty()) {
281 return false;
282 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000283 if (unlink(file.c_str())) {
284 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000285 return false;
286 }
287 return true;
288}
Nandana Dutt979388e2018-11-30 16:48:55 +0000289
Nikita Ioffea325a572019-05-16 19:49:47 +0100290int64_t GetModuleMetadataVersion() {
291 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
292 if (binder == nullptr) {
293 MYLOGE("Failed to retrieve package_native service");
294 return 0L;
295 }
296 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
297 std::string package_name;
298 auto status = package_service->getModuleMetadataPackageName(&package_name);
299 if (!status.isOk()) {
300 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
301 return 0L;
302 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100303 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100304 int64_t version_code;
305 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
306 &version_code);
307 if (!status.isOk()) {
308 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
309 return 0L;
310 }
311 return version_code;
312}
313
mhasank2d75c442020-06-11 15:05:25 -0700314static bool PathExists(const std::string& path) {
315 struct stat sb;
316 return stat(path.c_str(), &sb) == 0;
317}
318
319static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
320 if (input_file == output_file) {
321 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
322 output_file.c_str());
323 return false;
324 }
325 else if (PathExists(output_file)) {
326 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
327 return false;
328 }
329
330 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
331 android::base::unique_fd out_fd(OpenForWrite(output_file));
332 return CopyFileToFd(input_file, out_fd.get());
333}
334
Nandana Dutt979388e2018-11-30 16:48:55 +0000335} // namespace
336} // namespace os
337} // namespace android
338
Felipe Leme678727a2016-09-21 17:22:11 -0700339static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800340 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jao6b1ea2d2020-07-21 17:58:41 +0800341 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
342 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
343}
344static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
345 int out_fd) {
346 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700347}
348static int DumpFile(const std::string& title, const std::string& path) {
349 return ds.DumpFile(title, path);
350}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800351
Felipe Lemee844a9d2016-09-21 15:01:39 -0700352// Relative directory (inside the zip) for all files copied as-is into the bugreport.
353static const std::string ZIP_ROOT_DIR = "FS";
354
Vishnu Naire97d6122018-01-18 13:58:56 -0800355static const std::string kProtoPath = "proto/";
356static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700357static const std::string kDumpstateBoardFiles[] = {
358 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700359 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700360};
361static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
362
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700363static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700364static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700365
Felipe Lemef0292972016-11-22 13:57:05 -0800366static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
367
Narayan Kamath8f788292017-05-25 13:20:39 +0100368/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100369 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800370 * The returned vector is sorted by the mtimes of the dumps with descending
371 * order. If |limit_by_mtime| is set, the vector only contains files that
372 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100373 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700374static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
375 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700376 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100377 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
378
Narayan Kamathbd863722017-06-01 18:50:12 +0100379 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100380
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700381 if (dump_dir == nullptr) {
382 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700383 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700384 }
385
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700386 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100387 struct dirent* entry = nullptr;
388 while ((entry = readdir(dump_dir.get()))) {
389 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100390 continue;
391 }
392
Narayan Kamathbd863722017-06-01 18:50:12 +0100393 const std::string base_name(entry->d_name);
394 if (base_name.find(file_prefix) != 0) {
395 continue;
396 }
397
398 const std::string abs_path = dir_path + base_name;
399 android::base::unique_fd fd(
400 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
401 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700402 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100403 break;
404 }
405
406 struct stat st = {};
407 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700408 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100409 continue;
410 }
411
Narayan Kamath3f31b632018-02-22 19:42:36 +0000412 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100413 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100414 continue;
415 }
416
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700417 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700418 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800419 if (!dump_data.empty()) {
420 std::sort(dump_data.begin(), dump_data.end(),
421 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
422 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100423
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700424 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100425}
426
Narayan Kamathbd863722017-06-01 18:50:12 +0100427static bool AddDumps(const std::vector<DumpData>::const_iterator start,
428 const std::vector<DumpData>::const_iterator end,
429 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100430 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100431 for (auto it = start; it != end; ++it) {
432 const std::string& name = it->name;
433 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100434 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100435
436 // Seek to the beginning of the file before dumping any data. A given
437 // DumpData entry might be dumped multiple times in the report.
438 //
439 // For example, the most recent ANR entry is dumped to the body of the
440 // main entry and it also shows up as a separate entry in the bugreport
441 // ZIP file.
442 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
443 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
444 strerror(errno));
445 }
446
Narayan Kamath8f788292017-05-25 13:20:39 +0100447 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800448 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100449 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100450 }
451 } else {
452 dump_file_from_fd(type_name, name.c_str(), fd);
453 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100454 }
455
456 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700457}
458
Felipe Leme635ca312016-01-05 14:23:02 -0800459// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700460void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800461 char path[PATH_MAX];
462
463 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
464 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700465 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800466 char linkname[PATH_MAX];
467 ssize_t r = readlink(path, linkname, PATH_MAX);
468 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800469 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800470 return;
471 }
472 linkname[r] = '\0';
473
474 if (mount_points.find(linkname) == mount_points.end()) {
475 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700476 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700477 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800478 mount_points.insert(linkname);
479 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800480 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800481 }
482 }
483}
484
485void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700486 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700487 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800488 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800489 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700490 for_each_pid(do_mountinfo, nullptr);
491 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800492}
493
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700494static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
495{
496 DIR *d;
497 struct dirent *de;
498 char path[PATH_MAX];
499
500 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700501 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700502 return;
503 }
504
505 while ((de = readdir(d))) {
506 if (de->d_type != DT_LNK) {
507 continue;
508 }
509 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700510 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700511 }
512
513 closedir(d);
514}
515
Mark Salyzyn326842f2015-04-30 09:49:41 -0700516static bool skip_not_stat(const char *path) {
517 static const char stat[] = "/stat";
518 size_t len = strlen(path);
519 if (path[len - 1] == '/') { /* Directory? */
520 return false;
521 }
522 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
523}
524
Felipe Leme4c2d6632016-09-28 14:32:00 -0700525static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800526 return false;
527}
528
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700529unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700530
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800531//
532// stat offsets
533// Name units description
534// ---- ----- -----------
535// read I/Os requests number of read I/Os processed
536#define __STAT_READ_IOS 0
537// read merges requests number of read I/Os merged with in-queue I/O
538#define __STAT_READ_MERGES 1
539// read sectors sectors number of sectors read
540#define __STAT_READ_SECTORS 2
541// read ticks milliseconds total wait time for read requests
542#define __STAT_READ_TICKS 3
543// write I/Os requests number of write I/Os processed
544#define __STAT_WRITE_IOS 4
545// write merges requests number of write I/Os merged with in-queue I/O
546#define __STAT_WRITE_MERGES 5
547// write sectors sectors number of sectors written
548#define __STAT_WRITE_SECTORS 6
549// write ticks milliseconds total wait time for write requests
550#define __STAT_WRITE_TICKS 7
551// in_flight requests number of I/Os currently in flight
552#define __STAT_IN_FLIGHT 8
553// io_ticks milliseconds total time this block device has been active
554#define __STAT_IO_TICKS 9
555// time_in_queue milliseconds total wait time for all requests
556#define __STAT_IN_QUEUE 10
557#define __STAT_NUMBER_FIELD 11
558//
559// read I/Os, write I/Os
560// =====================
561//
562// These values increment when an I/O request completes.
563//
564// read merges, write merges
565// =========================
566//
567// These values increment when an I/O request is merged with an
568// already-queued I/O request.
569//
570// read sectors, write sectors
571// ===========================
572//
573// These values count the number of sectors read from or written to this
574// block device. The "sectors" in question are the standard UNIX 512-byte
575// sectors, not any device- or filesystem-specific block size. The
576// counters are incremented when the I/O completes.
577#define SECTOR_SIZE 512
578//
579// read ticks, write ticks
580// =======================
581//
582// These values count the number of milliseconds that I/O requests have
583// waited on this block device. If there are multiple I/O requests waiting,
584// these values will increase at a rate greater than 1000/second; for
585// example, if 60 read requests wait for an average of 30 ms, the read_ticks
586// field will increase by 60*30 = 1800.
587//
588// in_flight
589// =========
590//
591// This value counts the number of I/O requests that have been issued to
592// the device driver but have not yet completed. It does not include I/O
593// requests that are in the queue but not yet issued to the device driver.
594//
595// io_ticks
596// ========
597//
598// This value counts the number of milliseconds during which the device has
599// had I/O requests queued.
600//
601// time_in_queue
602// =============
603//
604// This value counts the number of milliseconds that I/O requests have waited
605// on this block device. If there are multiple I/O requests waiting, this
606// value will increase as the product of the number of milliseconds times the
607// number of requests waiting (see "read ticks" above for an example).
608#define S_TO_MS 1000
609//
610
Mark Salyzyn326842f2015-04-30 09:49:41 -0700611static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800612 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700613 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700614 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700615 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700616 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700617 getline(&buffer, &i, fp);
618 fclose(fp);
619 if (!buffer) {
620 return -errno;
621 }
622 i = strlen(buffer);
623 while ((i > 0) && (buffer[i - 1] == '\n')) {
624 buffer[--i] = '\0';
625 }
626 if (!*buffer) {
627 free(buffer);
628 return 0;
629 }
630 z = true;
631 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800632 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 if (fields[i] != 0) {
634 z = false;
635 }
636 }
637 if (z) { /* never accessed */
638 free(buffer);
639 return 0;
640 }
641
Wei Wang509bb5d2017-06-09 14:42:12 -0700642 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
643 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700644 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700645
646 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
647 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
648 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700649 free(buffer);
650
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800651 if (fields[__STAT_IO_TICKS]) {
652 unsigned long read_perf = 0;
653 unsigned long read_ios = 0;
654 if (fields[__STAT_READ_TICKS]) {
655 unsigned long long divisor = fields[__STAT_READ_TICKS]
656 * fields[__STAT_IO_TICKS];
657 read_perf = ((unsigned long long)SECTOR_SIZE
658 * fields[__STAT_READ_SECTORS]
659 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
660 / divisor;
661 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
662 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
663 / divisor;
664 }
665
666 unsigned long write_perf = 0;
667 unsigned long write_ios = 0;
668 if (fields[__STAT_WRITE_TICKS]) {
669 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
670 * fields[__STAT_IO_TICKS];
671 write_perf = ((unsigned long long)SECTOR_SIZE
672 * fields[__STAT_WRITE_SECTORS]
673 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
674 / divisor;
675 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
676 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
677 / divisor;
678 }
679
680 unsigned queue = (fields[__STAT_IN_QUEUE]
681 + (fields[__STAT_IO_TICKS] >> 1))
682 / fields[__STAT_IO_TICKS];
683
684 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700685 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 -0800686 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700687 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 -0800688 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800689 }
690
691 /* bugreport timeout factor adjustment */
692 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
693 worst_write_perf = write_perf;
694 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700695 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700696 return 0;
697}
698
Yao Chenbe3bbc12018-01-17 16:31:10 -0800699static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
700
Tom Cherryf4472f32020-08-05 09:31:17 -0700701// Returns the actual readable size of the given buffer or -1 on error.
702static long logcat_buffer_readable_size(const std::string& buffer) {
703 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
704 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
705 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
706
707 return android_logger_get_log_readable_size(logger);
708}
709
710// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800711static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
712 unsigned long timeout_ms = 0;
713 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700714 long readable_size = logcat_buffer_readable_size(buffer);
715 if (readable_size > 0) {
716 // Engineering margin is ten-fold our guess.
717 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
718 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800719 }
720 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700721}
722
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800723// Opens a socket and returns its file descriptor.
724static int open_socket(const char* service);
725
Nandana Duttd2f5f082019-01-18 17:13:52 +0000726Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
727}
728
729android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
730 std::lock_guard<std::mutex> lock(lock_);
731 result_ = APPROVED;
732 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800733
734 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
735 // consent is granted.
736 if (ds.options_->is_screenshot_copied) {
737 return android::binder::Status::ok();
738 }
739
740 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
741 !ds.do_early_screenshot_) {
742 return android::binder::Status::ok();
743 }
744
745 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
746 ds.options_->screenshot_fd.get());
747 ds.options_->is_screenshot_copied = copy_succeeded;
748 if (copy_succeeded) {
749 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
750 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000751 return android::binder::Status::ok();
752}
753
754android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
755 std::lock_guard<std::mutex> lock(lock_);
756 result_ = DENIED;
757 MYLOGW("User denied consent to share bugreport\n");
758 return android::binder::Status::ok();
759}
760
761UserConsentResult Dumpstate::ConsentCallback::getResult() {
762 std::lock_guard<std::mutex> lock(lock_);
763 return result_;
764}
765
766uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800767 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000768}
769
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700770void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700771 std::string build, fingerprint, radio, bootloader, network;
772 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700773
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700774 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
775 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700776 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
777 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
778 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700779 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700780
Felipe Lemed8b94e52016-12-08 10:21:44 -0800781 printf("========================================================\n");
782 printf("== dumpstate: %s\n", date);
783 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700784
Felipe Lemed8b94e52016-12-08 10:21:44 -0800785 printf("\n");
786 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700787 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800788 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
789 printf("Bootloader: %s\n", bootloader.c_str());
790 printf("Radio: %s\n", radio.c_str());
791 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100792 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
793 if (module_metadata_version != 0) {
794 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
795 }
Anton Hansson37c041d2021-04-14 17:49:06 +0100796 printf("SDK extension versions [r=%s s=%s]\n",
797 android::base::GetProperty("build.version.extensions.r", "-").c_str(),
798 android::base::GetProperty("build.version.extensions.s", "-").c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700799
Felipe Lemed8b94e52016-12-08 10:21:44 -0800800 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800801 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800802 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800803 printf("Uptime: ");
804 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
805 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800806 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao1c855122020-07-16 17:37:39 +0800807 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
808 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
809 options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800810 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800811}
812
Felipe Leme24b66ee2016-06-16 10:55:26 -0700813// List of file extensions that can cause a zip file attachment to be rejected by some email
814// service providers.
815static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
816 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
817 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
818 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
819};
820
Vishnu Naire97d6122018-01-18 13:58:56 -0800821status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
822 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700823 if (!IsZipping()) {
824 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
825 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800826 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800827 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700828 std::string valid_name = entry_name;
829
830 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700831 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700832 if (idx != std::string::npos) {
833 std::string extension = entry_name.substr(idx);
834 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
835 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
836 valid_name = entry_name + ".renamed";
837 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
838 }
839 }
840
Felipe Leme6fe9db62016-02-12 09:04:16 -0800841 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
842 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700843 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
844 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700845 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700846 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700847 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800848 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800849 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000850 bool finished_entry = false;
851 auto finish_entry = [this, &finished_entry] {
852 if (!finished_entry) {
853 // This should only be called when we're going to return an earlier error,
854 // which would've been logged. This may imply the file is already corrupt
855 // and any further logging from FinishEntry is more likely to mislead than
856 // not.
857 this->zip_writer_->FinishEntry();
858 }
859 };
860 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800861 auto start = std::chrono::steady_clock::now();
862 auto end = start + timeout;
863 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800864
Felipe Leme770410d2016-01-26 17:07:14 -0800865 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800866 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 if (timeout.count() > 0) {
868 // lambda to recalculate the timeout.
869 auto time_left_ms = [end]() {
870 auto now = std::chrono::steady_clock::now();
871 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
872 return std::max(diff.count(), 0LL);
873 };
874
875 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
876 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000877 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
878 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800879 return -errno;
880 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000881 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800882 entry_name.c_str(), strerror(errno), timeout.count());
883 return TIMED_OUT;
884 }
885 }
886
Zach Riggle22200402016-08-18 01:01:24 -0400887 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800888 if (bytes_read == 0) {
889 break;
890 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800891 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800892 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800893 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700894 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800895 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700896 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800897 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800898 }
899 }
900
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700901 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000902 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700903 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700904 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800905 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800906 }
907
Vishnu Naire97d6122018-01-18 13:58:56 -0800908 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800909}
910
Felipe Leme1d486fe2016-10-14 18:06:47 -0700911bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
912 android::base::unique_fd fd(
913 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700914 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800915 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800916 return false;
917 }
918
Vishnu Naire97d6122018-01-18 13:58:56 -0800919 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800920}
921
922/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700923static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800924 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800925}
926
Felipe Leme1d486fe2016-10-14 18:06:47 -0700927void Dumpstate::AddDir(const std::string& dir, bool recursive) {
928 if (!IsZipping()) {
929 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800930 return;
931 }
Felipe Leme678727a2016-09-21 17:22:11 -0700932 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800933 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700934 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800935}
936
Felipe Leme1d486fe2016-10-14 18:06:47 -0700937bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
938 if (!IsZipping()) {
939 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
940 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800941 return false;
942 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800943 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700944 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700945 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700946 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700947 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800948 return false;
949 }
950
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700951 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700952 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700953 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800955 return false;
956 }
957
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700958 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700959 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700960 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800961 return false;
962 }
963
964 return true;
965}
966
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800967static void DoKmsg() {
968 struct stat st;
969 if (!stat(PSTORE_LAST_KMSG, &st)) {
970 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
971 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
972 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
973 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
974 } else {
975 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
976 DumpFile("LAST KMSG", "/proc/last_kmsg");
977 }
978}
979
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800980static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800981 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800982 RunCommand(
983 "KERNEL LOG",
984 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
985 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
986}
987
Nandana Duttdb379fa2019-10-09 16:54:41 +0100988static void DoSystemLogcat(time_t since) {
989 char since_str[80];
990 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
991
992 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
993 RunCommand("SYSTEM LOG",
994 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
995 since_str},
996 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
997}
998
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800999static void DoRadioLogcat() {
1000 unsigned long timeout_ms = logcat_timeout({"radio"});
1001 RunCommand(
1002 "RADIO LOG",
1003 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1004 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1005}
1006
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001007static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001008 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001009 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1010 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001011 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001012 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001013 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1014 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001015 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001016 RunCommand(
1017 "EVENT LOG",
1018 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001019 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001020 timeout_ms = logcat_timeout({"stats"});
1021 RunCommand(
1022 "STATS LOG",
1023 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001024 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001025 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001026
1027 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1028
1029 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001030 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1031 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001032}
1033
Mike Ma5c267872019-08-21 11:31:34 -07001034static void DumpIncidentReport() {
1035 if (!ds.IsZipping()) {
1036 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1037 return;
1038 }
Mike Ma5c267872019-08-21 11:31:34 -07001039 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1040 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1041 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1042 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1043 if (fd < 0) {
1044 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1045 return;
1046 }
1047 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1048 bool empty = 0 == lseek(fd, 0, SEEK_END);
1049 if (!empty) {
1050 // Use a different name from "incident.proto"
1051 // /proto/incident.proto is reserved for incident service dump
1052 // i.e. metadata for debugging.
Rhed Jao4875aa62020-07-20 17:46:29 +08001053 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1054 path);
1055 } else {
1056 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001057 }
Mike Ma5c267872019-08-21 11:31:34 -07001058}
1059
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001060static void MaybeAddSystemTraceToZip() {
1061 // This function copies into the .zip the system trace that was snapshotted
1062 // by the early call to MaybeSnapshotSystemTrace(), if any background
1063 // tracing was happening.
1064 if (!ds.IsZipping()) {
1065 MYLOGD("Not dumping system trace because it's not a zipped bugreport\n");
1066 return;
1067 }
1068 if (!ds.has_system_trace_) {
1069 // No background trace was happening at the time dumpstate was invoked.
1070 return;
1071 }
1072 ds.AddZipEntry(
1073 ZIP_ROOT_DIR + SYSTEM_TRACE_SNAPSHOT,
1074 SYSTEM_TRACE_SNAPSHOT);
1075 android::os::UnlinkAndLogOnError(SYSTEM_TRACE_SNAPSHOT);
1076}
1077
Sunny Goyal35949782019-11-19 15:54:36 -08001078static void DumpVisibleWindowViews() {
1079 if (!ds.IsZipping()) {
1080 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1081 return;
1082 }
1083 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1084 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1085 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1086 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1087 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1088 if (fd < 0) {
1089 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1090 return;
1091 }
1092 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1093 CommandOptions::WithTimeout(120).Build());
1094 bool empty = 0 == lseek(fd, 0, SEEK_END);
1095 if (!empty) {
1096 ds.AddZipEntry("visible_windows.zip", path);
1097 } else {
1098 MYLOGW("Failed to dump visible windows\n");
1099 }
1100 unlink(path.c_str());
1101}
1102
Jayachandran Ca94c7172017-06-10 15:08:12 -07001103static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001104 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1105 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001106 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001107 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001108 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1109 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1110 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1111 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001112}
1113
David Andersond9ba4752018-12-11 18:26:59 -08001114static void DumpDynamicPartitionInfo() {
1115 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1116 return;
1117 }
1118
1119 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001120 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001121}
1122
Narayan Kamath8f788292017-05-25 13:20:39 +01001123static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1124 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1125 anr_traces_dir.c_str());
1126
1127 // If we're here, dump_traces_path will always be a temporary file
1128 // (created with mkostemp or similar) that contains dumps taken earlier
1129 // on in the process.
1130 if (dump_traces_path != nullptr) {
1131 if (add_to_zip) {
1132 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1133 } else {
1134 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1135 dump_traces_path);
1136 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1137 }
1138
1139 const int ret = unlink(dump_traces_path);
1140 if (ret == -1) {
1141 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1142 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001143 }
1144 }
1145
Narayan Kamathbd863722017-06-01 18:50:12 +01001146 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001147 if (ds.anr_data_.size() > 0) {
1148 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001149 "VM TRACES AT LAST ANR", add_to_zip);
1150
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001151 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1152 // it will be present in the body of the main entry if |add_to_zip| == false.
1153 //
1154 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001155 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001156 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001157 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001158 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1159 }
1160}
1161
1162static void AddAnrTraceFiles() {
1163 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1164
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001165 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001166
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001167 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001168
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001169 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1170
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001171 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001172 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001173 int i = 0;
1174 while (true) {
1175 const std::string slow_trace_path =
1176 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1177 if (stat(slow_trace_path.c_str(), &st)) {
1178 // No traces file at this index, done with the files.
1179 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001180 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001181 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1182 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001183 }
1184}
1185
Wei Wang509bb5d2017-06-09 14:42:12 -07001186static void DumpBlockStatFiles() {
1187 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001188
Wei Wang1dc1ef52017-06-12 11:28:37 -07001189 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1190
1191 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001192 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1193 return;
1194 }
1195
1196 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001197 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001198 if ((d->d_name[0] == '.')
1199 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1200 || (d->d_name[1] == '\0'))) {
1201 continue;
1202 }
1203 const std::string new_path =
1204 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1205 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1206 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1207 printf("\n");
1208 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001209 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001210}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001211
1212static void DumpPacketStats() {
1213 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001214}
1215
1216static void DumpIpAddrAndRules() {
1217 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1218 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1219 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1220 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1221 RunCommand("IP RULES", {"ip", "rule", "show"});
1222 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1223}
1224
Nandana Dutt5c390032019-03-12 10:52:56 +00001225static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1226 std::chrono::milliseconds timeout,
1227 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001228 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001229 sp<android::IServiceManager> sm = defaultServiceManager();
1230 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001231 Vector<String16> args;
1232 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001233 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1234 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001235 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001236 std::string path(title);
1237 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001238 size_t bytes_written = 0;
Steven Moreland5a30d342019-10-08 13:53:28 -07001239 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001240 if (status == OK) {
1241 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1242 std::chrono::duration<double> elapsed_seconds;
Gavin Corkeryfac7e2b2021-07-08 22:39:02 +01001243 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
1244 service == String16("meminfo")) {
1245 // Use a longer timeout for meminfo, since 30s is not always enough.
1246 status = dumpsys.writeDump(STDOUT_FILENO, service, 60s,
1247 /* as_proto = */ false, elapsed_seconds, bytes_written);
1248 } else {
1249 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1250 /* as_proto = */ false, elapsed_seconds, bytes_written);
1251 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001252 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1253 bool dump_complete = (status == OK);
1254 dumpsys.stopDumpThread(dump_complete);
1255 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001256
1257 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1258 std::chrono::steady_clock::now() - start);
1259 if (elapsed_duration > timeout) {
1260 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1261 elapsed_duration.count());
1262 break;
1263 }
1264 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001265 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001266}
1267
Vishnu Nair64afc022018-02-01 15:29:34 -08001268static void RunDumpsysText(const std::string& title, int priority,
1269 std::chrono::milliseconds timeout,
1270 std::chrono::milliseconds service_timeout) {
1271 DurationReporter duration_reporter(title);
1272 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1273 fsync(STDOUT_FILENO);
1274 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1275}
1276
1277/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001278static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1279 std::chrono::milliseconds timeout,
1280 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001281 DurationReporter duration_reporter(title);
1282 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1283 fsync(STDOUT_FILENO);
1284 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1285 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001286
1287 RETURN_IF_USER_DENIED_CONSENT();
1288
1289 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1290 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001291}
1292
Nandana Dutt5c390032019-03-12 10:52:56 +00001293static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1294 std::chrono::milliseconds timeout,
1295 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001296 if (!ds.IsZipping()) {
1297 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001298 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001299 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001300 sp<android::IServiceManager> sm = defaultServiceManager();
1301 Dumpsys dumpsys(sm.get());
1302 Vector<String16> args;
1303 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1304 DurationReporter duration_reporter(title);
1305
1306 auto start = std::chrono::steady_clock::now();
1307 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1308 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001309 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001310 std::string path(kProtoPath);
1311 path.append(String8(service).c_str());
1312 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1313 path.append("_CRITICAL");
1314 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1315 path.append("_HIGH");
1316 }
1317 path.append(kProtoExt);
Steven Moreland5a30d342019-10-08 13:53:28 -07001318 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001319 if (status == OK) {
1320 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1321 bool dumpTerminated = (status == OK);
1322 dumpsys.stopDumpThread(dumpTerminated);
1323 }
1324 ZipWriter::FileEntry file_entry;
1325 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001326
1327 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1328 std::chrono::steady_clock::now() - start);
1329 if (elapsed_duration > timeout) {
1330 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1331 elapsed_duration.count());
1332 break;
1333 }
1334 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001335 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001336}
1337
Nandana Dutta7db6342018-11-21 14:53:34 +00001338// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001339static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001340 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1341 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001342
1343 RETURN_IF_USER_DENIED_CONSENT();
1344
1345 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1346 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001347}
1348
1349// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001350static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001351 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1352 // high priority. Reduce timeout once they are able to dump in a shorter time or
1353 // moved to a parallel task.
1354 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1355 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001356
1357 RETURN_IF_USER_DENIED_CONSENT();
1358
1359 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1360 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001361}
1362
1363// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001364static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001365 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001366
1367 RETURN_IF_USER_DENIED_CONSENT();
1368
1369 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1370 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001371}
1372
Rhed Jao4875aa62020-07-20 17:46:29 +08001373/*
1374 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1375 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1376 * if it's not running in the parallel task.
1377 */
1378static void DumpHals(int out_fd = STDOUT_FILENO) {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001379 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001380 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Steven Moreland9de8a1f2020-09-23 17:26:33 +00001381 CommandOptions::WithTimeout(60).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001382 return;
1383 }
Yifan Hong30528a22020-08-07 18:24:06 -07001384 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao4875aa62020-07-20 17:46:29 +08001385 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1386 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001387
Steven Moreland44cd9482018-01-04 16:24:13 -08001388 using android::hidl::manager::V1_0::IServiceManager;
1389 using android::hardware::defaultServiceManager;
1390
1391 sp<IServiceManager> sm = defaultServiceManager();
1392 if (sm == nullptr) {
1393 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1394 return;
1395 }
1396
1397 auto ret = sm->list([&](const auto& interfaces) {
1398 for (const std::string& interface : interfaces) {
1399 std::string cleanName = interface;
1400 std::replace_if(cleanName.begin(),
1401 cleanName.end(),
1402 [](char c) {
1403 return !isalnum(c) &&
1404 std::string("@-_:.").find(c) == std::string::npos;
1405 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001406 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001407
Rhed Jao4875aa62020-07-20 17:46:29 +08001408 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001409 {
1410 auto fd = android::base::unique_fd(
1411 TEMP_FAILURE_RETRY(open(path.c_str(),
1412 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1413 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1414 if (fd < 0) {
1415 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1416 continue;
1417 }
1418 RunCommandToFd(fd,
1419 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001420 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001421 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1422
Rhed Jao4875aa62020-07-20 17:46:29 +08001423 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001424 }
Rhed Jao4875aa62020-07-20 17:46:29 +08001425 if (!empty) {
1426 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1427 path);
1428 } else {
1429 unlink(path.c_str());
1430 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001431 }
1432 });
1433
1434 if (!ret.isOk()) {
1435 MYLOGE("Could not list hals from hwservicemanager.\n");
1436 }
1437}
1438
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001439static void DumpExternalFragmentationInfo() {
1440 struct stat st;
1441 if (stat("/proc/buddyinfo", &st) != 0) {
1442 MYLOGE("Unable to dump external fragmentation info\n");
1443 return;
1444 }
1445
1446 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1447 std::ifstream ifs("/proc/buddyinfo");
1448 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1449 for (std::string line; std::getline(ifs, line);) {
1450 std::smatch match_results;
1451 if (std::regex_match(line, match_results, unusable_index_regex)) {
1452 std::stringstream free_pages(std::string{match_results[3]});
1453 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1454 std::istream_iterator<int>());
1455
1456 int total_free_pages = 0;
1457 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1458 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1459 }
1460
1461 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1462 match_results[2].str().c_str());
1463
1464 int usable_free_pages = total_free_pages;
1465 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1466 auto unusable_index = (total_free_pages - usable_free_pages) /
1467 static_cast<double>(total_free_pages);
1468 printf(" %5.3f", unusable_index);
1469 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1470 }
1471
1472 printf("\n");
1473 }
1474 }
1475 printf("\n");
1476}
1477
mhasankd451a472020-05-26 18:02:39 -07001478static void DumpstateLimitedOnly() {
1479 // Trimmed-down version of dumpstate to only include a whitelisted
1480 // set of logs (system log, event log, and system server / system app
1481 // crashes, and networking logs). See b/136273873 and b/138459828
1482 // for context.
1483 DurationReporter duration_reporter("DUMPSTATE");
1484 unsigned long timeout_ms;
1485 // calculate timeout
1486 timeout_ms = logcat_timeout({"main", "system", "crash"});
1487 RunCommand("SYSTEM LOG",
1488 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1489 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1490 timeout_ms = logcat_timeout({"events"});
1491 RunCommand(
1492 "EVENT LOG",
1493 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1494 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1495
1496 printf("========================================================\n");
1497 printf("== Networking Service\n");
1498 printf("========================================================\n");
1499
1500 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1501 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001502 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1503 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001504
1505 printf("========================================================\n");
1506 printf("== Dropbox crashes\n");
1507 printf("========================================================\n");
1508
1509 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1510 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1511
1512 printf("========================================================\n");
1513 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1514 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1515 printf("========================================================\n");
1516 printf("== dumpstate: done (id %d)\n", ds.id_);
1517 printf("========================================================\n");
1518}
1519
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001520/*
1521 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1522 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1523 * if it's not running in the parallel task.
1524 */
1525static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1526 dprintf(out_fd, "========================================================\n");
1527 dprintf(out_fd, "== Checkins\n");
1528 dprintf(out_fd, "========================================================\n");
1529
1530 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1531 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1532 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1533 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1534 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1535 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1536}
1537
1538/*
1539 * Runs dumpsys on activity service to dump all application activities, services
1540 * and providers in the device.
1541 *
1542 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1543 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1544 * if it's not running in the parallel task.
1545 */
1546static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1547 dprintf(out_fd, "========================================================\n");
1548 dprintf(out_fd, "== Running Application Activities\n");
1549 dprintf(out_fd, "========================================================\n");
1550
1551 // The following dumpsys internally collects output from running apps, so it can take a long
1552 // time. So let's extend the timeout.
1553
1554 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1555
1556 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1557
1558 dprintf(out_fd, "========================================================\n");
1559 dprintf(out_fd, "== Running Application Services (platform)\n");
1560 dprintf(out_fd, "========================================================\n");
1561
1562 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1563 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1564
1565 dprintf(out_fd, "========================================================\n");
1566 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1567 dprintf(out_fd, "========================================================\n");
1568
1569 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1570 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1571
1572 dprintf(out_fd, "========================================================\n");
1573 dprintf(out_fd, "== Running Application Providers (platform)\n");
1574 dprintf(out_fd, "========================================================\n");
1575
1576 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
Rhed Jaob049f182021-01-11 21:08:43 +08001577 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001578
1579 dprintf(out_fd, "========================================================\n");
1580 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1581 dprintf(out_fd, "========================================================\n");
1582
1583 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1584 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1585}
1586
Nandana Dutt5c390032019-03-12 10:52:56 +00001587// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1588// via the consent they are shown. Ignores other errors that occur while running various
1589// commands. The consent checking is currently done around long running tasks, which happen to
1590// be distributed fairly evenly throughout the function.
1591static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001592 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001593
Rhed Jao4875aa62020-07-20 17:46:29 +08001594 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1595 if (ds.dump_pool_) {
1596 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1597 // drop root user. Restarts it with two threads for the parallel run.
1598 ds.dump_pool_->start(/* thread_counts = */2);
1599
1600 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1601 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1602 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001603 ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao4875aa62020-07-20 17:46:29 +08001604 }
1605
Nandana Dutt5c390032019-03-12 10:52:56 +00001606 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1607 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1608 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001609 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001610 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001611 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001612 DumpFile("MEMORY INFO", "/proc/meminfo");
1613 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001614 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001615
1616 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1617
Sunny Goyal35949782019-11-19 15:54:36 -08001618 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1619
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001620 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1621 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1622 DumpFile("SLAB INFO", "/proc/slabinfo");
1623 DumpFile("ZONEINFO", "/proc/zoneinfo");
1624 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1625 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001626 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001627
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001628 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1629 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001630
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001631 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001632 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001633
1634 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1635 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001636
Rhed Jao4875aa62020-07-20 17:46:29 +08001637 if (ds.dump_pool_) {
1638 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1639 } else {
1640 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1641 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001642
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001643 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001644 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001645 struct stat s;
1646 if (stat("/proc/modules", &s) != 0) {
1647 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1648 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001649 RunCommand("LSMOD", {"lsmod"});
Woody Linc198f252021-05-04 16:37:11 +08001650 RunCommand("MODULES INFO",
1651 {"sh", "-c", "cat /proc/modules | cut -d' ' -f1 | "
1652 " while read MOD ; do echo modinfo:$MOD ; modinfo $MOD ; "
1653 "done"}, CommandOptions::AS_ROOT);
Felipe Lemee4eca582016-06-10 17:48:08 -07001654 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001655
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001656 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001657 DoKernelLogcat();
1658 } else {
1659 do_dmesg();
1660 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001661
Felipe Lemef0292972016-11-22 13:57:05 -08001662 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001663
1664 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1665
Jeff Brown1dc94e32014-09-11 14:15:27 -07001666 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001667 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001668
Jack Yu5a6b2e22020-08-14 18:13:35 +08001669 /* Dump Nfc NCI logs */
1670 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001671
Paul Chang0d2aad72020-02-13 20:04:03 +08001672 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001673 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001674 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001675 }
1676
Felipe Lemee184f662016-10-27 10:04:47 -07001677 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001678
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00001679 MaybeAddSystemTraceToZip();
1680
Narayan Kamath8f788292017-05-25 13:20:39 +01001681 // NOTE: tombstones are always added as separate entries in the zip archive
1682 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001683 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001684 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001685 if (!tombstones_dumped) {
1686 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001687 }
1688
Jayachandran Ca94c7172017-06-10 15:08:12 -07001689 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001690
Chenbo Feng276a3b62018-08-07 11:44:49 -07001691 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1692
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001693 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001694
Jayachandran Ca94c7172017-06-10 15:08:12 -07001695 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001696
1697 dump_route_tables();
1698
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001699 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1700 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1701 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001702
Nandana Dutt5c390032019-03-12 10:52:56 +00001703 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001704
Chiachang Wang7bafd702021-05-17 17:14:20 +08001705 // The dump mechanism in connectivity is refactored due to modularization work. Connectivity can
1706 // only register with a default priority(NORMAL priority). Dumpstate has to call connectivity
1707 // dump with priority parameters to dump high priority information.
1708 RunDumpsys("SERVICE HIGH connectivity", {"connectivity", "--dump-priority", "HIGH"},
1709 CommandOptions::WithTimeout(10).Build());
1710
Elliott Hughes23ccc622017-02-28 10:14:22 -08001711 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001712
Jin Qianf334d662017-10-10 14:41:37 -07001713 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001714
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001715 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001716
Colin Crossf45fa6b2012-03-26 12:38:26 -07001717 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001718 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1719 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1720
1721 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1722 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1723 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1724 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1725 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001726
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001727 /* Add window and surface trace files. */
1728 if (!PropertiesHelper::IsUserBuild()) {
1729 ds.AddDir(WMTRACE_DATA_DIR, false);
1730 }
1731
Yifan Hongcba0a4f2020-02-08 16:52:02 -08001732 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1733
Rhed Jao4875aa62020-07-20 17:46:29 +08001734 if (ds.dump_pool_) {
1735 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1736 } else {
1737 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1738 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001739
Steven Moreland7440ddb2016-12-15 16:13:39 -08001740 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001741 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1742 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001743 // su does not exist on user builds, so try running without it.
1744 // This way any implementations of vril-dump that do not require
1745 // root can run on user builds.
1746 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001747 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001748 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001749 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001750 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001751 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001752 }
1753
Felipe Lemed8b94e52016-12-08 10:21:44 -08001754 printf("========================================================\n");
1755 printf("== Android Framework Services\n");
1756 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001757
Nandana Dutt5c390032019-03-12 10:52:56 +00001758 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759
Jack He91ff2fe2021-02-18 18:23:43 -08001760 /* Dump Bluetooth HCI logs after getting bluetooth_manager dumpsys */
1761 ds.AddDir("/data/misc/bluetooth/logs", true);
1762
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001763 if (ds.dump_pool_) {
1764 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
1765 } else {
1766 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1767 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001768
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001769 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001770
Adrian Roos8b397ab2017-04-04 16:35:44 -07001771 printf("========================================================\n");
1772 printf("== Dropbox crashes\n");
1773 printf("========================================================\n");
1774
1775 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1776 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1777
Felipe Lemed8b94e52016-12-08 10:21:44 -08001778 printf("========================================================\n");
1779 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1780 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1781 printf("========================================================\n");
1782 printf("== dumpstate: done (id %d)\n", ds.id_);
1783 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001784
1785 printf("========================================================\n");
1786 printf("== Obtaining statsd metadata\n");
1787 printf("========================================================\n");
1788 // This differs from the usual dumpsys stats, which is the stats report data.
1789 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001790
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001791 // Add linker configuration directory
1792 ds.AddDir(LINKERCONFIG_DIR, true);
1793
Rhed Jao4875aa62020-07-20 17:46:29 +08001794 if (ds.dump_pool_) {
1795 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1796 } else {
1797 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1798 DumpIncidentReport);
1799 }
Mike Ma5c267872019-08-21 11:31:34 -07001800
Nandana Dutt5c390032019-03-12 10:52:56 +00001801 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802}
1803
Nandana Dutt5c390032019-03-12 10:52:56 +00001804/*
1805 * Dumps state for the default case; drops root after it's no longer necessary.
1806 *
1807 * Returns RunStatus::OK if everything went fine.
1808 * Returns RunStatus::ERROR if there was an error.
1809 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1810 * with the caller.
1811 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001812Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001813 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1814 // buffer.
1815 DoLogcat();
1816 // Capture timestamp after first logcat to use in next logcat
1817 time_t logcat_ts = time(nullptr);
1818
Nandana Dutt4be45d12018-09-26 15:04:23 +01001819 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao1c855122020-07-16 17:37:39 +08001820 if (dump_pool_) {
1821 RETURN_IF_USER_DENIED_CONSENT();
1822 // One thread is enough since we only need to enqueue DumpTraces here.
1823 dump_pool_->start(/* thread_counts = */1);
1824
1825 // DumpTraces takes long time, post it to the another thread in the
1826 // pool, if pool is available
1827 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1828 } else {
1829 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1830 &dump_traces_path);
1831 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001832
1833 /* Run some operations that require root. */
1834 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1835 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1836
1837 ds.AddDir(RECOVERY_DIR, true);
1838 ds.AddDir(RECOVERY_DATA_DIR, true);
1839 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1840 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1841 if (!PropertiesHelper::IsUserBuild()) {
1842 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1843 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravle78a0d842020-04-28 15:31:12 -07001844 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001845 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001846 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001847 add_mountinfo();
1848 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001849 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001850 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001851
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001852 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001853 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1854
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001855 // Dump IPsec stats. No keys are exposed here.
1856 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1857
Nandana Dutt4be45d12018-09-26 15:04:23 +01001858 // Run ss as root so we can see socket marks.
1859 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1860
1861 // Run iotop as root to show top 100 IO threads
1862 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1863
Erick Reyese68df822019-02-11 14:46:36 -08001864 // Gather shared memory buffer info if the product implements it
Hridya Valsaraju1da80c52021-01-09 22:10:11 -08001865 RunCommand("Dmabuf dump", {"dmabuf_dump"});
1866 RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
Erick Reyese68df822019-02-11 14:46:36 -08001867
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001868 DumpFile("PSI cpu", "/proc/pressure/cpu");
1869 DumpFile("PSI memory", "/proc/pressure/memory");
1870 DumpFile("PSI io", "/proc/pressure/io");
1871
Rhed Jao1c855122020-07-16 17:37:39 +08001872 if (dump_pool_) {
1873 RETURN_IF_USER_DENIED_CONSENT();
1874 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1875
1876 // Current running thread in the pool is the root user also. Shutdown
1877 // the pool and restart later to ensure all threads in the pool could
1878 // drop the root user.
1879 dump_pool_->shutdown();
1880 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001881 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001882 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001883 }
1884
Nandana Dutt5c390032019-03-12 10:52:56 +00001885 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001886 Dumpstate::RunStatus status = dumpstate();
1887 // Capture logcat since the last time we did it.
1888 DoSystemLogcat(logcat_ts);
1889 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001890}
1891
Rhed Jaoa5de5752020-08-14 17:19:17 +08001892// Common states for telephony and wifi which are needed to be collected before
1893// dumpstate drop the root user.
1894static void DumpstateRadioAsRoot() {
1895 DumpIpTablesAsRoot();
1896 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1897}
1898
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001899// This method collects common dumpsys for telephony and wifi. Typically, wifi
1900// reports are fine to include all information, but telephony reports on user
1901// builds need to strip some content (see DumpstateTelephonyOnly).
1902static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001903 // We need to be picky about some stuff for telephony reports on user builds.
1904 if (!include_sensitive_info) {
1905 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1906 DoRadioLogcat();
1907 } else {
Rhed Jaoa5de5752020-08-14 17:19:17 +08001908 // DumpHals takes long time, post it to the another thread in the pool,
1909 // if pool is available.
1910 if (ds.dump_pool_) {
1911 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1912 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001913 // Contains various system properties and process startup info.
1914 do_dmesg();
1915 // Logs other than the radio buffer may contain package/component names and potential PII.
1916 DoLogcat();
1917 // Too broad for connectivity problems.
1918 DoKmsg();
Rhed Jaoa5de5752020-08-14 17:19:17 +08001919 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1920 if (ds.dump_pool_) {
1921 ds.dump_pool_->waitForTask(DUMP_HALS_TASK);
1922 } else {
1923 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1924 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001925 }
1926
Jayachandran Ca94c7172017-06-10 15:08:12 -07001927 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001928 DumpIpAddrAndRules();
1929 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001930 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1931 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001932}
1933
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001934// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1935// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1936// for what can be included on user builds: all reported information MUST directly relate to
1937// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1938// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1939// names are not), and MUST NOT contain logs of user application traffic.
1940// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001941static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001942 DurationReporter duration_reporter("DUMPSTATE");
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001943
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001944 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001945
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001946 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001947
Rhed Jaoa5de5752020-08-14 17:19:17 +08001948 DumpstateRadioAsRoot();
1949 if (!DropRootUser()) {
1950 return;
1951 }
1952
1953 // Starts thread pool after the root user is dropped, and two additional threads
1954 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1955 if (ds.dump_pool_) {
1956 ds.dump_pool_->start(/*thread_counts =*/2);
1957
1958 // DumpstateBoard takes long time, post it to the another thread in the pool,
1959 // if pool is available.
1960 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1961 }
1962
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001963 DumpstateRadioCommon(include_sensitive_info);
1964
1965 if (include_sensitive_info) {
1966 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1967 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1968 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1969 // way.
1970 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1971 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001972
1973 printf("========================================================\n");
1974 printf("== Android Framework Services\n");
1975 printf("========================================================\n");
1976
Vishnu Nair652cc802017-11-30 15:18:30 -08001977 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1978 SEC_TO_MSEC(10));
Hunter Knepshield31cbae12021-05-11 16:23:24 -07001979 RunDumpsys("DUMPSYS", {"vcn_management"}, CommandOptions::WithTimeout(90).Build(),
1980 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001981 if (include_sensitive_info) {
1982 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1983 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1984 SEC_TO_MSEC(10));
1985 } else {
1986 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1987 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1988 // give a higher timeout as well.
1989 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1990 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1991 }
1992 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001993 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1994 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001995 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001996 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1997 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001998 if (include_sensitive_info) {
1999 // Contains raw IP addresses, omit from reports on user builds.
2000 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
2001 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
2002 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
2003 SEC_TO_MSEC(10));
2004 // Contains package/component names, omit from reports on user builds.
2005 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
2006 SEC_TO_MSEC(10));
2007 // Contains package names, but should be relatively simple to remove them (also contains
2008 // UIDs already), omit from reports on user builds.
2009 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
2010 SEC_TO_MSEC(10));
2011 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002012
2013 printf("========================================================\n");
2014 printf("== Running Application Services\n");
2015 printf("========================================================\n");
2016
2017 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
2018
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002019 if (include_sensitive_info) {
2020 printf("========================================================\n");
2021 printf("== Running Application Services (non-platform)\n");
2022 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002023
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002024 // Contains package/component names and potential PII, omit from reports on user builds.
2025 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
2026 // carrier_config dumpsys instead.
2027 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
2028 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07002029
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002030 printf("========================================================\n");
2031 printf("== Checkins\n");
2032 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002033
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002034 // Contains package/component names, omit from reports on user builds.
2035 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
2036 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07002037
2038 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002039 printf("== dumpstate: done (id %d)\n", ds.id_);
2040 printf("========================================================\n");
Rhed Jaoa5de5752020-08-14 17:19:17 +08002041
2042 if (ds.dump_pool_) {
2043 ds.dump_pool_->waitForTask(DUMP_BOARD_TASK);
2044 } else {
2045 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2046 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002047}
2048
mukesh agrawal253dad42018-01-23 21:59:59 -08002049// This method collects dumpsys for wifi debugging only
2050static void DumpstateWifiOnly() {
2051 DurationReporter duration_reporter("DUMPSTATE");
2052
Rhed Jaoa5de5752020-08-14 17:19:17 +08002053 DumpstateRadioAsRoot();
2054 if (!DropRootUser()) {
2055 return;
2056 }
2057
2058 // Starts thread pool after the root user is dropped. Only one additional
2059 // thread is needed for DumpHals in the DumpstateRadioCommon.
2060 if (ds.dump_pool_) {
2061 ds.dump_pool_->start(/*thread_counts =*/1);
2062 }
2063
mukesh agrawal253dad42018-01-23 21:59:59 -08002064 DumpstateRadioCommon();
2065
2066 printf("========================================================\n");
2067 printf("== Android Framework Services\n");
2068 printf("========================================================\n");
2069
2070 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2071 SEC_TO_MSEC(10));
2072 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2073 SEC_TO_MSEC(10));
2074
2075 printf("========================================================\n");
2076 printf("== dumpstate: done (id %d)\n", ds.id_);
2077 printf("========================================================\n");
2078}
2079
Nandana Duttcf419a72019-03-14 10:40:17 +00002080Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Gavin Corkery789d7a52021-02-24 23:52:35 +00002081 const std::string temp_file_pattern = ds.bugreport_internal_dir_ + "/dumptrace_XXXXXX";
Nandana Duttfaafd522019-03-11 09:23:09 +00002082 const size_t buf_size = temp_file_pattern.length() + 1;
2083 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2084 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2085
2086 // Create a new, empty file to receive all trace dumps.
2087 //
2088 // TODO: This can be simplified once we remove support for the old style
2089 // dumps. We can have a file descriptor passed in to dump_traces instead
2090 // of creating a file, closing it and then reopening it again.
2091 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2092 if (fd < 0) {
2093 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002094 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002095 }
2096
2097 // Nobody should have access to this temporary file except dumpstate, but we
2098 // temporarily grant 'read' to 'others' here because this file is created
2099 // when tombstoned is still running as root, but dumped after dropping. This
2100 // can go away once support for old style dumping has.
2101 const int chmod_ret = fchmod(fd, 0666);
2102 if (chmod_ret < 0) {
2103 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002104 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002105 }
2106
2107 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2108 if (proc.get() == nullptr) {
2109 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002110 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002111 }
2112
2113 // Number of times process dumping has timed out. If we encounter too many
2114 // failures, we'll give up.
2115 int timeout_failures = 0;
2116 bool dalvik_found = false;
2117
2118 const std::set<int> hal_pids = get_interesting_hal_pids();
2119
2120 struct dirent* d;
2121 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002122 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002123 int pid = atoi(d->d_name);
2124 if (pid <= 0) {
2125 continue;
2126 }
2127
2128 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2129 std::string exe;
2130 if (!android::base::Readlink(link_name, &exe)) {
2131 continue;
2132 }
2133
2134 bool is_java_process;
2135 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2136 // Don't bother dumping backtraces for the zygote.
2137 if (IsZygote(pid)) {
2138 continue;
2139 }
2140
2141 dalvik_found = true;
2142 is_java_process = true;
2143 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2144 is_java_process = false;
2145 } else {
2146 // Probably a native process we don't care about, continue.
2147 continue;
2148 }
2149
2150 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2151 if (timeout_failures == 3) {
2152 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2153 break;
2154 }
2155
2156 const uint64_t start = Nanotime();
2157 const int ret = dump_backtrace_to_file_timeout(
2158 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2159 is_java_process ? 5 : 20, fd);
2160
2161 if (ret == -1) {
2162 // For consistency, the header and footer to this message match those
2163 // dumped by debuggerd in the success case.
2164 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2165 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2166 dprintf(fd, "---- end %d ----", pid);
2167 timeout_failures++;
2168 continue;
2169 }
2170
2171 // We've successfully dumped stack traces, reset the failure count
2172 // and write a summary of the elapsed time to the file and continue with the
2173 // next process.
2174 timeout_failures = 0;
2175
2176 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2177 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2178 }
2179
2180 if (!dalvik_found) {
2181 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2182 }
2183
Nandana Duttcf419a72019-03-14 10:40:17 +00002184 *path = file_name_buf.release();
2185 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002186}
2187
Rhed Jao4875aa62020-07-20 17:46:29 +08002188void Dumpstate::DumpstateBoard(int out_fd) {
2189 dprintf(out_fd, "========================================================\n");
2190 dprintf(out_fd, "== Board\n");
2191 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002192
Felipe Leme6f674ae2016-11-18 17:10:33 -08002193 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002194 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002195 return;
2196 }
2197
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002198 /*
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002199 * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
Hridya Valsaraju51101602021-04-02 14:32:46 -07002200 * set to true and unmount it after invoking dumpstateBoard_* methods.
2201 * This is to enable debug builds to not have debugfs mounted during runtime.
2202 * It will also ensure that debugfs is only accessed by the dumpstate HAL.
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002203 */
Hridya Valsaraju51101602021-04-02 14:32:46 -07002204 auto mount_debugfs =
Hridya Valsarajud09460c2021-04-15 22:11:18 -07002205 android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002206 if (mount_debugfs) {
2207 RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
2208 AS_ROOT_20);
2209 RunCommand("chmod debugfs", {"chmod", "0755", "/sys/kernel/debug"},
2210 AS_ROOT_20);
2211 }
2212
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002213 std::vector<std::string> paths;
2214 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002215 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002216 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2217 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002218 remover.emplace_back(android::base::make_scope_guard(
2219 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002220 }
Jie Song9fbfad02017-06-20 16:29:42 -07002221
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002222 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2223 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002224 MYLOGE("No IDumpstateDevice implementation\n");
2225 return;
2226 }
2227
2228 using ScopedNativeHandle =
2229 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2230 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2231 [](native_handle_t* handle) {
2232 native_handle_close(handle);
2233 native_handle_delete(handle);
2234 });
2235 if (handle == nullptr) {
2236 MYLOGE("Could not create native_handle\n");
2237 return;
2238 }
2239
Nandana Dutt5c390032019-03-12 10:52:56 +00002240 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002241 for (size_t i = 0; i < paths.size(); i++) {
2242 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2243
2244 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2245 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2246 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2247 if (fd < 0) {
2248 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2249 return;
2250 }
2251 handle.get()->data[i] = fd.release();
2252 }
2253
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002254 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2255 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2256 // will kill the HAL and grab whatever it dumped in time.
2257 constexpr size_t timeout_sec = 30;
2258 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2259 // implement just 1.0.
2260 const char* descriptor_to_kill;
2261 using DumpstateBoardTask = std::packaged_task<bool()>;
2262 DumpstateBoardTask dumpstate_board_task;
2263 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2264 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2265 if (dumpstate_device_1_1 != nullptr) {
2266 MYLOGI("Using IDumpstateDevice v1.1");
2267 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2268 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2269 ::android::hardware::Return<DumpstateStatus> status =
2270 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2271 SEC_TO_MSEC(timeout_sec));
2272 if (!status.isOk()) {
2273 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2274 return false;
2275 } else if (status != DumpstateStatus::OK) {
2276 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2277 return false;
2278 }
2279 return true;
2280 });
2281 } else {
2282 MYLOGI("Using IDumpstateDevice v1.0");
2283 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2284 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2285 ::android::hardware::Return<void> status =
2286 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002287 if (!status.isOk()) {
2288 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002289 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002290 }
Wei Wang587eac92018-04-05 12:17:20 -07002291 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002292 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002293 }
2294 auto result = dumpstate_board_task.get_future();
2295 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002296
Wei Wang587eac92018-04-05 12:17:20 -07002297 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2298 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002299 if (!android::base::SetProperty(
2300 "ctl.interface_restart",
2301 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002302 MYLOGE("Couldn't restart dumpstate HAL\n");
2303 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002304 }
Wei Wang587eac92018-04-05 12:17:20 -07002305 // Wait some time for init to kill dumpstate vendor HAL
2306 constexpr size_t killing_timeout_sec = 10;
2307 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2308 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2309 "there might be racing in content\n", killing_timeout_sec);
2310 }
2311
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002312 if (mount_debugfs) {
Hridya Valsaraju51101602021-04-02 14:32:46 -07002313 auto keep_debugfs_mounted =
2314 android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
2315 if (keep_debugfs_mounted.empty())
2316 RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
Hridya Valsaraju9376bfa2020-10-21 15:48:48 -07002317 }
2318
Wei Wang587eac92018-04-05 12:17:20 -07002319 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2320 for (size_t i = 0; i < paths.size(); i++) {
2321 struct stat s;
2322 if (fstat(handle.get()->data[i], &s) == -1) {
2323 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2324 strerror(errno));
2325 file_sizes[i] = -1;
2326 continue;
2327 }
2328 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002329 }
2330
2331 for (size_t i = 0; i < paths.size(); i++) {
2332 if (file_sizes[i] == -1) {
2333 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002334 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002335 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002336 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002337 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002338 }
Rhed Jao4875aa62020-07-20 17:46:29 +08002339 remover[i].Disable();
2340 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2341 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002342 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002343}
2344
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002345static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002346 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002347 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2348 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002349 " -h: display this help message\n"
2350 " -b: play sound file instead of vibrate, at beginning of job\n"
2351 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002352 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002353 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002354 " -s: write zipped file to control socket (for init)\n"
2355 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002356 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002357 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002358 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002359 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002360 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002361 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002362}
2363
Wei Liuf87959e2016-08-26 14:51:42 -07002364static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002365 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002366}
2367
Felipe Leme1d486fe2016-10-14 18:06:47 -07002368bool Dumpstate::FinishZipFile() {
Rhed Jao4875aa62020-07-20 17:46:29 +08002369 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2370 if (zip_entry_tasks_) {
2371 zip_entry_tasks_->run(/* do_cancel = */false);
2372 }
2373
Felipe Leme9a523ae2016-10-20 15:10:33 -07002374 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002375 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002376 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002377 // Final timestamp
2378 char date[80];
2379 time_t the_real_now_please_stand_up = time(nullptr);
2380 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002381 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002382 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002383
Felipe Leme9a523ae2016-10-20 15:10:33 -07002384 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002385 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002386 return false;
2387 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002388 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002389 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002390 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002391 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002392
Felipe Leme0f3fb202016-06-10 17:10:53 -07002393 // Add log file (which contains stderr output) to zip...
2394 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002395 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002396 MYLOGE("Failed to add dumpstate log to .zip file\n");
2397 return false;
2398 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002399 // TODO: Should truncate the existing file.
2400 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002401 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2402 return false;
2403 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002404 fprintf(stderr, "\n");
2405
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002406 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002407 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002408 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002409 return false;
2410 }
2411
Felipe Leme1d486fe2016-10-14 18:06:47 -07002412 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2413 ds.zip_file.reset(nullptr);
2414
Felipe Lemee9d2c542016-11-15 11:48:26 -08002415 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002416 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002417
Felipe Leme1e9edc62015-12-21 16:02:13 -08002418 return true;
2419}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002420
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002421static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2422 // clang-format off
2423 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2424 "--receiver-foreground", "--receiver-include-background", "-a", action};
2425 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002426
2427 am.insert(am.end(), args.begin(), args.end());
2428
Felipe Leme8d2410e2017-02-08 09:46:08 -08002429 RunCommand("", am,
2430 CommandOptions::WithTimeout(20)
2431 .Log("Sending broadcast: '%s'\n")
2432 .Always()
2433 .DropRoot()
2434 .RedirectStderr()
2435 .Build());
2436}
2437
Felipe Leme35b8cf12017-02-10 15:47:29 -08002438static void Vibrate(int duration_ms) {
2439 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002440 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002441 CommandOptions::WithTimeout(10)
2442 .Log("Vibrate: '%s'\n")
2443 .Always()
2444 .Build());
2445 // clang-format on
2446}
2447
Nandana Dutt979388e2018-11-30 16:48:55 +00002448static void MaybeResolveSymlink(std::string* path) {
2449 std::string resolved_path;
2450 if (android::base::Readlink(*path, &resolved_path)) {
2451 *path = resolved_path;
2452 }
2453}
2454
Nandana Dutt4be45d12018-09-26 15:04:23 +01002455/*
2456 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002457 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002458 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002459static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002460 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2461
Nandana Dutt4be45d12018-09-26 15:04:23 +01002462 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2463 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002464 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002465 char date[80];
2466 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2467 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002468
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002469 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002470 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002471 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002472 ds.base_name_ += "-wifi";
2473 }
2474
Paul Chang0d2aad72020-02-13 20:04:03 +08002475 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002476 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002477 }
2478 ds.tmp_path_ = ds.GetPath(".tmp");
2479 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2480
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002481 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002482 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002483 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002484 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002485 "Bugreport dir: [%s] "
2486 "Base name: [%s] "
2487 "Suffix: [%s] "
2488 "Log path: [%s] "
2489 "Temporary path: [%s] "
2490 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002491 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2492 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002493
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002494 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2495 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2496 create_parent_dirs(ds.path_.c_str());
2497 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2498 if (ds.zip_file == nullptr) {
2499 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2500 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002501 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002502 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2503 ds.AddTextZipEntry("version.txt", ds.version_);
2504 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002505}
2506
2507/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002508 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002509 * printing zipped file status, etc.
2510 */
2511static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002512 bool do_text_file = !ds.FinishZipFile();
2513 if (do_text_file) {
2514 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002515 }
mhasank2d75c442020-06-11 15:05:25 -07002516
2517 std::string final_path = ds.path_;
2518 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002519 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002520 android::os::CopyFileToFile(ds.path_, final_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002521 }
mhasank2d75c442020-06-11 15:05:25 -07002522
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002523 if (ds.options_->stream_to_socket) {
2524 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2525 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002526 if (do_text_file) {
2527 dprintf(ds.control_socket_fd_,
2528 "FAIL:could not create zip file, check %s "
2529 "for more details\n",
2530 ds.log_path_.c_str());
2531 } else {
mhasank2d75c442020-06-11 15:05:25 -07002532 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002533 }
2534 }
2535}
2536
Nandana Dutt4be45d12018-09-26 15:04:23 +01002537
Nandana Dutt58d72e22018-11-16 10:30:48 +00002538static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2539 switch (mode) {
2540 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2541 return "BUGREPORT_FULL";
2542 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2543 return "BUGREPORT_INTERACTIVE";
2544 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2545 return "BUGREPORT_REMOTE";
2546 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2547 return "BUGREPORT_WEAR";
2548 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2549 return "BUGREPORT_TELEPHONY";
2550 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2551 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002552 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2553 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002554 }
2555}
2556
Paul Changf59c2b72020-03-10 02:08:55 +08002557static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2558 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002559 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2560 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002561 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002562 switch (mode) {
2563 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002564 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002565 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002566 break;
2567 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002568 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002569 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002570 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002571 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002572 break;
2573 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002574 options->do_vibrate = false;
2575 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002576 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002577 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002578 break;
2579 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002580 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002581 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002582 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002583 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002584 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002585 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002586 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002587 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002588 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002589 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002590 break;
2591 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002592 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002593 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002594 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002595 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002596 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2597 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002598 }
2599}
2600
Nandana Dutt58d72e22018-11-16 10:30:48 +00002601static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002602 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002603 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao6f5ddce2020-08-20 00:10:32 +08002604 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002605 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002606 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002607 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002608 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao6f5ddce2020-08-20 00:10:32 +08002609 options.telephony_only, options.wifi_only,
mhasankd451a472020-05-26 18:02:39 -07002610 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2611 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002612}
2613
Nandana Dutt54dbd672019-01-11 12:58:05 +00002614void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2615 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002616 const android::base::unique_fd& screenshot_fd_in,
2617 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002618 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2619 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2620 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002621
Paul Changf59c2b72020-03-10 02:08:55 +08002622 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002623}
2624
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002625Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2626 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002627 int c;
mhasankd451a472020-05-26 18:02:39 -07002628 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002629 switch (c) {
2630 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002631 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002632 case 's': stream_to_socket = true; break;
2633 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002634 case 'v': show_header_only = true; break;
2635 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002636 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002637 case 'P': do_progress_updates = true; break;
2638 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002639 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002640 case 'V':
2641 case 'd':
2642 case 'z':
2643 // compatibility no-op
2644 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002645 case 'w':
2646 // This was already processed
2647 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002648 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002649 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002650 break;
2651 default:
2652 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002653 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002654 break;
2655 // clang-format on
2656 }
2657 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002658
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002659 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002660 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002661 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002662 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002663 }
2664 }
2665
2666 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2667 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002668
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002669 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002670}
2671
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002672bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002673 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002674 return false;
2675 }
2676
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002677 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002678 return false;
2679 }
2680
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002681 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002682 return false;
2683 }
2684 return true;
2685}
2686
Nandana Dutt197661d2018-11-16 16:40:21 +00002687void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2688 options_ = std::move(options);
2689}
2690
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002691void Dumpstate::Initialize() {
2692 /* gets the sequential id */
2693 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2694 id_ = ++last_id;
2695 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2696}
2697
Nandana Duttd2f5f082019-01-18 17:13:52 +00002698Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2699 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002700 if (listener_ != nullptr) {
2701 switch (status) {
2702 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002703 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002704 break;
2705 case Dumpstate::RunStatus::HELP:
2706 break;
2707 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002708 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002709 break;
2710 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002711 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2712 break;
2713 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2714 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2715 break;
2716 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2717 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002718 break;
2719 }
2720 }
2721 return status;
2722}
2723
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002724void Dumpstate::Cancel() {
2725 CleanupTmpFiles();
2726 android::os::UnlinkAndLogOnError(log_path_);
2727 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2728 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2729 kDumpstateBoardFiles[i]);
2730 }
2731 tombstone_data_.clear();
2732 anr_data_.clear();
Rhed Jaoe96bcd52020-08-21 14:48:20 +08002733
2734 // Instead of shutdown the pool, we delete temporary files directly since
2735 // shutdown blocking the call.
2736 if (dump_pool_) {
2737 dump_pool_->deleteTempFiles();
2738 }
2739 if (zip_entry_tasks_) {
2740 zip_entry_tasks_->run(/*do_cancel =*/ true);
2741 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002742}
2743
Nandana Dutt979388e2018-11-30 16:48:55 +00002744/*
2745 * Dumps relevant information to a bugreport based on the given options.
2746 *
2747 * The bugreport can be dumped to a file or streamed to a socket.
2748 *
2749 * How dumping to file works:
2750 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2751 * stderr is redirected a log file.
2752 *
2753 * The temporary bugreport is then populated via printfs, dumping contents of files and
2754 * output of commands to stdout.
2755 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002756 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002757 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002758 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002759 *
mhasank2d75c442020-06-11 15:05:25 -07002760 * Bugreports are first generated in a local directory and later copied to the caller's fd
2761 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002762 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002763Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2764 const std::string& calling_package) {
Rhed Jao1c855122020-07-16 17:37:39 +08002765 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002766 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002767 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002768 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002769 return RunStatus::INVALID_INPUT;
2770 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002771 /* set as high priority, and protect from OOM killer */
2772 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002773
Felipe Lemed071c682016-10-20 16:48:00 -07002774 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002775 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002776 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002777 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002778 } else {
2779 /* fallback to kernels <= 2.6.35 */
2780 oom_adj = fopen("/proc/self/oom_adj", "we");
2781 if (oom_adj) {
2782 fputs("-17", oom_adj);
2783 fclose(oom_adj);
2784 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002785 }
2786
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002787 if (version_ == VERSION_DEFAULT) {
2788 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002789 }
2790
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002791 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002792 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002793 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002794 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002795 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002796 }
2797
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002798 if (options_->show_header_only) {
2799 PrintHeader();
2800 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002801 }
2802
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002803 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2804 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002805
Felipe Leme7447d7c2016-11-03 18:12:22 -07002806 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002807 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002808 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002809 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002810
Sahana Raof35ed432019-07-12 10:47:52 +01002811 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2812 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2813 } else {
2814 // Wake lock will be released automatically on process death
2815 MYLOGD("Wake lock acquired.\n");
2816 }
2817
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002818 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002819
Felipe Lemef0292972016-11-22 13:57:05 -08002820 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002821 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2822 }
2823
Nandana Dutt235c6672019-11-14 15:22:32 +00002824 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2825 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002826
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002827 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002828
Christopher Ferrised9354f2014-10-01 17:35:01 -07002829 // If we are going to use a socket, do it as early as possible
2830 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002831 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002832 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002833 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002834 if (control_socket_fd_ == -1) {
2835 return ERROR;
2836 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002837 if (options_->progress_updates_to_socket) {
2838 options_->do_progress_updates = 1;
2839 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002840 }
2841
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002842 if (!PrepareToWriteToFile()) {
2843 return ERROR;
2844 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002845
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002846 // Interactive, wear & telephony modes are default to true.
2847 // and may enable from cli option or when using control socket
2848 if (options_->do_progress_updates) {
2849 // clang-format off
2850 std::vector<std::string> am_args = {
2851 "--receiver-permission", "android.permission.DUMP",
2852 };
2853 // clang-format on
2854 // Send STARTED broadcast for apps that listen to bugreport generation events
2855 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2856 if (options_->progress_updates_to_socket) {
2857 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002858 }
2859 }
2860
Nick Kralevichf3599b32016-01-25 15:05:16 -08002861 /* read /proc/cmdline before dropping root */
2862 FILE *cmdline = fopen("/proc/cmdline", "re");
2863 if (cmdline) {
2864 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2865 fclose(cmdline);
2866 }
2867
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002868 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002869 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002870 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002871
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002872 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002873 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2874 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002875 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002876 }
2877 }
2878
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002879 int dup_stdout_fd;
2880 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002881 // Redirect stderr to log_path_ for debugging.
2882 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2883 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2884 return ERROR;
2885 }
2886 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2887 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2888 strerror(errno));
2889 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002890
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002891 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2892 // moved into zip file later, if zipping.
2893 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2894 // TODO: why not write to a file instead of stdout to overcome this problem?
2895 /* TODO: rather than generating a text file now and zipping it later,
2896 it would be more efficient to redirect stdout to the zip entry
2897 directly, but the libziparchive doesn't support that option yet. */
2898 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2899 return ERROR;
2900 }
2901 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2902 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2903 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002904 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002905
2906 // Don't buffer stdout
2907 setvbuf(stdout, nullptr, _IONBF, 0);
2908
Rhed Jao1c855122020-07-16 17:37:39 +08002909 // Enable the parallel run if the client requests to output to a file.
2910 EnableParallelRunIfNeeded();
2911 // Using scope guard to make sure the dump pool can be shut down correctly.
2912 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2913 ShutdownDumpPool();
2914 });
2915
Felipe Leme608385d2016-02-01 10:35:38 -08002916 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2917 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002918 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002919 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002920
Gavin Corkery6968f552020-11-22 18:09:05 +00002921 bool is_dumpstate_restricted = options_->telephony_only
2922 || options_->wifi_only
2923 || options_->limited_only;
2924 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002925 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002926 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00002927 }
2928 MaybeTakeEarlyScreenshot();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00002929
2930 if (!is_dumpstate_restricted) {
2931 // Snapshot the system trace now (if running) to avoid that dumpstate's
2932 // own activity pushes out interesting data from the trace ring buffer.
2933 // The trace file is added to the zip by MaybeAddSystemTraceToZip().
2934 MaybeSnapshotSystemTrace();
Yohei Yukawa95305b32021-03-09 07:54:27 -08002935
2936 // If a winscope trace is running, snapshot it now. It will be pulled into bugreport later
2937 // from WMTRACE_DATA_DIR.
2938 MaybeSnapshotWinTrace();
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00002939 }
Gavin Corkery6968f552020-11-22 18:09:05 +00002940 onUiIntensiveBugreportDumpsFinished(calling_uid);
2941 MaybeCheckUserConsent(calling_uid, calling_package);
2942 if (options_->telephony_only) {
2943 DumpstateTelephonyOnly(calling_package);
2944 } else if (options_->wifi_only) {
2945 DumpstateWifiOnly();
2946 } else if (options_->limited_only) {
2947 DumpstateLimitedOnly();
2948 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002949 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002950 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002951 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002952 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002953 HandleUserConsentDenied();
2954 }
2955 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002956 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002957 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002958
Felipe Leme55b42a62015-11-10 17:39:08 -08002959 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002960 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002961
Abhijeet Kaure370d682019-10-01 16:49:30 +01002962 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002963 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002964
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002965 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002966 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002967 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002968 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002969 if (status != Dumpstate::RunStatus::OK &&
2970 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2971 // Do an early return if there were errors. We make an exception for consent
2972 // timing out because it's possible the user got distracted. In this case the
2973 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002974 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002975 return status;
2976 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002977 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2978 MYLOGI(
2979 "Did not receive user consent yet."
2980 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002981 const String16 incidentcompanion("incidentcompanion");
2982 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2983 if (ics != nullptr) {
2984 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2985 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2986 consent_callback_.get());
2987 } else {
2988 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2989 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002990 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002991 }
2992
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002993 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002994 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002995 for (int i = 0; i < 3; i++) {
2996 Vibrate(75);
2997 usleep((75 + 50) * 1000);
2998 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002999 }
3000
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003001 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
3002 progress_->GetInitialMax());
3003 progress_->Save();
3004 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07003005
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003006 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08003007
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003008 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07003009 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003010 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07003011 }
3012
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003013 tombstone_data_.clear();
3014 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01003015
Nandana Duttd2f5f082019-01-18 17:13:52 +00003016 return (consent_callback_ != nullptr &&
3017 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
3018 ? USER_CONSENT_TIMED_OUT
3019 : RunStatus::OK;
3020}
3021
Paul Chang0d2aad72020-02-13 20:04:03 +08003022void Dumpstate::MaybeTakeEarlyScreenshot() {
3023 if (!options_->do_screenshot || !do_early_screenshot_) {
3024 return;
3025 }
3026
3027 TakeScreenshot();
3028}
3029
Primiano Tuccifaaaafb2021-01-14 12:26:29 +00003030void Dumpstate::MaybeSnapshotSystemTrace() {
3031 // If a background system trace is happening and is marked as "suitable for
3032 // bugreport" (i.e. bugreport_score > 0 in the trace config), this command
3033 // will stop it and serialize into SYSTEM_TRACE_SNAPSHOT. In the (likely)
3034 // case that no trace is ongoing, this command is a no-op.
3035 // Note: this should not be enqueued as we need to freeze the trace before
3036 // dumpstate starts. Otherwise the trace ring buffers will contain mostly
3037 // the dumpstate's own activity which is irrelevant.
3038 int res = RunCommand(
3039 "SERIALIZE PERFETTO TRACE",
3040 {"perfetto", "--save-for-bugreport"},
3041 CommandOptions::WithTimeout(10)
3042 .DropRoot()
3043 .CloseAllFileDescriptorsOnExec()
3044 .Build());
3045 has_system_trace_ = res == 0;
3046 // MaybeAddSystemTraceToZip() will take care of copying the trace in the zip
3047 // file in the later stages.
3048}
3049
Yohei Yukawa95305b32021-03-09 07:54:27 -08003050void Dumpstate::MaybeSnapshotWinTrace() {
Yohei Yukawa02b1d2c2021-03-16 09:20:30 -07003051 // Currently WindowManagerService and InputMethodManagerSerivice support WinScope protocol.
3052 for (const auto& service : {"window", "input_method"}) {
3053 RunCommand(
3054 // Empty name because it's not intended to be classified as a bugreport section.
3055 // Actual tracing files can be found in "/data/misc/wmtrace/" in the bugreport.
3056 "", {"cmd", service, "tracing", "save-for-bugreport"},
3057 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3058 }
Yohei Yukawa95305b32021-03-09 07:54:27 -08003059}
3060
Paul Chang5702b482020-05-28 22:05:47 +08003061void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08003062 if (calling_uid == AID_SHELL || !CalledByApi()) {
3063 return;
3064 }
3065 if (listener_ != nullptr) {
3066 // Let listener know ui intensive bugreport dumps are finished, then it can do event
3067 // handling if required.
Paul Chang5702b482020-05-28 22:05:47 +08003068 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08003069 }
3070}
3071
Jichao Lie89d9c12019-11-21 19:02:51 -08003072void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
3073 if (calling_uid == AID_SHELL || !CalledByApi()) {
3074 // No need to get consent for shell triggered dumpstates, or not through
3075 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003076 return;
3077 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003078 consent_callback_ = new ConsentCallback();
3079 const String16 incidentcompanion("incidentcompanion");
3080 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08003081 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003082 if (ics != nullptr) {
3083 MYLOGD("Checking user consent via incidentcompanion service\n");
3084 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08003085 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07003086 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00003087 } else {
3088 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
3089 }
3090}
3091
Nandana Dutt5c390032019-03-12 10:52:56 +00003092bool Dumpstate::IsUserConsentDenied() const {
3093 return ds.consent_callback_ != nullptr &&
3094 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
3095}
3096
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01003097bool Dumpstate::CalledByApi() const {
3098 return ds.options_->bugreport_fd.get() != -1 ? true : false;
3099}
3100
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003101void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003102 android::os::UnlinkAndLogOnError(tmp_path_);
3103 android::os::UnlinkAndLogOnError(screenshot_path_);
3104 android::os::UnlinkAndLogOnError(path_);
Gavin Corkery789d7a52021-02-24 23:52:35 +00003105 if (dump_traces_path != nullptr) {
3106 android::os::UnlinkAndLogOnError(dump_traces_path);
3107 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003108}
3109
Rhed Jao1c855122020-07-16 17:37:39 +08003110void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003111 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao1c855122020-07-16 17:37:39 +08003112 return;
3113 }
3114 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao4875aa62020-07-20 17:46:29 +08003115 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao1c855122020-07-16 17:37:39 +08003116}
3117
3118void Dumpstate::ShutdownDumpPool() {
3119 if (dump_pool_) {
3120 dump_pool_->shutdown();
3121 dump_pool_ = nullptr;
3122 }
Rhed Jao4875aa62020-07-20 17:46:29 +08003123 if (zip_entry_tasks_) {
3124 zip_entry_tasks_->run(/* do_cancel = */true);
3125 zip_entry_tasks_ = nullptr;
3126 }
3127}
3128
3129void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3130 const std::string& entry_path) {
3131 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3132 if (!task_cancelled) {
3133 AddZipEntry(entry_name, entry_path);
3134 }
3135 android::os::UnlinkAndLogOnError(entry_path);
3136 };
3137 if (zip_entry_tasks_) {
3138 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3139 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3140 } else {
3141 // Invokes AddZipEntryAndCleanup immediately
3142 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3143 }
Rhed Jao1c855122020-07-16 17:37:39 +08003144}
3145
Nandana Duttd2f5f082019-01-18 17:13:52 +00003146Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3147 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003148 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003149 return USER_CONSENT_DENIED;
3150}
3151
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003152Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003153 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003154 // user consent (unless the caller is Shell).
3155 UserConsentResult consent_result;
3156 if (calling_uid == AID_SHELL) {
3157 consent_result = UserConsentResult::APPROVED;
3158 } else {
3159 consent_result = consent_callback_->getResult();
3160 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003161 if (consent_result == UserConsentResult::UNAVAILABLE) {
3162 // User has not responded yet.
3163 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003164 // Telephony is a fast report type, particularly on user builds where information may be
3165 // more aggressively limited. To give the user time to read the consent dialog, increase the
3166 // timeout.
3167 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3168 : USER_CONSENT_TIMEOUT_MS;
3169 if (elapsed_ms < timeout_ms) {
3170 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003171 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3172 sleep(delay_seconds);
3173 }
3174 consent_result = consent_callback_->getResult();
3175 }
3176 if (consent_result == UserConsentResult::DENIED) {
3177 // User has explicitly denied sharing with the app. To be safe delete the
3178 // internal bugreport & tmp files.
3179 return HandleUserConsentDenied();
3180 }
3181 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003182 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3183 if (copy_succeeded) {
3184 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003185 if (options_->do_screenshot &&
3186 options_->screenshot_fd.get() != -1 &&
3187 !options_->is_screenshot_copied) {
3188 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3189 options_->screenshot_fd.get());
3190 options_->is_screenshot_copied = copy_succeeded;
3191 if (copy_succeeded) {
3192 android::os::UnlinkAndLogOnError(screenshot_path_);
3193 }
3194 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003195 }
3196 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3197 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3198 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3199 // Since we do not have user consent to share the bugreport it does not get
3200 // copied over to the calling app but remains in the internal directory from
3201 // where the user can manually pull it.
3202 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3203 }
3204 // Unknown result; must be a programming error.
3205 MYLOGE("Unknown user consent result:%d\n", consent_result);
3206 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003207}
3208
Nandana Duttf02564e2019-02-15 15:24:24 +00003209Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003210 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3211 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3212 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003213 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003214 // When directly running dumpstate binary, the output is not expected to be written
3215 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003216 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003217
3218 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003219 // an app; they are irrelevant here because bugreport is triggered via command line.
3220 // Update Last ID before calling Run().
3221 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003222 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003223 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003224 return status;
3225}
3226
3227/* Main entry point for dumpstate binary. */
3228int run_main(int argc, char* argv[]) {
3229 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003230
3231 switch (status) {
3232 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003233 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003234 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003235 ShowUsage();
3236 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003237 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003238 fprintf(stderr, "Invalid combination of args\n");
3239 ShowUsage();
3240 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003241 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003242 FALLTHROUGH_INTENDED;
3243 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3244 FALLTHROUGH_INTENDED;
3245 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003246 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003247 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003248}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003249
3250// TODO(111441001): Default DumpOptions to sensible values.
3251Dumpstate::Dumpstate(const std::string& version)
3252 : pid_(getpid()),
3253 options_(new Dumpstate::DumpOptions()),
Nandana Duttf02cd782019-06-14 14:25:13 +01003254 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003255 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003256 now_(time(nullptr)),
3257 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003258}
3259
3260Dumpstate& Dumpstate::GetInstance() {
3261 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3262 return singleton_;
3263}
3264
Rhed Jao1c855122020-07-16 17:37:39 +08003265DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3266 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3267 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003268 if (!title_.empty()) {
3269 started_ = Nanotime();
3270 }
3271}
3272
3273DurationReporter::~DurationReporter() {
3274 if (!title_.empty()) {
3275 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003276 if (elapsed >= .5f || verbose_) {
3277 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003278 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003279 if (!logcat_only_) {
3280 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao1c855122020-07-16 17:37:39 +08003281 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3282 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003283 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003284 }
3285}
3286
3287const int32_t Progress::kDefaultMax = 5000;
3288
3289Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3290}
3291
3292Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3293 : Progress(initial_max, growth_factor, "") {
3294 progress_ = progress;
3295}
3296
3297Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3298 : initial_max_(initial_max),
3299 progress_(0),
3300 max_(initial_max),
3301 growth_factor_(growth_factor),
3302 n_runs_(0),
3303 average_max_(0),
3304 path_(path) {
3305 if (!path_.empty()) {
3306 Load();
3307 }
3308}
3309
3310void Progress::Load() {
3311 MYLOGD("Loading stats from %s\n", path_.c_str());
3312 std::string content;
3313 if (!android::base::ReadFileToString(path_, &content)) {
3314 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3315 return;
3316 }
3317 if (content.empty()) {
3318 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3319 return;
3320 }
3321 std::vector<std::string> lines = android::base::Split(content, "\n");
3322
3323 if (lines.size() < 1) {
3324 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3325 (int)lines.size(), max_);
3326 return;
3327 }
3328 char* ptr;
3329 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3330 average_max_ = strtol(ptr, nullptr, 10);
3331 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3332 average_max_ > STATS_MAX_AVERAGE) {
3333 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3334 initial_max_ = Progress::kDefaultMax;
3335 } else {
3336 initial_max_ = average_max_;
3337 }
3338 max_ = initial_max_;
3339
3340 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3341}
3342
3343void Progress::Save() {
3344 int32_t total = n_runs_ * average_max_ + progress_;
3345 int32_t runs = n_runs_ + 1;
3346 int32_t average = floor(((float)total) / runs);
3347 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3348 path_.c_str());
3349 if (path_.empty()) {
3350 return;
3351 }
3352
3353 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3354 if (!android::base::WriteStringToFile(content, path_)) {
3355 MYLOGE("Could not save stats on %s\n", path_.c_str());
3356 }
3357}
3358
3359int32_t Progress::Get() const {
3360 return progress_;
3361}
3362
3363bool Progress::Inc(int32_t delta_sec) {
3364 bool changed = false;
3365 if (delta_sec >= 0) {
3366 progress_ += delta_sec;
3367 if (progress_ > max_) {
3368 int32_t old_max = max_;
3369 max_ = floor((float)progress_ * growth_factor_);
3370 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3371 changed = true;
3372 }
3373 }
3374 return changed;
3375}
3376
3377int32_t Progress::GetMax() const {
3378 return max_;
3379}
3380
3381int32_t Progress::GetInitialMax() const {
3382 return initial_max_;
3383}
3384
3385void Progress::Dump(int fd, const std::string& prefix) const {
3386 const char* pr = prefix.c_str();
3387 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3388 dprintf(fd, "%smax: %d\n", pr, max_);
3389 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3390 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3391 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3392 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3393 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3394}
3395
3396bool Dumpstate::IsZipping() const {
3397 return zip_writer_ != nullptr;
3398}
3399
3400std::string Dumpstate::GetPath(const std::string& suffix) const {
3401 return GetPath(bugreport_internal_dir_, suffix);
3402}
3403
3404std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3405 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3406 name_.c_str(), suffix.c_str());
3407}
3408
3409void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3410 progress_ = std::move(progress);
3411}
3412
3413void for_each_userid(void (*func)(int), const char *header) {
3414 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3415 "for_each_userid(%s)", header);
3416 DurationReporter duration_reporter(title);
3417 if (PropertiesHelper::IsDryRun()) return;
3418
3419 DIR *d;
3420 struct dirent *de;
3421
3422 if (header) printf("\n------ %s ------\n", header);
3423 func(0);
3424
3425 if (!(d = opendir("/data/system/users"))) {
3426 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3427 return;
3428 }
3429
3430 while ((de = readdir(d))) {
3431 int userid;
3432 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3433 continue;
3434 }
3435 func(userid);
3436 }
3437
3438 closedir(d);
3439}
3440
3441static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3442 DIR *d;
3443 struct dirent *de;
3444
3445 if (!(d = opendir("/proc"))) {
3446 printf("Failed to open /proc (%s)\n", strerror(errno));
3447 return;
3448 }
3449
3450 if (header) printf("\n------ %s ------\n", header);
3451 while ((de = readdir(d))) {
3452 if (ds.IsUserConsentDenied()) {
3453 MYLOGE(
3454 "Returning early because user denied consent to share bugreport with calling app.");
3455 closedir(d);
3456 return;
3457 }
3458 int pid;
3459 int fd;
3460 char cmdpath[255];
3461 char cmdline[255];
3462
3463 if (!(pid = atoi(de->d_name))) {
3464 continue;
3465 }
3466
3467 memset(cmdline, 0, sizeof(cmdline));
3468
3469 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3470 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3471 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3472 close(fd);
3473 if (cmdline[0]) {
3474 helper(pid, cmdline, arg);
3475 continue;
3476 }
3477 }
3478
3479 // if no cmdline, a kernel thread has comm
3480 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3481 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3482 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3483 close(fd);
3484 if (cmdline[1]) {
3485 cmdline[0] = '[';
3486 size_t len = strcspn(cmdline, "\f\b\r\n");
3487 cmdline[len] = ']';
3488 cmdline[len+1] = '\0';
3489 }
3490 }
3491 if (!cmdline[0]) {
3492 strcpy(cmdline, "N/A");
3493 }
3494 helper(pid, cmdline, arg);
3495 }
3496
3497 closedir(d);
3498}
3499
3500static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3501 for_each_pid_func *func = (for_each_pid_func*) arg;
3502 func(pid, cmdline);
3503}
3504
3505void for_each_pid(for_each_pid_func func, const char *header) {
3506 std::string title = header == nullptr ? "for_each_pid"
3507 : android::base::StringPrintf("for_each_pid(%s)", header);
3508 DurationReporter duration_reporter(title);
3509 if (PropertiesHelper::IsDryRun()) return;
3510
3511 __for_each_pid(for_each_pid_helper, header, (void *) func);
3512}
3513
3514static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3515 DIR *d;
3516 struct dirent *de;
3517 char taskpath[255];
3518 for_each_tid_func *func = (for_each_tid_func *) arg;
3519
3520 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3521
3522 if (!(d = opendir(taskpath))) {
3523 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3524 return;
3525 }
3526
3527 func(pid, pid, cmdline);
3528
3529 while ((de = readdir(d))) {
3530 if (ds.IsUserConsentDenied()) {
3531 MYLOGE(
3532 "Returning early because user denied consent to share bugreport with calling app.");
3533 closedir(d);
3534 return;
3535 }
3536 int tid;
3537 int fd;
3538 char commpath[255];
3539 char comm[255];
3540
3541 if (!(tid = atoi(de->d_name))) {
3542 continue;
3543 }
3544
3545 if (tid == pid)
3546 continue;
3547
3548 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3549 memset(comm, 0, sizeof(comm));
3550 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3551 strcpy(comm, "N/A");
3552 } else {
3553 char *c;
3554 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3555 close(fd);
3556
3557 c = strrchr(comm, '\n');
3558 if (c) {
3559 *c = '\0';
3560 }
3561 }
3562 func(pid, tid, comm);
3563 }
3564
3565 closedir(d);
3566}
3567
3568void for_each_tid(for_each_tid_func func, const char *header) {
3569 std::string title = header == nullptr ? "for_each_tid"
3570 : android::base::StringPrintf("for_each_tid(%s)", header);
3571 DurationReporter duration_reporter(title);
3572
3573 if (PropertiesHelper::IsDryRun()) return;
3574
3575 __for_each_pid(for_each_tid_helper, header, (void *) func);
3576}
3577
3578void show_wchan(int pid, int tid, const char *name) {
3579 if (PropertiesHelper::IsDryRun()) return;
3580
3581 char path[255];
3582 char buffer[255];
3583 int fd, ret, save_errno;
3584 char name_buffer[255];
3585
3586 memset(buffer, 0, sizeof(buffer));
3587
3588 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3589 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3590 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3591 return;
3592 }
3593
3594 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3595 save_errno = errno;
3596 close(fd);
3597
3598 if (ret < 0) {
3599 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3600 return;
3601 }
3602
3603 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3604 pid == tid ? 0 : 3, "", name);
3605
3606 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3607
3608 return;
3609}
3610
3611// print time in centiseconds
3612static void snprcent(char *buffer, size_t len, size_t spc,
3613 unsigned long long time) {
3614 static long hz; // cache discovered hz
3615
3616 if (hz <= 0) {
3617 hz = sysconf(_SC_CLK_TCK);
3618 if (hz <= 0) {
3619 hz = 1000;
3620 }
3621 }
3622
3623 // convert to centiseconds
3624 time = (time * 100 + (hz / 2)) / hz;
3625
3626 char str[16];
3627
3628 snprintf(str, sizeof(str), " %llu.%02u",
3629 time / 100, (unsigned)(time % 100));
3630 size_t offset = strlen(buffer);
3631 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3632 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3633}
3634
3635// print permille as a percent
3636static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3637 char str[16];
3638
3639 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3640 size_t offset = strlen(buffer);
3641 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3642 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3643}
3644
3645void show_showtime(int pid, const char *name) {
3646 if (PropertiesHelper::IsDryRun()) return;
3647
3648 char path[255];
3649 char buffer[1023];
3650 int fd, ret, save_errno;
3651
3652 memset(buffer, 0, sizeof(buffer));
3653
3654 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3655 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3656 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3657 return;
3658 }
3659
3660 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3661 save_errno = errno;
3662 close(fd);
3663
3664 if (ret < 0) {
3665 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3666 return;
3667 }
3668
3669 // field 14 is utime
3670 // field 15 is stime
3671 // field 42 is iotime
3672 unsigned long long utime = 0, stime = 0, iotime = 0;
3673 if (sscanf(buffer,
3674 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3675 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3676 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3677 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3678 &utime, &stime, &iotime) != 3) {
3679 return;
3680 }
3681
3682 unsigned long long total = utime + stime;
3683 if (!total) {
3684 return;
3685 }
3686
3687 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3688 if (permille > 1000) {
3689 permille = 1000;
3690 }
3691
3692 // try to beautify and stabilize columns at <80 characters
3693 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3694 if ((name[0] != '[') || utime) {
3695 snprcent(buffer, sizeof(buffer), 57, utime);
3696 }
3697 snprcent(buffer, sizeof(buffer), 65, stime);
3698 if ((name[0] != '[') || iotime) {
3699 snprcent(buffer, sizeof(buffer), 73, iotime);
3700 }
3701 if (iotime) {
3702 snprdec(buffer, sizeof(buffer), 79, permille);
3703 }
3704 puts(buffer); // adds a trailing newline
3705
3706 return;
3707}
3708
3709void do_dmesg() {
3710 const char *title = "KERNEL LOG (dmesg)";
3711 DurationReporter duration_reporter(title);
3712 printf("------ %s ------\n", title);
3713
3714 if (PropertiesHelper::IsDryRun()) return;
3715
3716 /* Get size of kernel buffer */
3717 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3718 if (size <= 0) {
3719 printf("Unexpected klogctl return value: %d\n\n", size);
3720 return;
3721 }
3722 char *buf = (char *) malloc(size + 1);
3723 if (buf == nullptr) {
3724 printf("memory allocation failed\n\n");
3725 return;
3726 }
3727 int retval = klogctl(KLOG_READ_ALL, buf, size);
3728 if (retval < 0) {
3729 printf("klogctl failure\n\n");
3730 free(buf);
3731 return;
3732 }
3733 buf[retval] = '\0';
3734 printf("%s\n\n", buf);
3735 free(buf);
3736 return;
3737}
3738
3739void do_showmap(int pid, const char *name) {
3740 char title[255];
3741 char arg[255];
3742
3743 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3744 snprintf(arg, sizeof(arg), "%d", pid);
3745 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3746}
3747
3748int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3749 DurationReporter duration_reporter(title);
3750
3751 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3752
3753 UpdateProgress(WEIGHT_FILE);
3754
3755 return status;
3756}
3757
3758int read_file_as_long(const char *path, long int *output) {
3759 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3760 if (fd < 0) {
3761 int err = errno;
3762 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3763 return -1;
3764 }
3765 char buffer[50];
3766 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3767 if (bytes_read == -1) {
3768 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3769 return -2;
3770 }
3771 if (bytes_read == 0) {
3772 MYLOGE("File %s is empty\n", path);
3773 return -3;
3774 }
3775 *output = atoi(buffer);
3776 return 0;
3777}
3778
3779/* calls skip to gate calling dump_from_fd recursively
3780 * in the specified directory. dump_from_fd defaults to
3781 * dump_file_from_fd above when set to NULL. skip defaults
3782 * to false when set to NULL. dump_from_fd will always be
3783 * called with title NULL.
3784 */
3785int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3786 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3787 DurationReporter duration_reporter(title);
3788 DIR *dirp;
3789 struct dirent *d;
3790 char *newpath = nullptr;
3791 const char *slash = "/";
3792 int retval = 0;
3793
3794 if (!title.empty()) {
3795 printf("------ %s (%s) ------\n", title.c_str(), dir);
3796 }
3797 if (PropertiesHelper::IsDryRun()) return 0;
3798
3799 if (dir[strlen(dir) - 1] == '/') {
3800 ++slash;
3801 }
3802 dirp = opendir(dir);
3803 if (dirp == nullptr) {
3804 retval = -errno;
3805 MYLOGE("%s: %s\n", dir, strerror(errno));
3806 return retval;
3807 }
3808
3809 if (!dump_from_fd) {
3810 dump_from_fd = dump_file_from_fd;
3811 }
3812 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3813 if ((d->d_name[0] == '.')
3814 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3815 || (d->d_name[1] == '\0'))) {
3816 continue;
3817 }
3818 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3819 (d->d_type == DT_DIR) ? "/" : "");
3820 if (!newpath) {
3821 retval = -errno;
3822 continue;
3823 }
3824 if (skip && (*skip)(newpath)) {
3825 continue;
3826 }
3827 if (d->d_type == DT_DIR) {
3828 int ret = dump_files("", newpath, skip, dump_from_fd);
3829 if (ret < 0) {
3830 retval = ret;
3831 }
3832 continue;
3833 }
3834 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3835 if (fd.get() < 0) {
3836 retval = -1;
3837 printf("*** %s: %s\n", newpath, strerror(errno));
3838 continue;
3839 }
3840 (*dump_from_fd)(nullptr, newpath, fd.get());
3841 }
3842 closedir(dirp);
3843 if (!title.empty()) {
3844 printf("\n");
3845 }
3846 return retval;
3847}
3848
3849/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3850 * it's possible to avoid issues where opening the file itself can get
3851 * stuck.
3852 */
3853int dump_file_from_fd(const char *title, const char *path, int fd) {
3854 if (PropertiesHelper::IsDryRun()) return 0;
3855
3856 int flags = fcntl(fd, F_GETFL);
3857 if (flags == -1) {
3858 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3859 return -1;
3860 } else if (!(flags & O_NONBLOCK)) {
3861 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3862 return -1;
3863 }
3864 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3865}
3866
3867int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao4875aa62020-07-20 17:46:29 +08003868 const CommandOptions& options, bool verbose_duration, int out_fd) {
3869 DurationReporter duration_reporter(title, false /* logcat_only */,
3870 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003871
Rhed Jao4875aa62020-07-20 17:46:29 +08003872 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003873
3874 /* TODO: for now we're simplifying the progress calculation by using the
3875 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3876 * where its weight should be much higher proportionally to its timeout.
3877 * Ideally, it should use a options.EstimatedDuration() instead...*/
3878 UpdateProgress(options.Timeout());
3879
3880 return status;
3881}
3882
3883void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08003884 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003885 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3886 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3887 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08003888 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003889}
3890
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003891static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003892 int s = android_get_control_socket(service);
3893 if (s < 0) {
3894 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3895 return -1;
3896 }
3897 fcntl(s, F_SETFD, FD_CLOEXEC);
3898
3899 // Set backlog to 0 to make sure that queue size will be minimum.
3900 // In Linux, because the minimum queue will be 1, connect() will be blocked
3901 // if the other clients already called connect() and the connection request was not accepted.
3902 if (listen(s, 0) < 0) {
3903 MYLOGE("listen(control socket): %s\n", strerror(errno));
3904 return -1;
3905 }
3906
3907 struct sockaddr addr;
3908 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003909 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003910
3911 // Close socket just after accept(), to make sure that connect() by client will get error
3912 // when the socket is used by the other services.
3913 // There is still a race condition possibility between accept and close, but there is no way
3914 // to close-on-accept atomically.
3915 // See detail; b/123306389#comment25
3916 close(s);
3917
3918 if (fd < 0) {
3919 MYLOGE("accept(control socket): %s\n", strerror(errno));
3920 return -1;
3921 }
3922
3923 return fd;
3924}
3925
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003926// TODO: should call is_valid_output_file and/or be merged into it.
3927void create_parent_dirs(const char *path) {
3928 char *chp = const_cast<char *> (path);
3929
3930 /* skip initial slash */
3931 if (chp[0] == '/')
3932 chp++;
3933
3934 /* create leading directories, if necessary */
3935 struct stat dir_stat;
3936 while (chp && chp[0]) {
3937 chp = strchr(chp, '/');
3938 if (chp) {
3939 *chp = 0;
3940 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3941 MYLOGI("Creating directory %s\n", path);
3942 if (mkdir(path, 0770)) { /* drwxrwx--- */
3943 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3944 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3945 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3946 }
3947 }
3948 *chp++ = '/';
3949 }
3950 }
3951}
3952
3953bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3954 create_parent_dirs(path);
3955
3956 int fd = TEMP_FAILURE_RETRY(open(path,
3957 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3958 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3959 if (fd < 0) {
3960 MYLOGE("%s: %s\n", path, strerror(errno));
3961 return false;
3962 }
3963
3964 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3965 close(fd);
3966 return true;
3967}
3968
3969bool redirect_to_file(FILE* redirect, char* path) {
3970 return _redirect_to_file(redirect, path, O_TRUNC);
3971}
3972
3973bool redirect_to_existing_file(FILE* redirect, char* path) {
3974 return _redirect_to_file(redirect, path, O_APPEND);
3975}
3976
3977void dump_route_tables() {
3978 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3979 if (PropertiesHelper::IsDryRun()) return;
3980 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3981 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3982 FILE* fp = fopen(RT_TABLES_PATH, "re");
3983 if (!fp) {
3984 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3985 return;
3986 }
3987 char table[16];
3988 // Each line has an integer (the table number), a space, and a string (the table name). We only
3989 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3990 // Add a fixed max limit so this doesn't go awry.
3991 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3992 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3993 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3994 }
3995 fclose(fp);
3996}
3997
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003998void Dumpstate::UpdateProgress(int32_t delta_sec) {
3999 if (progress_ == nullptr) {
4000 MYLOGE("UpdateProgress: progress_ not set\n");
4001 return;
4002 }
Rhed Jao2cc4eec2020-07-21 15:42:55 +08004003 // This function updates progress related members of the dumpstate and reports
4004 // progress percentage to the bugreport client. Since it could be called by
4005 // different dump tasks at the same time if the parallel run is enabled, a
4006 // mutex lock is necessary here to synchronize the call.
4007 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004008
4009 // Always update progess so stats can be tuned...
Nandana Duttf02cd782019-06-14 14:25:13 +01004010 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004011
4012 // ...but only notifiy listeners when necessary.
4013 if (!options_->do_progress_updates) return;
4014
4015 int progress = progress_->Get();
4016 int max = progress_->GetMax();
Nandana Duttf02cd782019-06-14 14:25:13 +01004017 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004018
Nandana Duttf02cd782019-06-14 14:25:13 +01004019 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004020 return;
4021 }
Nandana Duttf02cd782019-06-14 14:25:13 +01004022 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004023
4024 if (control_socket_fd_ >= 0) {
4025 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
4026 fsync(control_socket_fd_);
4027 }
4028
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004029 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00004030 if (percent % 10 == 0) {
4031 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004032 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004033 } else {
4034 // stderr is ignored on normal invocations, but useful when calling
4035 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01004036 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004037 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004038
4039 listener_->onProgress(percent);
4040 }
4041}
4042
4043void Dumpstate::TakeScreenshot(const std::string& path) {
4044 const std::string& real_path = path.empty() ? screenshot_path_ : path;
4045 int status =
4046 RunCommand("", {"/system/bin/screencap", "-p", real_path},
4047 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
4048 if (status == 0) {
4049 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
4050 } else {
4051 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
4052 }
Paul Chang0d2aad72020-02-13 20:04:03 +08004053 if (listener_ != nullptr) {
4054 // Show a visual indication to indicate screenshot is taken via
4055 // IDumpstateListener.onScreenshotTaken()
4056 listener_->onScreenshotTaken(status == 0);
4057 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01004058}
4059
4060bool is_dir(const char* pathname) {
4061 struct stat info;
4062 if (stat(pathname, &info) == -1) {
4063 return false;
4064 }
4065 return S_ISDIR(info.st_mode);
4066}
4067
4068time_t get_mtime(int fd, time_t default_mtime) {
4069 struct stat info;
4070 if (fstat(fd, &info) == -1) {
4071 return default_mtime;
4072 }
4073 return info.st_mtime;
4074}