blob: 9c5b8833d79f324bb31807ff6b998143d24a3667 [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>
Vishnu Naire97d6122018-01-18 13:58:56 -080031#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070032#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070033#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/time.h>
36#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010037#include <signal.h>
38#include <stdarg.h>
39#include <string.h>
40#include <sys/capability.h>
41#include <sys/inotify.h>
42#include <sys/klog.h>
43#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070045
46#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070047#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000048#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070049#include <functional>
50#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010051#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070052#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <regex>
54#include <set>
55#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070056#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010057#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070058
Felipe Leme96c2bbb2016-09-26 09:21:21 -070059#include <android-base/file.h>
60#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070061#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080062#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070063#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070064#include <android-base/unique_fd.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010065#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080066#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080067#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
68#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080069#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000070#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070073#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010074#include <cutils/sockets.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000075#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080076#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000077#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010078#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080079#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070081#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070082#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070083#include <private/android_filesystem_config.h>
84#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080085#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070086#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080087#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070088#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070089#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080090
Hunter Knepshield8540faf2020-02-04 19:47:20 -080091using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
92using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
93using ::android::hardware::dumpstate::V1_1::DumpstateMode;
94using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
95using ::android::hardware::dumpstate::V1_1::toString;
Vishnu Naire97d6122018-01-18 13:58:56 -080096using ::std::literals::chrono_literals::operator""ms;
97using ::std::literals::chrono_literals::operator""s;
Rhed Jao1c855122020-07-16 17:37:39 +080098using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -080099
Felipe Leme47e9be22016-12-21 15:37:07 -0800100// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800101using android::defaultServiceManager;
102using android::Dumpsys;
103using android::INVALID_OPERATION;
104using android::IServiceManager;
105using android::OK;
106using android::sp;
107using android::status_t;
108using android::String16;
109using android::String8;
110using android::TIMED_OUT;
111using android::UNKNOWN_ERROR;
112using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000113using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000114using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800115using android::os::dumpstate::CommandOptions;
116using android::os::dumpstate::DumpFileToFd;
Rhed Jao1c855122020-07-16 17:37:39 +0800117using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800118using android::os::dumpstate::PropertiesHelper;
Rhed Jao4875aa62020-07-20 17:46:29 +0800119using android::os::dumpstate::TaskQueue;
Felipe Leme47e9be22016-12-21 15:37:07 -0800120
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100121// Keep in sync with
122// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
123static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
124
125/* Most simple commands have 10 as timeout, so 5 is a good estimate */
126static const int32_t WEIGHT_FILE = 5;
127
128// TODO: temporary variables and functions used during C++ refactoring
129static Dumpstate& ds = Dumpstate::GetInstance();
130static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100131 const CommandOptions& options = CommandOptions::DEFAULT,
Rhed Jao4875aa62020-07-20 17:46:29 +0800132 bool verbose_duration = false, int out_fd = STDOUT_FILENO) {
133 return ds.RunCommand(title, full_command, options, verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100134}
135
136// Reasonable value for max stats.
137static const int STATS_MAX_N_RUNS = 1000;
138static const long STATS_MAX_AVERAGE = 100000;
139
140CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
141
Nandana Duttd2f5f082019-01-18 17:13:52 +0000142typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
143
Colin Crossf45fa6b2012-03-26 12:38:26 -0700144/* read before root is shed */
145static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700146static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000147static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800148// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
149// it's often the case that they time out far too quickly for consent with such a hefty dialog for
150// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
151// roughly match full reports' durations.
152static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700153
Felipe Leme1d486fe2016-10-14 18:06:47 -0700154// TODO: variables and functions below should be part of dumpstate object
155
Felipe Leme635ca312016-01-05 14:23:02 -0800156static std::set<std::string> mount_points;
157void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800158
Todd Poynor2a83daa2013-11-22 15:44:22 -0800159#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700160#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700161#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800162
Felipe Lemee82a27d2016-01-05 13:35:44 -0800163#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700164#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700165#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700166#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800167#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100168#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
169#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800170#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900171#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800172#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700173#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800174#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900175#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravle78a0d842020-04-28 15:31:12 -0700176#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700177
Narayan Kamath8f788292017-05-25 13:20:39 +0100178// TODO(narayan): Since this information has to be kept in sync
179// with tombstoned, we should just put it in a common header.
180//
181// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100182static const std::string TOMBSTONE_DIR = "/data/tombstones/";
183static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
184static const std::string ANR_DIR = "/data/anr/";
185static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700186
Felipe Lemee844a9d2016-09-21 15:01:39 -0700187// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000188
Nandana Dutt5c390032019-03-12 10:52:56 +0000189#define RETURN_IF_USER_DENIED_CONSENT() \
190 if (ds.IsUserConsentDenied()) { \
191 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
192 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
193 }
194
195// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
196// if consent is found to be denied.
197#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
198 RETURN_IF_USER_DENIED_CONSENT(); \
199 func_ptr(__VA_ARGS__); \
200 RETURN_IF_USER_DENIED_CONSENT();
201
Rhed Jao1c855122020-07-16 17:37:39 +0800202// Runs func_ptr, and logs a duration report after it's finished.
203#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
204 { \
205 DurationReporter duration_reporter_in_macro(log_title); \
206 func_ptr(__VA_ARGS__); \
207 }
208
209// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
210// is output after a slow function is finished.
211#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
212 RETURN_IF_USER_DENIED_CONSENT(); \
213 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
214 RETURN_IF_USER_DENIED_CONSENT();
215
Rhed Jao4875aa62020-07-20 17:46:29 +0800216#define WAIT_TASK_WITH_CONSENT_CHECK(task_name, pool_ptr) \
217 RETURN_IF_USER_DENIED_CONSENT(); \
218 pool_ptr->waitForTask(task_name); \
219 RETURN_IF_USER_DENIED_CONSENT();
220
Sahana Raof35ed432019-07-12 10:47:52 +0100221static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
222
Rhed Jao1c855122020-07-16 17:37:39 +0800223// Names of parallel tasks, they are used for the DumpPool to identify the dump
224// task and the log title of the duration report.
225static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
Rhed Jao4875aa62020-07-20 17:46:29 +0800226static const std::string DUMP_INCIDENT_REPORT_TASK = "INCIDENT REPORT";
227static const std::string DUMP_HALS_TASK = "DUMP HALS";
228static const std::string DUMP_BOARD_TASK = "dumpstate_board()";
Rhed Jao6b1ea2d2020-07-21 17:58:41 +0800229static const std::string DUMP_CHECKINS_TASK = "DUMP CHECKINS";
Rhed Jao1c855122020-07-16 17:37:39 +0800230
Nandana Dutt979388e2018-11-30 16:48:55 +0000231namespace android {
232namespace os {
233namespace {
234
235static int Open(std::string path, int flags, mode_t mode = 0) {
236 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
237 if (fd == -1) {
238 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
239 }
240 return fd;
241}
242
mhasank2d75c442020-06-11 15:05:25 -0700243static int OpenForWrite(std::string path) {
244 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
245 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
246}
Nandana Dutt979388e2018-11-30 16:48:55 +0000247
248static int OpenForRead(std::string path) {
249 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
250}
251
252bool CopyFile(int in_fd, int out_fd) {
253 char buf[4096];
254 ssize_t byte_count;
255 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
256 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
257 return false;
258 }
259 }
260 return (byte_count != -1);
261}
262
263static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000264 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000265
266 // Obtain a handle to the source file.
267 android::base::unique_fd in_fd(OpenForRead(input_file));
268 if (out_fd != -1 && in_fd.get() != -1) {
269 if (CopyFile(in_fd.get(), out_fd)) {
270 return true;
271 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000272 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000273 }
274 return false;
275}
276
Nandana Duttd2f5f082019-01-18 17:13:52 +0000277static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000278 if (file.empty()) {
279 return false;
280 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000281 if (unlink(file.c_str())) {
282 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000283 return false;
284 }
285 return true;
286}
Nandana Dutt979388e2018-11-30 16:48:55 +0000287
Nikita Ioffea325a572019-05-16 19:49:47 +0100288int64_t GetModuleMetadataVersion() {
289 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
290 if (binder == nullptr) {
291 MYLOGE("Failed to retrieve package_native service");
292 return 0L;
293 }
294 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
295 std::string package_name;
296 auto status = package_service->getModuleMetadataPackageName(&package_name);
297 if (!status.isOk()) {
298 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
299 return 0L;
300 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100301 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100302 int64_t version_code;
303 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
304 &version_code);
305 if (!status.isOk()) {
306 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
307 return 0L;
308 }
309 return version_code;
310}
311
mhasank2d75c442020-06-11 15:05:25 -0700312static bool PathExists(const std::string& path) {
313 struct stat sb;
314 return stat(path.c_str(), &sb) == 0;
315}
316
317static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
318 if (input_file == output_file) {
319 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
320 output_file.c_str());
321 return false;
322 }
323 else if (PathExists(output_file)) {
324 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
325 return false;
326 }
327
328 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
329 android::base::unique_fd out_fd(OpenForWrite(output_file));
330 return CopyFileToFd(input_file, out_fd.get());
331}
332
Nandana Dutt979388e2018-11-30 16:48:55 +0000333} // namespace
334} // namespace os
335} // namespace android
336
Felipe Leme678727a2016-09-21 17:22:11 -0700337static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800338 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Rhed Jao6b1ea2d2020-07-21 17:58:41 +0800339 long dumpsysTimeoutMs = 0, int out_fd = STDOUT_FILENO) {
340 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs, out_fd);
341}
342static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
343 int out_fd) {
344 return ds.RunDumpsys(title, dumpsysArgs, Dumpstate::DEFAULT_DUMPSYS, 0, out_fd);
Felipe Leme678727a2016-09-21 17:22:11 -0700345}
346static int DumpFile(const std::string& title, const std::string& path) {
347 return ds.DumpFile(title, path);
348}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800349
Felipe Lemee844a9d2016-09-21 15:01:39 -0700350// Relative directory (inside the zip) for all files copied as-is into the bugreport.
351static const std::string ZIP_ROOT_DIR = "FS";
352
Vishnu Naire97d6122018-01-18 13:58:56 -0800353static const std::string kProtoPath = "proto/";
354static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700355static const std::string kDumpstateBoardFiles[] = {
356 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700357 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700358};
359static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
360
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700361static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700362static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700363
Felipe Lemef0292972016-11-22 13:57:05 -0800364static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
365
Narayan Kamath8f788292017-05-25 13:20:39 +0100366/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100367 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800368 * The returned vector is sorted by the mtimes of the dumps with descending
369 * order. If |limit_by_mtime| is set, the vector only contains files that
370 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100371 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700372static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
373 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700374 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100375 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
376
Narayan Kamathbd863722017-06-01 18:50:12 +0100377 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100378
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700379 if (dump_dir == nullptr) {
380 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700381 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700382 }
383
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700384 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100385 struct dirent* entry = nullptr;
386 while ((entry = readdir(dump_dir.get()))) {
387 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100388 continue;
389 }
390
Narayan Kamathbd863722017-06-01 18:50:12 +0100391 const std::string base_name(entry->d_name);
392 if (base_name.find(file_prefix) != 0) {
393 continue;
394 }
395
396 const std::string abs_path = dir_path + base_name;
397 android::base::unique_fd fd(
398 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
399 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700400 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100401 break;
402 }
403
404 struct stat st = {};
405 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700406 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100407 continue;
408 }
409
Narayan Kamath3f31b632018-02-22 19:42:36 +0000410 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100411 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100412 continue;
413 }
414
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700415 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700416 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800417 if (!dump_data.empty()) {
418 std::sort(dump_data.begin(), dump_data.end(),
419 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
420 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100421
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700422 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100423}
424
Narayan Kamathbd863722017-06-01 18:50:12 +0100425static bool AddDumps(const std::vector<DumpData>::const_iterator start,
426 const std::vector<DumpData>::const_iterator end,
427 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100428 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100429 for (auto it = start; it != end; ++it) {
430 const std::string& name = it->name;
431 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100432 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100433
434 // Seek to the beginning of the file before dumping any data. A given
435 // DumpData entry might be dumped multiple times in the report.
436 //
437 // For example, the most recent ANR entry is dumped to the body of the
438 // main entry and it also shows up as a separate entry in the bugreport
439 // ZIP file.
440 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
441 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
442 strerror(errno));
443 }
444
Narayan Kamath8f788292017-05-25 13:20:39 +0100445 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800446 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100447 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100448 }
449 } else {
450 dump_file_from_fd(type_name, name.c_str(), fd);
451 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100452 }
453
454 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700455}
456
Felipe Leme635ca312016-01-05 14:23:02 -0800457// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700458void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800459 char path[PATH_MAX];
460
461 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
462 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700463 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800464 char linkname[PATH_MAX];
465 ssize_t r = readlink(path, linkname, PATH_MAX);
466 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800467 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800468 return;
469 }
470 linkname[r] = '\0';
471
472 if (mount_points.find(linkname) == mount_points.end()) {
473 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700474 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700475 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800476 mount_points.insert(linkname);
477 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800478 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800479 }
480 }
481}
482
483void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700484 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700485 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800486 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800487 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700488 for_each_pid(do_mountinfo, nullptr);
489 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800490}
491
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700492static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
493{
494 DIR *d;
495 struct dirent *de;
496 char path[PATH_MAX];
497
498 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700499 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700500 return;
501 }
502
503 while ((de = readdir(d))) {
504 if (de->d_type != DT_LNK) {
505 continue;
506 }
507 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700508 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700509 }
510
511 closedir(d);
512}
513
Mark Salyzyn326842f2015-04-30 09:49:41 -0700514static bool skip_not_stat(const char *path) {
515 static const char stat[] = "/stat";
516 size_t len = strlen(path);
517 if (path[len - 1] == '/') { /* Directory? */
518 return false;
519 }
520 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
521}
522
Felipe Leme4c2d6632016-09-28 14:32:00 -0700523static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800524 return false;
525}
526
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700527unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700528
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800529//
530// stat offsets
531// Name units description
532// ---- ----- -----------
533// read I/Os requests number of read I/Os processed
534#define __STAT_READ_IOS 0
535// read merges requests number of read I/Os merged with in-queue I/O
536#define __STAT_READ_MERGES 1
537// read sectors sectors number of sectors read
538#define __STAT_READ_SECTORS 2
539// read ticks milliseconds total wait time for read requests
540#define __STAT_READ_TICKS 3
541// write I/Os requests number of write I/Os processed
542#define __STAT_WRITE_IOS 4
543// write merges requests number of write I/Os merged with in-queue I/O
544#define __STAT_WRITE_MERGES 5
545// write sectors sectors number of sectors written
546#define __STAT_WRITE_SECTORS 6
547// write ticks milliseconds total wait time for write requests
548#define __STAT_WRITE_TICKS 7
549// in_flight requests number of I/Os currently in flight
550#define __STAT_IN_FLIGHT 8
551// io_ticks milliseconds total time this block device has been active
552#define __STAT_IO_TICKS 9
553// time_in_queue milliseconds total wait time for all requests
554#define __STAT_IN_QUEUE 10
555#define __STAT_NUMBER_FIELD 11
556//
557// read I/Os, write I/Os
558// =====================
559//
560// These values increment when an I/O request completes.
561//
562// read merges, write merges
563// =========================
564//
565// These values increment when an I/O request is merged with an
566// already-queued I/O request.
567//
568// read sectors, write sectors
569// ===========================
570//
571// These values count the number of sectors read from or written to this
572// block device. The "sectors" in question are the standard UNIX 512-byte
573// sectors, not any device- or filesystem-specific block size. The
574// counters are incremented when the I/O completes.
575#define SECTOR_SIZE 512
576//
577// read ticks, write ticks
578// =======================
579//
580// These values count the number of milliseconds that I/O requests have
581// waited on this block device. If there are multiple I/O requests waiting,
582// these values will increase at a rate greater than 1000/second; for
583// example, if 60 read requests wait for an average of 30 ms, the read_ticks
584// field will increase by 60*30 = 1800.
585//
586// in_flight
587// =========
588//
589// This value counts the number of I/O requests that have been issued to
590// the device driver but have not yet completed. It does not include I/O
591// requests that are in the queue but not yet issued to the device driver.
592//
593// io_ticks
594// ========
595//
596// This value counts the number of milliseconds during which the device has
597// had I/O requests queued.
598//
599// time_in_queue
600// =============
601//
602// This value counts the number of milliseconds that I/O requests have waited
603// on this block device. If there are multiple I/O requests waiting, this
604// value will increase as the product of the number of milliseconds times the
605// number of requests waiting (see "read ticks" above for an example).
606#define S_TO_MS 1000
607//
608
Mark Salyzyn326842f2015-04-30 09:49:41 -0700609static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800610 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700611 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700612 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700613 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700614 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700615 getline(&buffer, &i, fp);
616 fclose(fp);
617 if (!buffer) {
618 return -errno;
619 }
620 i = strlen(buffer);
621 while ((i > 0) && (buffer[i - 1] == '\n')) {
622 buffer[--i] = '\0';
623 }
624 if (!*buffer) {
625 free(buffer);
626 return 0;
627 }
628 z = true;
629 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700631 if (fields[i] != 0) {
632 z = false;
633 }
634 }
635 if (z) { /* never accessed */
636 free(buffer);
637 return 0;
638 }
639
Wei Wang509bb5d2017-06-09 14:42:12 -0700640 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
641 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700642 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700643
644 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
645 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
646 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700647 free(buffer);
648
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800649 if (fields[__STAT_IO_TICKS]) {
650 unsigned long read_perf = 0;
651 unsigned long read_ios = 0;
652 if (fields[__STAT_READ_TICKS]) {
653 unsigned long long divisor = fields[__STAT_READ_TICKS]
654 * fields[__STAT_IO_TICKS];
655 read_perf = ((unsigned long long)SECTOR_SIZE
656 * fields[__STAT_READ_SECTORS]
657 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
658 / divisor;
659 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
660 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
661 / divisor;
662 }
663
664 unsigned long write_perf = 0;
665 unsigned long write_ios = 0;
666 if (fields[__STAT_WRITE_TICKS]) {
667 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
668 * fields[__STAT_IO_TICKS];
669 write_perf = ((unsigned long long)SECTOR_SIZE
670 * fields[__STAT_WRITE_SECTORS]
671 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
672 / divisor;
673 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
674 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
675 / divisor;
676 }
677
678 unsigned queue = (fields[__STAT_IN_QUEUE]
679 + (fields[__STAT_IO_TICKS] >> 1))
680 / fields[__STAT_IO_TICKS];
681
682 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700683 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 -0800684 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700685 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 -0800686 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800687 }
688
689 /* bugreport timeout factor adjustment */
690 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
691 worst_write_perf = write_perf;
692 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700693 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700694 return 0;
695}
696
Yao Chenbe3bbc12018-01-17 16:31:10 -0800697static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
698
Tom Cherryf4472f32020-08-05 09:31:17 -0700699// Returns the actual readable size of the given buffer or -1 on error.
700static long logcat_buffer_readable_size(const std::string& buffer) {
701 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
702 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
703 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
704
705 return android_logger_get_log_readable_size(logger);
706}
707
708// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800709static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
710 unsigned long timeout_ms = 0;
711 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700712 long readable_size = logcat_buffer_readable_size(buffer);
713 if (readable_size > 0) {
714 // Engineering margin is ten-fold our guess.
715 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
716 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800717 }
718 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700719}
720
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800721// Opens a socket and returns its file descriptor.
722static int open_socket(const char* service);
723
Nandana Duttd2f5f082019-01-18 17:13:52 +0000724Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
725}
726
727android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
728 std::lock_guard<std::mutex> lock(lock_);
729 result_ = APPROVED;
730 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800731
732 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
733 // consent is granted.
734 if (ds.options_->is_screenshot_copied) {
735 return android::binder::Status::ok();
736 }
737
738 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
739 !ds.do_early_screenshot_) {
740 return android::binder::Status::ok();
741 }
742
743 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
744 ds.options_->screenshot_fd.get());
745 ds.options_->is_screenshot_copied = copy_succeeded;
746 if (copy_succeeded) {
747 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
748 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000749 return android::binder::Status::ok();
750}
751
752android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
753 std::lock_guard<std::mutex> lock(lock_);
754 result_ = DENIED;
755 MYLOGW("User denied consent to share bugreport\n");
756 return android::binder::Status::ok();
757}
758
759UserConsentResult Dumpstate::ConsentCallback::getResult() {
760 std::lock_guard<std::mutex> lock(lock_);
761 return result_;
762}
763
764uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800765 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000766}
767
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700768void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700769 std::string build, fingerprint, radio, bootloader, network;
770 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700771
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700772 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
773 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700774 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
775 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
776 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700777 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700778
Felipe Lemed8b94e52016-12-08 10:21:44 -0800779 printf("========================================================\n");
780 printf("== dumpstate: %s\n", date);
781 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700782
Felipe Lemed8b94e52016-12-08 10:21:44 -0800783 printf("\n");
784 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700785 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800786 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
787 printf("Bootloader: %s\n", bootloader.c_str());
788 printf("Radio: %s\n", radio.c_str());
789 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100790 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
791 if (module_metadata_version != 0) {
792 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
793 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700794
Felipe Lemed8b94e52016-12-08 10:21:44 -0800795 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800796 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800797 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800798 printf("Uptime: ");
799 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
800 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800801 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao1c855122020-07-16 17:37:39 +0800802 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
803 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
804 options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800805 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800806}
807
Felipe Leme24b66ee2016-06-16 10:55:26 -0700808// List of file extensions that can cause a zip file attachment to be rejected by some email
809// service providers.
810static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
811 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
812 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
813 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
814};
815
Vishnu Naire97d6122018-01-18 13:58:56 -0800816status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
817 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700818 if (!IsZipping()) {
819 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
820 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800821 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800822 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700823 std::string valid_name = entry_name;
824
825 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700826 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700827 if (idx != std::string::npos) {
828 std::string extension = entry_name.substr(idx);
829 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
830 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
831 valid_name = entry_name + ".renamed";
832 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
833 }
834 }
835
Felipe Leme6fe9db62016-02-12 09:04:16 -0800836 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
837 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700838 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
839 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700840 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700841 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700842 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800843 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800844 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000845 bool finished_entry = false;
846 auto finish_entry = [this, &finished_entry] {
847 if (!finished_entry) {
848 // This should only be called when we're going to return an earlier error,
849 // which would've been logged. This may imply the file is already corrupt
850 // and any further logging from FinishEntry is more likely to mislead than
851 // not.
852 this->zip_writer_->FinishEntry();
853 }
854 };
855 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800856 auto start = std::chrono::steady_clock::now();
857 auto end = start + timeout;
858 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800859
Felipe Leme770410d2016-01-26 17:07:14 -0800860 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800861 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800862 if (timeout.count() > 0) {
863 // lambda to recalculate the timeout.
864 auto time_left_ms = [end]() {
865 auto now = std::chrono::steady_clock::now();
866 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
867 return std::max(diff.count(), 0LL);
868 };
869
870 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
871 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000872 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
873 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800874 return -errno;
875 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000876 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800877 entry_name.c_str(), strerror(errno), timeout.count());
878 return TIMED_OUT;
879 }
880 }
881
Zach Riggle22200402016-08-18 01:01:24 -0400882 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800883 if (bytes_read == 0) {
884 break;
885 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800886 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800887 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800888 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700889 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800890 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700891 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800892 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800893 }
894 }
895
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700896 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000897 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700898 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700899 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800900 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800901 }
902
Vishnu Naire97d6122018-01-18 13:58:56 -0800903 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800904}
905
Felipe Leme1d486fe2016-10-14 18:06:47 -0700906bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
907 android::base::unique_fd fd(
908 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700909 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800910 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800911 return false;
912 }
913
Vishnu Naire97d6122018-01-18 13:58:56 -0800914 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800915}
916
917/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700918static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800919 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800920}
921
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922void Dumpstate::AddDir(const std::string& dir, bool recursive) {
923 if (!IsZipping()) {
924 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800925 return;
926 }
Felipe Leme678727a2016-09-21 17:22:11 -0700927 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800928 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700929 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800930}
931
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
933 if (!IsZipping()) {
934 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
935 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800936 return false;
937 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800938 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700939 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700940 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700941 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700942 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800943 return false;
944 }
945
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700946 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700947 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700948 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700949 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800950 return false;
951 }
952
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700953 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700954 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700955 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800956 return false;
957 }
958
959 return true;
960}
961
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800962static void DoKmsg() {
963 struct stat st;
964 if (!stat(PSTORE_LAST_KMSG, &st)) {
965 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
966 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
967 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
968 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
969 } else {
970 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
971 DumpFile("LAST KMSG", "/proc/last_kmsg");
972 }
973}
974
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800975static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800976 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800977 RunCommand(
978 "KERNEL LOG",
979 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
980 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
981}
982
Nandana Duttdb379fa2019-10-09 16:54:41 +0100983static void DoSystemLogcat(time_t since) {
984 char since_str[80];
985 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
986
987 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
988 RunCommand("SYSTEM LOG",
989 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
990 since_str},
991 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
992}
993
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800994static void DoRadioLogcat() {
995 unsigned long timeout_ms = logcat_timeout({"radio"});
996 RunCommand(
997 "RADIO LOG",
998 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
999 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
1000}
1001
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001002static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -08001003 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001004 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
1005 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -08001006 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +01001007 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001008 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1009 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001010 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001011 RunCommand(
1012 "EVENT LOG",
1013 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001014 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001015 timeout_ms = logcat_timeout({"stats"});
1016 RunCommand(
1017 "STATS LOG",
1018 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001019 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001020 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001021
1022 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1023
1024 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001025 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1026 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001027}
1028
Mike Ma5c267872019-08-21 11:31:34 -07001029static void DumpIncidentReport() {
1030 if (!ds.IsZipping()) {
1031 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1032 return;
1033 }
Mike Ma5c267872019-08-21 11:31:34 -07001034 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1035 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1036 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1037 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1038 if (fd < 0) {
1039 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1040 return;
1041 }
1042 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1043 bool empty = 0 == lseek(fd, 0, SEEK_END);
1044 if (!empty) {
1045 // Use a different name from "incident.proto"
1046 // /proto/incident.proto is reserved for incident service dump
1047 // i.e. metadata for debugging.
Rhed Jao4875aa62020-07-20 17:46:29 +08001048 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1049 path);
1050 } else {
1051 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001052 }
Mike Ma5c267872019-08-21 11:31:34 -07001053}
1054
Sunny Goyal35949782019-11-19 15:54:36 -08001055static void DumpVisibleWindowViews() {
1056 if (!ds.IsZipping()) {
1057 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1058 return;
1059 }
1060 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1061 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1062 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1063 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1064 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1065 if (fd < 0) {
1066 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1067 return;
1068 }
1069 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1070 CommandOptions::WithTimeout(120).Build());
1071 bool empty = 0 == lseek(fd, 0, SEEK_END);
1072 if (!empty) {
1073 ds.AddZipEntry("visible_windows.zip", path);
1074 } else {
1075 MYLOGW("Failed to dump visible windows\n");
1076 }
1077 unlink(path.c_str());
1078}
1079
Jayachandran Ca94c7172017-06-10 15:08:12 -07001080static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001081 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1082 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001083 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001084 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001085 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1086 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1087 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1088 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001089}
1090
David Andersond9ba4752018-12-11 18:26:59 -08001091static void DumpDynamicPartitionInfo() {
1092 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1093 return;
1094 }
1095
1096 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001097 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001098}
1099
Narayan Kamath8f788292017-05-25 13:20:39 +01001100static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1101 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1102 anr_traces_dir.c_str());
1103
1104 // If we're here, dump_traces_path will always be a temporary file
1105 // (created with mkostemp or similar) that contains dumps taken earlier
1106 // on in the process.
1107 if (dump_traces_path != nullptr) {
1108 if (add_to_zip) {
1109 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1110 } else {
1111 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1112 dump_traces_path);
1113 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1114 }
1115
1116 const int ret = unlink(dump_traces_path);
1117 if (ret == -1) {
1118 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1119 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001120 }
1121 }
1122
Narayan Kamathbd863722017-06-01 18:50:12 +01001123 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001124 if (ds.anr_data_.size() > 0) {
1125 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001126 "VM TRACES AT LAST ANR", add_to_zip);
1127
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001128 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1129 // it will be present in the body of the main entry if |add_to_zip| == false.
1130 //
1131 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001132 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001133 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001134 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001135 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1136 }
1137}
1138
1139static void AddAnrTraceFiles() {
1140 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1141
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001142 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001143
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001144 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001145
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001146 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1147
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001148 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001149 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001150 int i = 0;
1151 while (true) {
1152 const std::string slow_trace_path =
1153 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1154 if (stat(slow_trace_path.c_str(), &st)) {
1155 // No traces file at this index, done with the files.
1156 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001157 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001158 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1159 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001160 }
1161}
1162
Wei Wang509bb5d2017-06-09 14:42:12 -07001163static void DumpBlockStatFiles() {
1164 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001165
Wei Wang1dc1ef52017-06-12 11:28:37 -07001166 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1167
1168 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001169 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1170 return;
1171 }
1172
1173 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001174 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001175 if ((d->d_name[0] == '.')
1176 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1177 || (d->d_name[1] == '\0'))) {
1178 continue;
1179 }
1180 const std::string new_path =
1181 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1182 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1183 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1184 printf("\n");
1185 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001186 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001187}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001188
1189static void DumpPacketStats() {
1190 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1191 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1192 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1193 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1194 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1195}
1196
1197static void DumpIpAddrAndRules() {
1198 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1199 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1200 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1201 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1202 RunCommand("IP RULES", {"ip", "rule", "show"});
1203 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1204}
1205
Nandana Dutt5c390032019-03-12 10:52:56 +00001206static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1207 std::chrono::milliseconds timeout,
1208 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001209 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001210 sp<android::IServiceManager> sm = defaultServiceManager();
1211 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001212 Vector<String16> args;
1213 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001214 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1215 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001216 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001217 std::string path(title);
1218 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001219 size_t bytes_written = 0;
Steven Moreland5a30d342019-10-08 13:53:28 -07001220 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001221 if (status == OK) {
1222 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1223 std::chrono::duration<double> elapsed_seconds;
1224 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1225 /* as_proto = */ false, elapsed_seconds, bytes_written);
Vishnu Naire97d6122018-01-18 13:58:56 -08001226 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1227 bool dump_complete = (status == OK);
1228 dumpsys.stopDumpThread(dump_complete);
1229 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001230
1231 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1232 std::chrono::steady_clock::now() - start);
1233 if (elapsed_duration > timeout) {
1234 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1235 elapsed_duration.count());
1236 break;
1237 }
1238 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001239 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001240}
1241
Vishnu Nair64afc022018-02-01 15:29:34 -08001242static void RunDumpsysText(const std::string& title, int priority,
1243 std::chrono::milliseconds timeout,
1244 std::chrono::milliseconds service_timeout) {
1245 DurationReporter duration_reporter(title);
1246 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1247 fsync(STDOUT_FILENO);
1248 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1249}
1250
1251/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001252static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1253 std::chrono::milliseconds timeout,
1254 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001255 DurationReporter duration_reporter(title);
1256 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1257 fsync(STDOUT_FILENO);
1258 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1259 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001260
1261 RETURN_IF_USER_DENIED_CONSENT();
1262
1263 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1264 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001265}
1266
Nandana Dutt5c390032019-03-12 10:52:56 +00001267static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1268 std::chrono::milliseconds timeout,
1269 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001270 if (!ds.IsZipping()) {
1271 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001272 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001273 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001274 sp<android::IServiceManager> sm = defaultServiceManager();
1275 Dumpsys dumpsys(sm.get());
1276 Vector<String16> args;
1277 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1278 DurationReporter duration_reporter(title);
1279
1280 auto start = std::chrono::steady_clock::now();
1281 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1282 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001283 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001284 std::string path(kProtoPath);
1285 path.append(String8(service).c_str());
1286 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1287 path.append("_CRITICAL");
1288 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1289 path.append("_HIGH");
1290 }
1291 path.append(kProtoExt);
Steven Moreland5a30d342019-10-08 13:53:28 -07001292 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001293 if (status == OK) {
1294 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1295 bool dumpTerminated = (status == OK);
1296 dumpsys.stopDumpThread(dumpTerminated);
1297 }
1298 ZipWriter::FileEntry file_entry;
1299 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001300
1301 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1302 std::chrono::steady_clock::now() - start);
1303 if (elapsed_duration > timeout) {
1304 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1305 elapsed_duration.count());
1306 break;
1307 }
1308 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001309 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001310}
1311
Nandana Dutta7db6342018-11-21 14:53:34 +00001312// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001313static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001314 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1315 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001316
1317 RETURN_IF_USER_DENIED_CONSENT();
1318
1319 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1320 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001321}
1322
1323// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001324static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001325 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1326 // high priority. Reduce timeout once they are able to dump in a shorter time or
1327 // moved to a parallel task.
1328 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1329 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001330
1331 RETURN_IF_USER_DENIED_CONSENT();
1332
1333 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1334 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001335}
1336
1337// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001338static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001339 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001340
1341 RETURN_IF_USER_DENIED_CONSENT();
1342
1343 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1344 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001345}
1346
Rhed Jao4875aa62020-07-20 17:46:29 +08001347/*
1348 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1349 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1350 * if it's not running in the parallel task.
1351 */
1352static void DumpHals(int out_fd = STDOUT_FILENO) {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001353 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001354 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Steven Moreland9de8a1f2020-09-23 17:26:33 +00001355 CommandOptions::WithTimeout(60).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001356 return;
1357 }
Yifan Hong30528a22020-08-07 18:24:06 -07001358 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao4875aa62020-07-20 17:46:29 +08001359 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1360 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001361
Steven Moreland44cd9482018-01-04 16:24:13 -08001362 using android::hidl::manager::V1_0::IServiceManager;
1363 using android::hardware::defaultServiceManager;
1364
1365 sp<IServiceManager> sm = defaultServiceManager();
1366 if (sm == nullptr) {
1367 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1368 return;
1369 }
1370
1371 auto ret = sm->list([&](const auto& interfaces) {
1372 for (const std::string& interface : interfaces) {
1373 std::string cleanName = interface;
1374 std::replace_if(cleanName.begin(),
1375 cleanName.end(),
1376 [](char c) {
1377 return !isalnum(c) &&
1378 std::string("@-_:.").find(c) == std::string::npos;
1379 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001380 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001381
Rhed Jao4875aa62020-07-20 17:46:29 +08001382 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001383 {
1384 auto fd = android::base::unique_fd(
1385 TEMP_FAILURE_RETRY(open(path.c_str(),
1386 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1387 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1388 if (fd < 0) {
1389 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1390 continue;
1391 }
1392 RunCommandToFd(fd,
1393 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001394 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001395 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1396
Rhed Jao4875aa62020-07-20 17:46:29 +08001397 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001398 }
Rhed Jao4875aa62020-07-20 17:46:29 +08001399 if (!empty) {
1400 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1401 path);
1402 } else {
1403 unlink(path.c_str());
1404 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001405 }
1406 });
1407
1408 if (!ret.isOk()) {
1409 MYLOGE("Could not list hals from hwservicemanager.\n");
1410 }
1411}
1412
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001413static void DumpExternalFragmentationInfo() {
1414 struct stat st;
1415 if (stat("/proc/buddyinfo", &st) != 0) {
1416 MYLOGE("Unable to dump external fragmentation info\n");
1417 return;
1418 }
1419
1420 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1421 std::ifstream ifs("/proc/buddyinfo");
1422 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1423 for (std::string line; std::getline(ifs, line);) {
1424 std::smatch match_results;
1425 if (std::regex_match(line, match_results, unusable_index_regex)) {
1426 std::stringstream free_pages(std::string{match_results[3]});
1427 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1428 std::istream_iterator<int>());
1429
1430 int total_free_pages = 0;
1431 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1432 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1433 }
1434
1435 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1436 match_results[2].str().c_str());
1437
1438 int usable_free_pages = total_free_pages;
1439 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1440 auto unusable_index = (total_free_pages - usable_free_pages) /
1441 static_cast<double>(total_free_pages);
1442 printf(" %5.3f", unusable_index);
1443 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1444 }
1445
1446 printf("\n");
1447 }
1448 }
1449 printf("\n");
1450}
1451
mhasankd451a472020-05-26 18:02:39 -07001452static void DumpstateLimitedOnly() {
1453 // Trimmed-down version of dumpstate to only include a whitelisted
1454 // set of logs (system log, event log, and system server / system app
1455 // crashes, and networking logs). See b/136273873 and b/138459828
1456 // for context.
1457 DurationReporter duration_reporter("DUMPSTATE");
1458 unsigned long timeout_ms;
1459 // calculate timeout
1460 timeout_ms = logcat_timeout({"main", "system", "crash"});
1461 RunCommand("SYSTEM LOG",
1462 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1463 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1464 timeout_ms = logcat_timeout({"events"});
1465 RunCommand(
1466 "EVENT LOG",
1467 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1468 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1469
1470 printf("========================================================\n");
1471 printf("== Networking Service\n");
1472 printf("========================================================\n");
1473
1474 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1475 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hugo Benichiaa162682020-10-30 23:28:56 +09001476 RunDumpsys("DUMPSYS CONNECTIVITY REQUESTS", {"connectivity", "requests"},
1477 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
mhasankd451a472020-05-26 18:02:39 -07001478
1479 printf("========================================================\n");
1480 printf("== Dropbox crashes\n");
1481 printf("========================================================\n");
1482
1483 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1484 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1485
1486 printf("========================================================\n");
1487 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1488 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1489 printf("========================================================\n");
1490 printf("== dumpstate: done (id %d)\n", ds.id_);
1491 printf("========================================================\n");
1492}
1493
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001494/*
1495 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1496 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1497 * if it's not running in the parallel task.
1498 */
1499static void DumpCheckins(int out_fd = STDOUT_FILENO) {
1500 dprintf(out_fd, "========================================================\n");
1501 dprintf(out_fd, "== Checkins\n");
1502 dprintf(out_fd, "========================================================\n");
1503
1504 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}, out_fd);
1505 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}, out_fd);
1506 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}, out_fd);
1507 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}, out_fd);
1508 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}, out_fd);
1509 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}, out_fd);
1510}
1511
1512/*
1513 * Runs dumpsys on activity service to dump all application activities, services
1514 * and providers in the device.
1515 *
1516 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1517 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1518 * if it's not running in the parallel task.
1519 */
1520static void DumpAppInfos(int out_fd = STDOUT_FILENO) {
1521 dprintf(out_fd, "========================================================\n");
1522 dprintf(out_fd, "== Running Application Activities\n");
1523 dprintf(out_fd, "========================================================\n");
1524
1525 // The following dumpsys internally collects output from running apps, so it can take a long
1526 // time. So let's extend the timeout.
1527
1528 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1529
1530 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1531
1532 dprintf(out_fd, "========================================================\n");
1533 dprintf(out_fd, "== Running Application Services (platform)\n");
1534 dprintf(out_fd, "========================================================\n");
1535
1536 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
1537 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1538
1539 dprintf(out_fd, "========================================================\n");
1540 dprintf(out_fd, "== Running Application Services (non-platform)\n");
1541 dprintf(out_fd, "========================================================\n");
1542
1543 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1544 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1545
1546 dprintf(out_fd, "========================================================\n");
1547 dprintf(out_fd, "== Running Application Providers (platform)\n");
1548 dprintf(out_fd, "========================================================\n");
1549
1550 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1551 DUMPSYS_COMPONENTS_OPTIONS, out_fd);
1552
1553 dprintf(out_fd, "========================================================\n");
1554 dprintf(out_fd, "== Running Application Providers (non-platform)\n");
1555 dprintf(out_fd, "========================================================\n");
1556
1557 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1558 DUMPSYS_COMPONENTS_OPTIONS, 0, out_fd);
1559}
1560
Nandana Dutt5c390032019-03-12 10:52:56 +00001561// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1562// via the consent they are shown. Ignores other errors that occur while running various
1563// commands. The consent checking is currently done around long running tasks, which happen to
1564// be distributed fairly evenly throughout the function.
1565static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001566 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001567
Rhed Jao4875aa62020-07-20 17:46:29 +08001568 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1569 if (ds.dump_pool_) {
1570 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1571 // drop root user. Restarts it with two threads for the parallel run.
1572 ds.dump_pool_->start(/* thread_counts = */2);
1573
1574 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1575 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1576 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001577 ds.dump_pool_->enqueueTaskWithFd(DUMP_CHECKINS_TASK, &DumpCheckins, _1);
Rhed Jao4875aa62020-07-20 17:46:29 +08001578 }
1579
Nandana Dutt5c390032019-03-12 10:52:56 +00001580 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1581 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1582 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001583 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001584 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001585 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001586 DumpFile("MEMORY INFO", "/proc/meminfo");
1587 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001588 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001589
1590 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1591
Sunny Goyal35949782019-11-19 15:54:36 -08001592 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1593
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001594 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1595 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1596 DumpFile("SLAB INFO", "/proc/slabinfo");
1597 DumpFile("ZONEINFO", "/proc/zoneinfo");
1598 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1599 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001600 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001601
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001602 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1603 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001604
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001605 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001606 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001607
1608 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1609 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001610
Rhed Jao4875aa62020-07-20 17:46:29 +08001611 if (ds.dump_pool_) {
1612 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1613 } else {
1614 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1615 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001616
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001617 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001618 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001619 struct stat s;
1620 if (stat("/proc/modules", &s) != 0) {
1621 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1622 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001623 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001624 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001625
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001626 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001627 DoKernelLogcat();
1628 } else {
1629 do_dmesg();
1630 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001631
Felipe Lemef0292972016-11-22 13:57:05 -08001632 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001633
1634 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1635
Jeff Brown1dc94e32014-09-11 14:15:27 -07001636 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001637 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001638
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001639 /* Dump Bluetooth HCI logs */
1640 ds.AddDir("/data/misc/bluetooth/logs", true);
Jack Yu5a6b2e22020-08-14 18:13:35 +08001641 /* Dump Nfc NCI logs */
1642 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001643
Paul Chang0d2aad72020-02-13 20:04:03 +08001644 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001645 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001646 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001647 }
1648
Felipe Lemee184f662016-10-27 10:04:47 -07001649 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001650
Narayan Kamath8f788292017-05-25 13:20:39 +01001651 // NOTE: tombstones are always added as separate entries in the zip archive
1652 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001653 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001654 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001655 if (!tombstones_dumped) {
1656 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001657 }
1658
Jayachandran Ca94c7172017-06-10 15:08:12 -07001659 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001660
Chenbo Feng276a3b62018-08-07 11:44:49 -07001661 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1662
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001663 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001664
Jayachandran Ca94c7172017-06-10 15:08:12 -07001665 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001666
1667 dump_route_tables();
1668
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001669 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1670 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1671 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001672
Nandana Dutt5c390032019-03-12 10:52:56 +00001673 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001674
Elliott Hughes23ccc622017-02-28 10:14:22 -08001675 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001676
Jin Qianf334d662017-10-10 14:41:37 -07001677 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001678
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001679 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001680
Colin Crossf45fa6b2012-03-26 12:38:26 -07001681 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001682 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1683 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1684
1685 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1686 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1687 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1688 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1689 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001690
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001691 /* Add window and surface trace files. */
1692 if (!PropertiesHelper::IsUserBuild()) {
1693 ds.AddDir(WMTRACE_DATA_DIR, false);
1694 }
1695
Yifan Hongcba0a4f2020-02-08 16:52:02 -08001696 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1697
Rhed Jao4875aa62020-07-20 17:46:29 +08001698 if (ds.dump_pool_) {
1699 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1700 } else {
1701 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1702 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001703
Steven Moreland7440ddb2016-12-15 16:13:39 -08001704 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001705 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1706 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001707 // su does not exist on user builds, so try running without it.
1708 // This way any implementations of vril-dump that do not require
1709 // root can run on user builds.
1710 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001711 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001712 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001713 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001715 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001716 }
1717
Felipe Lemed8b94e52016-12-08 10:21:44 -08001718 printf("========================================================\n");
1719 printf("== Android Framework Services\n");
1720 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001721
Nandana Dutt5c390032019-03-12 10:52:56 +00001722 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001723
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08001724 if (ds.dump_pool_) {
1725 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_CHECKINS_TASK, ds.dump_pool_);
1726 } else {
1727 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_CHECKINS_TASK, DumpCheckins);
1728 }
Dianne Hackborn02bea972013-06-26 18:59:09 -07001729
Rhed Jaoc5f7ec32020-12-22 22:11:08 +08001730 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpAppInfos);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001731
Adrian Roos8b397ab2017-04-04 16:35:44 -07001732 printf("========================================================\n");
1733 printf("== Dropbox crashes\n");
1734 printf("========================================================\n");
1735
1736 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1737 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1738
Felipe Lemed8b94e52016-12-08 10:21:44 -08001739 printf("========================================================\n");
1740 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1741 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1742 printf("========================================================\n");
1743 printf("== dumpstate: done (id %d)\n", ds.id_);
1744 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001745
1746 printf("========================================================\n");
1747 printf("== Obtaining statsd metadata\n");
1748 printf("========================================================\n");
1749 // This differs from the usual dumpsys stats, which is the stats report data.
1750 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001751
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001752 // Add linker configuration directory
1753 ds.AddDir(LINKERCONFIG_DIR, true);
1754
Rhed Jao4875aa62020-07-20 17:46:29 +08001755 if (ds.dump_pool_) {
1756 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1757 } else {
1758 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1759 DumpIncidentReport);
1760 }
Mike Ma5c267872019-08-21 11:31:34 -07001761
Nandana Dutt5c390032019-03-12 10:52:56 +00001762 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001763}
1764
Nandana Dutt5c390032019-03-12 10:52:56 +00001765/*
1766 * Dumps state for the default case; drops root after it's no longer necessary.
1767 *
1768 * Returns RunStatus::OK if everything went fine.
1769 * Returns RunStatus::ERROR if there was an error.
1770 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1771 * with the caller.
1772 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001773Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001774 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1775 // buffer.
1776 DoLogcat();
1777 // Capture timestamp after first logcat to use in next logcat
1778 time_t logcat_ts = time(nullptr);
1779
Nandana Dutt4be45d12018-09-26 15:04:23 +01001780 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao1c855122020-07-16 17:37:39 +08001781 if (dump_pool_) {
1782 RETURN_IF_USER_DENIED_CONSENT();
1783 // One thread is enough since we only need to enqueue DumpTraces here.
1784 dump_pool_->start(/* thread_counts = */1);
1785
1786 // DumpTraces takes long time, post it to the another thread in the
1787 // pool, if pool is available
1788 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1789 } else {
1790 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1791 &dump_traces_path);
1792 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001793
1794 /* Run some operations that require root. */
1795 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1796 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1797
1798 ds.AddDir(RECOVERY_DIR, true);
1799 ds.AddDir(RECOVERY_DATA_DIR, true);
1800 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1801 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1802 if (!PropertiesHelper::IsUserBuild()) {
1803 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1804 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravle78a0d842020-04-28 15:31:12 -07001805 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001806 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001807 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001808 add_mountinfo();
1809 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001810 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001811 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001812
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001813 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001814 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1815
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001816 // Dump IPsec stats. No keys are exposed here.
1817 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1818
Nandana Dutt4be45d12018-09-26 15:04:23 +01001819 // Run ss as root so we can see socket marks.
1820 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1821
1822 // Run iotop as root to show top 100 IO threads
1823 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1824
Erick Reyese68df822019-02-11 14:46:36 -08001825 // Gather shared memory buffer info if the product implements it
1826 struct stat st;
1827 if (!stat("/product/bin/dmabuf_dump", &st)) {
1828 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1829 }
1830
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001831 DumpFile("PSI cpu", "/proc/pressure/cpu");
1832 DumpFile("PSI memory", "/proc/pressure/memory");
1833 DumpFile("PSI io", "/proc/pressure/io");
1834
Rhed Jao1c855122020-07-16 17:37:39 +08001835 if (dump_pool_) {
1836 RETURN_IF_USER_DENIED_CONSENT();
1837 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1838
1839 // Current running thread in the pool is the root user also. Shutdown
1840 // the pool and restart later to ensure all threads in the pool could
1841 // drop the root user.
1842 dump_pool_->shutdown();
1843 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001844 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001845 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001846 }
1847
Nandana Dutt5c390032019-03-12 10:52:56 +00001848 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001849 Dumpstate::RunStatus status = dumpstate();
1850 // Capture logcat since the last time we did it.
1851 DoSystemLogcat(logcat_ts);
1852 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001853}
1854
Rhed Jaoa5de5752020-08-14 17:19:17 +08001855// Common states for telephony and wifi which are needed to be collected before
1856// dumpstate drop the root user.
1857static void DumpstateRadioAsRoot() {
1858 DumpIpTablesAsRoot();
1859 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1860}
1861
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001862// This method collects common dumpsys for telephony and wifi. Typically, wifi
1863// reports are fine to include all information, but telephony reports on user
1864// builds need to strip some content (see DumpstateTelephonyOnly).
1865static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001866 // We need to be picky about some stuff for telephony reports on user builds.
1867 if (!include_sensitive_info) {
1868 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1869 DoRadioLogcat();
1870 } else {
Rhed Jaoa5de5752020-08-14 17:19:17 +08001871 // DumpHals takes long time, post it to the another thread in the pool,
1872 // if pool is available.
1873 if (ds.dump_pool_) {
1874 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1875 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001876 // Contains various system properties and process startup info.
1877 do_dmesg();
1878 // Logs other than the radio buffer may contain package/component names and potential PII.
1879 DoLogcat();
1880 // Too broad for connectivity problems.
1881 DoKmsg();
Rhed Jaoa5de5752020-08-14 17:19:17 +08001882 // DumpHals contains unrelated hardware info (camera, NFC, biometrics, ...).
1883 if (ds.dump_pool_) {
1884 ds.dump_pool_->waitForTask(DUMP_HALS_TASK);
1885 } else {
1886 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
1887 }
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001888 }
1889
Jayachandran Ca94c7172017-06-10 15:08:12 -07001890 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001891 DumpIpAddrAndRules();
1892 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001893 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1894 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001895}
1896
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001897// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1898// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1899// for what can be included on user builds: all reported information MUST directly relate to
1900// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1901// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1902// names are not), and MUST NOT contain logs of user application traffic.
1903// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001904static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001905 DurationReporter duration_reporter("DUMPSTATE");
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001906
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001907 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001908
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001909 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001910
Rhed Jaoa5de5752020-08-14 17:19:17 +08001911 DumpstateRadioAsRoot();
1912 if (!DropRootUser()) {
1913 return;
1914 }
1915
1916 // Starts thread pool after the root user is dropped, and two additional threads
1917 // are created for DumpHals in the DumpstateRadioCommon and DumpstateBoard.
1918 if (ds.dump_pool_) {
1919 ds.dump_pool_->start(/*thread_counts =*/2);
1920
1921 // DumpstateBoard takes long time, post it to the another thread in the pool,
1922 // if pool is available.
1923 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1924 }
1925
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001926 DumpstateRadioCommon(include_sensitive_info);
1927
1928 if (include_sensitive_info) {
1929 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1930 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1931 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1932 // way.
1933 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1934 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001935
1936 printf("========================================================\n");
1937 printf("== Android Framework Services\n");
1938 printf("========================================================\n");
1939
Vishnu Nair652cc802017-11-30 15:18:30 -08001940 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1941 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001942 if (include_sensitive_info) {
1943 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1944 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1945 SEC_TO_MSEC(10));
1946 } else {
1947 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1948 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1949 // give a higher timeout as well.
1950 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1951 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1952 }
1953 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001954 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1955 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001956 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001957 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1958 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001959 if (include_sensitive_info) {
1960 // Contains raw IP addresses, omit from reports on user builds.
1961 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1962 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1963 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1964 SEC_TO_MSEC(10));
1965 // Contains package/component names, omit from reports on user builds.
1966 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1967 SEC_TO_MSEC(10));
1968 // Contains package names, but should be relatively simple to remove them (also contains
1969 // UIDs already), omit from reports on user builds.
1970 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1971 SEC_TO_MSEC(10));
1972 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001973
1974 printf("========================================================\n");
1975 printf("== Running Application Services\n");
1976 printf("========================================================\n");
1977
1978 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1979
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001980 if (include_sensitive_info) {
1981 printf("========================================================\n");
1982 printf("== Running Application Services (non-platform)\n");
1983 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001984
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001985 // Contains package/component names and potential PII, omit from reports on user builds.
1986 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1987 // carrier_config dumpsys instead.
1988 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1989 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001990
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001991 printf("========================================================\n");
1992 printf("== Checkins\n");
1993 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001994
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001995 // Contains package/component names, omit from reports on user builds.
1996 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1997 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001998
1999 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07002000 printf("== dumpstate: done (id %d)\n", ds.id_);
2001 printf("========================================================\n");
Rhed Jaoa5de5752020-08-14 17:19:17 +08002002
2003 if (ds.dump_pool_) {
2004 ds.dump_pool_->waitForTask(DUMP_BOARD_TASK);
2005 } else {
2006 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
2007 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07002008}
2009
mukesh agrawal253dad42018-01-23 21:59:59 -08002010// This method collects dumpsys for wifi debugging only
2011static void DumpstateWifiOnly() {
2012 DurationReporter duration_reporter("DUMPSTATE");
2013
Rhed Jaoa5de5752020-08-14 17:19:17 +08002014 DumpstateRadioAsRoot();
2015 if (!DropRootUser()) {
2016 return;
2017 }
2018
2019 // Starts thread pool after the root user is dropped. Only one additional
2020 // thread is needed for DumpHals in the DumpstateRadioCommon.
2021 if (ds.dump_pool_) {
2022 ds.dump_pool_->start(/*thread_counts =*/1);
2023 }
2024
mukesh agrawal253dad42018-01-23 21:59:59 -08002025 DumpstateRadioCommon();
2026
2027 printf("========================================================\n");
2028 printf("== Android Framework Services\n");
2029 printf("========================================================\n");
2030
2031 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
2032 SEC_TO_MSEC(10));
2033 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
2034 SEC_TO_MSEC(10));
2035
2036 printf("========================================================\n");
2037 printf("== dumpstate: done (id %d)\n", ds.id_);
2038 printf("========================================================\n");
2039}
2040
Nandana Duttcf419a72019-03-14 10:40:17 +00002041Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00002042 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
2043 const size_t buf_size = temp_file_pattern.length() + 1;
2044 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
2045 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
2046
2047 // Create a new, empty file to receive all trace dumps.
2048 //
2049 // TODO: This can be simplified once we remove support for the old style
2050 // dumps. We can have a file descriptor passed in to dump_traces instead
2051 // of creating a file, closing it and then reopening it again.
2052 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
2053 if (fd < 0) {
2054 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002055 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002056 }
2057
2058 // Nobody should have access to this temporary file except dumpstate, but we
2059 // temporarily grant 'read' to 'others' here because this file is created
2060 // when tombstoned is still running as root, but dumped after dropping. This
2061 // can go away once support for old style dumping has.
2062 const int chmod_ret = fchmod(fd, 0666);
2063 if (chmod_ret < 0) {
2064 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002065 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002066 }
2067
2068 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
2069 if (proc.get() == nullptr) {
2070 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00002071 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002072 }
2073
2074 // Number of times process dumping has timed out. If we encounter too many
2075 // failures, we'll give up.
2076 int timeout_failures = 0;
2077 bool dalvik_found = false;
2078
2079 const std::set<int> hal_pids = get_interesting_hal_pids();
2080
2081 struct dirent* d;
2082 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002083 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002084 int pid = atoi(d->d_name);
2085 if (pid <= 0) {
2086 continue;
2087 }
2088
2089 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2090 std::string exe;
2091 if (!android::base::Readlink(link_name, &exe)) {
2092 continue;
2093 }
2094
2095 bool is_java_process;
2096 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2097 // Don't bother dumping backtraces for the zygote.
2098 if (IsZygote(pid)) {
2099 continue;
2100 }
2101
2102 dalvik_found = true;
2103 is_java_process = true;
2104 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2105 is_java_process = false;
2106 } else {
2107 // Probably a native process we don't care about, continue.
2108 continue;
2109 }
2110
2111 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2112 if (timeout_failures == 3) {
2113 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2114 break;
2115 }
2116
2117 const uint64_t start = Nanotime();
2118 const int ret = dump_backtrace_to_file_timeout(
2119 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2120 is_java_process ? 5 : 20, fd);
2121
2122 if (ret == -1) {
2123 // For consistency, the header and footer to this message match those
2124 // dumped by debuggerd in the success case.
2125 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2126 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2127 dprintf(fd, "---- end %d ----", pid);
2128 timeout_failures++;
2129 continue;
2130 }
2131
2132 // We've successfully dumped stack traces, reset the failure count
2133 // and write a summary of the elapsed time to the file and continue with the
2134 // next process.
2135 timeout_failures = 0;
2136
2137 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2138 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2139 }
2140
2141 if (!dalvik_found) {
2142 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2143 }
2144
Nandana Duttcf419a72019-03-14 10:40:17 +00002145 *path = file_name_buf.release();
2146 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002147}
2148
Rhed Jao4875aa62020-07-20 17:46:29 +08002149void Dumpstate::DumpstateBoard(int out_fd) {
2150 dprintf(out_fd, "========================================================\n");
2151 dprintf(out_fd, "== Board\n");
2152 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002153
Felipe Leme6f674ae2016-11-18 17:10:33 -08002154 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002155 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002156 return;
2157 }
2158
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002159 std::vector<std::string> paths;
2160 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002161 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002162 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2163 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002164 remover.emplace_back(android::base::make_scope_guard(
2165 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002166 }
Jie Song9fbfad02017-06-20 16:29:42 -07002167
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002168 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2169 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002170 MYLOGE("No IDumpstateDevice implementation\n");
2171 return;
2172 }
2173
2174 using ScopedNativeHandle =
2175 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2176 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2177 [](native_handle_t* handle) {
2178 native_handle_close(handle);
2179 native_handle_delete(handle);
2180 });
2181 if (handle == nullptr) {
2182 MYLOGE("Could not create native_handle\n");
2183 return;
2184 }
2185
Nandana Dutt5c390032019-03-12 10:52:56 +00002186 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002187 for (size_t i = 0; i < paths.size(); i++) {
2188 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2189
2190 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2191 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2192 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2193 if (fd < 0) {
2194 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2195 return;
2196 }
2197 handle.get()->data[i] = fd.release();
2198 }
2199
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002200 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2201 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2202 // will kill the HAL and grab whatever it dumped in time.
2203 constexpr size_t timeout_sec = 30;
2204 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2205 // implement just 1.0.
2206 const char* descriptor_to_kill;
2207 using DumpstateBoardTask = std::packaged_task<bool()>;
2208 DumpstateBoardTask dumpstate_board_task;
2209 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2210 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2211 if (dumpstate_device_1_1 != nullptr) {
2212 MYLOGI("Using IDumpstateDevice v1.1");
2213 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2214 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2215 ::android::hardware::Return<DumpstateStatus> status =
2216 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2217 SEC_TO_MSEC(timeout_sec));
2218 if (!status.isOk()) {
2219 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2220 return false;
2221 } else if (status != DumpstateStatus::OK) {
2222 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2223 return false;
2224 }
2225 return true;
2226 });
2227 } else {
2228 MYLOGI("Using IDumpstateDevice v1.0");
2229 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2230 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2231 ::android::hardware::Return<void> status =
2232 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002233 if (!status.isOk()) {
2234 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002235 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002236 }
Wei Wang587eac92018-04-05 12:17:20 -07002237 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002238 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002239 }
2240 auto result = dumpstate_board_task.get_future();
2241 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002242
Wei Wang587eac92018-04-05 12:17:20 -07002243 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2244 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002245 if (!android::base::SetProperty(
2246 "ctl.interface_restart",
2247 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002248 MYLOGE("Couldn't restart dumpstate HAL\n");
2249 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002250 }
Wei Wang587eac92018-04-05 12:17:20 -07002251 // Wait some time for init to kill dumpstate vendor HAL
2252 constexpr size_t killing_timeout_sec = 10;
2253 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2254 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2255 "there might be racing in content\n", killing_timeout_sec);
2256 }
2257
2258 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2259 for (size_t i = 0; i < paths.size(); i++) {
2260 struct stat s;
2261 if (fstat(handle.get()->data[i], &s) == -1) {
2262 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2263 strerror(errno));
2264 file_sizes[i] = -1;
2265 continue;
2266 }
2267 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002268 }
2269
2270 for (size_t i = 0; i < paths.size(); i++) {
2271 if (file_sizes[i] == -1) {
2272 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002273 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002274 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002275 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002276 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002277 }
Rhed Jao4875aa62020-07-20 17:46:29 +08002278 remover[i].Disable();
2279 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2280 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002281 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002282}
2283
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002284static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002285 fprintf(stderr,
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002286 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-p] "
2287 "[-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002288 " -h: display this help message\n"
2289 " -b: play sound file instead of vibrate, at beginning of job\n"
2290 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002291 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002292 " -p: capture screenshot to filename.png\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002293 " -s: write zipped file to control socket (for init)\n"
2294 " -S: write file location to control socket (for init)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002295 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002296 " -P: send broadcast when started and do progress updates\n"
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002297 " -R: take bugreport in remote mode (shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002298 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002299 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002300 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002301}
2302
Wei Liuf87959e2016-08-26 14:51:42 -07002303static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002304 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002305}
2306
Felipe Leme1d486fe2016-10-14 18:06:47 -07002307bool Dumpstate::FinishZipFile() {
Rhed Jao4875aa62020-07-20 17:46:29 +08002308 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2309 if (zip_entry_tasks_) {
2310 zip_entry_tasks_->run(/* do_cancel = */false);
2311 }
2312
Felipe Leme9a523ae2016-10-20 15:10:33 -07002313 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002314 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002315 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002316 // Final timestamp
2317 char date[80];
2318 time_t the_real_now_please_stand_up = time(nullptr);
2319 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002320 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002321 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002322
Felipe Leme9a523ae2016-10-20 15:10:33 -07002323 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002324 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002325 return false;
2326 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002327 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002328 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002329 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002330 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002331
Felipe Leme0f3fb202016-06-10 17:10:53 -07002332 // Add log file (which contains stderr output) to zip...
2333 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002334 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002335 MYLOGE("Failed to add dumpstate log to .zip file\n");
2336 return false;
2337 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002338 // TODO: Should truncate the existing file.
2339 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002340 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2341 return false;
2342 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002343 fprintf(stderr, "\n");
2344
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002345 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002346 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002347 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002348 return false;
2349 }
2350
Felipe Leme1d486fe2016-10-14 18:06:47 -07002351 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2352 ds.zip_file.reset(nullptr);
2353
Felipe Lemee9d2c542016-11-15 11:48:26 -08002354 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002355 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002356
Felipe Leme1e9edc62015-12-21 16:02:13 -08002357 return true;
2358}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002359
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002360static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2361 // clang-format off
2362 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2363 "--receiver-foreground", "--receiver-include-background", "-a", action};
2364 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002365
2366 am.insert(am.end(), args.begin(), args.end());
2367
Felipe Leme8d2410e2017-02-08 09:46:08 -08002368 RunCommand("", am,
2369 CommandOptions::WithTimeout(20)
2370 .Log("Sending broadcast: '%s'\n")
2371 .Always()
2372 .DropRoot()
2373 .RedirectStderr()
2374 .Build());
2375}
2376
Felipe Leme35b8cf12017-02-10 15:47:29 -08002377static void Vibrate(int duration_ms) {
2378 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002379 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002380 CommandOptions::WithTimeout(10)
2381 .Log("Vibrate: '%s'\n")
2382 .Always()
2383 .Build());
2384 // clang-format on
2385}
2386
Nandana Dutt979388e2018-11-30 16:48:55 +00002387static void MaybeResolveSymlink(std::string* path) {
2388 std::string resolved_path;
2389 if (android::base::Readlink(*path, &resolved_path)) {
2390 *path = resolved_path;
2391 }
2392}
2393
Nandana Dutt4be45d12018-09-26 15:04:23 +01002394/*
2395 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002396 * and adds the version file. Return false if zip_file could not be open to write.
Nandana Dutt4be45d12018-09-26 15:04:23 +01002397 */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002398static bool PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002399 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2400
Nandana Dutt4be45d12018-09-26 15:04:23 +01002401 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2402 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002403 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002404 char date[80];
2405 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2406 ds.name_ = date;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002407
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002408 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002409 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002410 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002411 ds.base_name_ += "-wifi";
2412 }
2413
Paul Chang0d2aad72020-02-13 20:04:03 +08002414 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002415 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002416 }
2417 ds.tmp_path_ = ds.GetPath(".tmp");
2418 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2419
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002420 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002421 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002422 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002423 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002424 "Bugreport dir: [%s] "
2425 "Base name: [%s] "
2426 "Suffix: [%s] "
2427 "Log path: [%s] "
2428 "Temporary path: [%s] "
2429 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002430 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2431 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002432
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002433 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
2434 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2435 create_parent_dirs(ds.path_.c_str());
2436 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2437 if (ds.zip_file == nullptr) {
2438 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2439 return false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002440 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002441 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2442 ds.AddTextZipEntry("version.txt", ds.version_);
2443 return true;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002444}
2445
2446/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002447 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002448 * printing zipped file status, etc.
2449 */
2450static void FinalizeFile() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002451 bool do_text_file = !ds.FinishZipFile();
2452 if (do_text_file) {
2453 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002454 }
mhasank2d75c442020-06-11 15:05:25 -07002455
2456 std::string final_path = ds.path_;
2457 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002458 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002459 android::os::CopyFileToFile(ds.path_, final_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002460 }
mhasank2d75c442020-06-11 15:05:25 -07002461
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002462 if (ds.options_->stream_to_socket) {
2463 android::os::CopyFileToFd(ds.path_, ds.control_socket_fd_);
2464 } else if (ds.options_->progress_updates_to_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002465 if (do_text_file) {
2466 dprintf(ds.control_socket_fd_,
2467 "FAIL:could not create zip file, check %s "
2468 "for more details\n",
2469 ds.log_path_.c_str());
2470 } else {
mhasank2d75c442020-06-11 15:05:25 -07002471 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002472 }
2473 }
2474}
2475
Nandana Dutt4be45d12018-09-26 15:04:23 +01002476
Nandana Dutt58d72e22018-11-16 10:30:48 +00002477static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2478 switch (mode) {
2479 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2480 return "BUGREPORT_FULL";
2481 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2482 return "BUGREPORT_INTERACTIVE";
2483 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2484 return "BUGREPORT_REMOTE";
2485 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2486 return "BUGREPORT_WEAR";
2487 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2488 return "BUGREPORT_TELEPHONY";
2489 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2490 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002491 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2492 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002493 }
2494}
2495
Paul Changf59c2b72020-03-10 02:08:55 +08002496static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2497 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002498 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2499 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002500 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002501 switch (mode) {
2502 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002503 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002504 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002505 break;
2506 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002507 // Currently, the dumpstate binder is only used by Shell to update progress.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002508 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002509 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002510 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002511 break;
2512 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002513 options->do_vibrate = false;
2514 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002515 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002516 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002517 break;
2518 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002519 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002520 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002521 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002522 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002523 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002524 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002525 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002526 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002527 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002528 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002529 break;
2530 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002531 options->wifi_only = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002532 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002533 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002534 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002535 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2536 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002537 }
2538}
2539
Nandana Dutt58d72e22018-11-16 10:30:48 +00002540static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002541 MYLOGI(
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002542 "do_vibrate: %d stream_to_socket: %d progress_updates_to_socket: %d do_screenshot: %d "
Rhed Jao6f5ddce2020-08-20 00:10:32 +08002543 "is_remote_mode: %d show_header_only: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002544 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002545 "limited_only: %d args: %s\n",
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002546 options.do_vibrate, options.stream_to_socket, options.progress_updates_to_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002547 options.do_screenshot, options.is_remote_mode, options.show_header_only,
Rhed Jao6f5ddce2020-08-20 00:10:32 +08002548 options.telephony_only, options.wifi_only,
mhasankd451a472020-05-26 18:02:39 -07002549 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2550 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002551}
2552
Nandana Dutt54dbd672019-01-11 12:58:05 +00002553void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2554 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002555 const android::base::unique_fd& screenshot_fd_in,
2556 bool is_screenshot_requested) {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002557 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2558 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2559 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002560
Paul Changf59c2b72020-03-10 02:08:55 +08002561 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002562}
2563
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002564Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2565 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002566 int c;
mhasankd451a472020-05-26 18:02:39 -07002567 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002568 switch (c) {
2569 // clang-format off
mhasank3a4cfb42020-06-15 18:06:43 -07002570 case 'o': out_dir = optarg; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002571 case 's': stream_to_socket = true; break;
2572 case 'S': progress_updates_to_socket = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002573 case 'v': show_header_only = true; break;
2574 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002575 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002576 case 'P': do_progress_updates = true; break;
2577 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002578 case 'L': limited_only = true; break;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002579 case 'V':
2580 case 'd':
2581 case 'z':
2582 // compatibility no-op
2583 break;
Nandana Dutt235864b2019-01-22 12:10:16 +00002584 case 'w':
2585 // This was already processed
2586 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002587 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002588 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002589 break;
2590 default:
2591 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002592 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002593 break;
2594 // clang-format on
2595 }
2596 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002597
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002598 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002599 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002600 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002601 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002602 }
2603 }
2604
2605 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2606 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002607
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002608 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002609}
2610
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002611bool Dumpstate::DumpOptions::ValidateOptions() const {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002612 if (bugreport_fd.get() != -1 && stream_to_socket) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002613 return false;
2614 }
2615
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002616 if ((progress_updates_to_socket || do_progress_updates) && stream_to_socket) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002617 return false;
2618 }
2619
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002620 if (is_remote_mode && (do_progress_updates || stream_to_socket)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002621 return false;
2622 }
2623 return true;
2624}
2625
Nandana Dutt197661d2018-11-16 16:40:21 +00002626void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2627 options_ = std::move(options);
2628}
2629
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002630void Dumpstate::Initialize() {
2631 /* gets the sequential id */
2632 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2633 id_ = ++last_id;
2634 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2635}
2636
Nandana Duttd2f5f082019-01-18 17:13:52 +00002637Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2638 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002639 if (listener_ != nullptr) {
2640 switch (status) {
2641 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002642 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002643 break;
2644 case Dumpstate::RunStatus::HELP:
2645 break;
2646 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002647 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002648 break;
2649 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002650 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2651 break;
2652 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2653 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2654 break;
2655 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2656 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002657 break;
2658 }
2659 }
2660 return status;
2661}
2662
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002663void Dumpstate::Cancel() {
2664 CleanupTmpFiles();
2665 android::os::UnlinkAndLogOnError(log_path_);
2666 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2667 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2668 kDumpstateBoardFiles[i]);
2669 }
2670 tombstone_data_.clear();
2671 anr_data_.clear();
Rhed Jaoe96bcd52020-08-21 14:48:20 +08002672
2673 // Instead of shutdown the pool, we delete temporary files directly since
2674 // shutdown blocking the call.
2675 if (dump_pool_) {
2676 dump_pool_->deleteTempFiles();
2677 }
2678 if (zip_entry_tasks_) {
2679 zip_entry_tasks_->run(/*do_cancel =*/ true);
2680 }
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002681}
2682
Nandana Dutt979388e2018-11-30 16:48:55 +00002683/*
2684 * Dumps relevant information to a bugreport based on the given options.
2685 *
2686 * The bugreport can be dumped to a file or streamed to a socket.
2687 *
2688 * How dumping to file works:
2689 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2690 * stderr is redirected a log file.
2691 *
2692 * The temporary bugreport is then populated via printfs, dumping contents of files and
2693 * output of commands to stdout.
2694 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002695 * A bunch of other files and dumps are added to the zip archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002696 *
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002697 * The temporary bugreport file and the log file also get added to the archive.
Nandana Dutt979388e2018-11-30 16:48:55 +00002698 *
mhasank2d75c442020-06-11 15:05:25 -07002699 * Bugreports are first generated in a local directory and later copied to the caller's fd
2700 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002701 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002702Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2703 const std::string& calling_package) {
Rhed Jao1c855122020-07-16 17:37:39 +08002704 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002705 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002706 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002707 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002708 return RunStatus::INVALID_INPUT;
2709 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002710 /* set as high priority, and protect from OOM killer */
2711 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002712
Felipe Lemed071c682016-10-20 16:48:00 -07002713 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002714 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002715 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002716 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002717 } else {
2718 /* fallback to kernels <= 2.6.35 */
2719 oom_adj = fopen("/proc/self/oom_adj", "we");
2720 if (oom_adj) {
2721 fputs("-17", oom_adj);
2722 fclose(oom_adj);
2723 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002724 }
2725
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002726 if (version_ == VERSION_DEFAULT) {
2727 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002728 }
2729
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002730 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002731 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002732 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002733 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002735 }
2736
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002737 if (options_->show_header_only) {
2738 PrintHeader();
2739 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002740 }
2741
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002742 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2743 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002744
Felipe Leme7447d7c2016-11-03 18:12:22 -07002745 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002746 std::string stats_path =
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002747 android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002748 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002749
Sahana Raof35ed432019-07-12 10:47:52 +01002750 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2751 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2752 } else {
2753 // Wake lock will be released automatically on process death
2754 MYLOGD("Wake lock acquired.\n");
2755 }
2756
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002757 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002758
Felipe Lemef0292972016-11-22 13:57:05 -08002759 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002760 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2761 }
2762
Nandana Dutt235c6672019-11-14 15:22:32 +00002763 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2764 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002765
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002766 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002767
Christopher Ferrised9354f2014-10-01 17:35:01 -07002768 // If we are going to use a socket, do it as early as possible
2769 // to avoid timeouts from bugreport.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002770 if (options_->stream_to_socket || options_->progress_updates_to_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002771 MYLOGD("Opening control socket\n");
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002772 control_socket_fd_ = open_socket_fn_("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002773 if (control_socket_fd_ == -1) {
2774 return ERROR;
2775 }
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002776 if (options_->progress_updates_to_socket) {
2777 options_->do_progress_updates = 1;
2778 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002779 }
2780
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002781 if (!PrepareToWriteToFile()) {
2782 return ERROR;
2783 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002784
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002785 // Interactive, wear & telephony modes are default to true.
2786 // and may enable from cli option or when using control socket
2787 if (options_->do_progress_updates) {
2788 // clang-format off
2789 std::vector<std::string> am_args = {
2790 "--receiver-permission", "android.permission.DUMP",
2791 };
2792 // clang-format on
2793 // Send STARTED broadcast for apps that listen to bugreport generation events
2794 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
2795 if (options_->progress_updates_to_socket) {
2796 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08002797 }
2798 }
2799
Nick Kralevichf3599b32016-01-25 15:05:16 -08002800 /* read /proc/cmdline before dropping root */
2801 FILE *cmdline = fopen("/proc/cmdline", "re");
2802 if (cmdline) {
2803 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2804 fclose(cmdline);
2805 }
2806
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002807 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002808 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002809 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002810
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002811 if (zip_file != nullptr) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002812 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2813 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002814 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002815 }
2816 }
2817
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002818 int dup_stdout_fd;
2819 int dup_stderr_fd;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002820 // Redirect stderr to log_path_ for debugging.
2821 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
2822 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2823 return ERROR;
2824 }
2825 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2826 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2827 strerror(errno));
2828 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002829
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002830 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2831 // moved into zip file later, if zipping.
2832 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
2833 // TODO: why not write to a file instead of stdout to overcome this problem?
2834 /* TODO: rather than generating a text file now and zipping it later,
2835 it would be more efficient to redirect stdout to the zip entry
2836 directly, but the libziparchive doesn't support that option yet. */
2837 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2838 return ERROR;
2839 }
2840 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
2841 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
2842 tmp_path_.c_str(), strerror(errno));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002843 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002844
2845 // Don't buffer stdout
2846 setvbuf(stdout, nullptr, _IONBF, 0);
2847
Rhed Jao1c855122020-07-16 17:37:39 +08002848 // Enable the parallel run if the client requests to output to a file.
2849 EnableParallelRunIfNeeded();
2850 // Using scope guard to make sure the dump pool can be shut down correctly.
2851 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2852 ShutdownDumpPool();
2853 });
2854
Felipe Leme608385d2016-02-01 10:35:38 -08002855 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2856 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002857 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002858 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002859
Gavin Corkery6968f552020-11-22 18:09:05 +00002860 bool is_dumpstate_restricted = options_->telephony_only
2861 || options_->wifi_only
2862 || options_->limited_only;
2863 if (!is_dumpstate_restricted) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002864 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002865 RunDumpsysCritical();
Gavin Corkery6968f552020-11-22 18:09:05 +00002866 }
2867 MaybeTakeEarlyScreenshot();
2868 onUiIntensiveBugreportDumpsFinished(calling_uid);
2869 MaybeCheckUserConsent(calling_uid, calling_package);
2870 if (options_->telephony_only) {
2871 DumpstateTelephonyOnly(calling_package);
2872 } else if (options_->wifi_only) {
2873 DumpstateWifiOnly();
2874 } else if (options_->limited_only) {
2875 DumpstateLimitedOnly();
2876 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002877 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002878 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002879 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002880 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002881 HandleUserConsentDenied();
2882 }
2883 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002884 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002885 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002886
Felipe Leme55b42a62015-11-10 17:39:08 -08002887 /* close output if needed */
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002888 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002889
Abhijeet Kaure370d682019-10-01 16:49:30 +01002890 // Zip the (now complete) .tmp file within the internal directory.
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002891 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002892
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002893 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002894 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002895 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002896 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002897 if (status != Dumpstate::RunStatus::OK &&
2898 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2899 // Do an early return if there were errors. We make an exception for consent
2900 // timing out because it's possible the user got distracted. In this case the
2901 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002902 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002903 return status;
2904 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002905 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2906 MYLOGI(
2907 "Did not receive user consent yet."
2908 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002909 const String16 incidentcompanion("incidentcompanion");
2910 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2911 if (ics != nullptr) {
2912 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2913 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2914 consent_callback_.get());
2915 } else {
2916 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2917 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002918 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002919 }
2920
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002921 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002922 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002923 for (int i = 0; i < 3; i++) {
2924 Vibrate(75);
2925 usleep((75 + 50) * 1000);
2926 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002927 }
2928
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2930 progress_->GetInitialMax());
2931 progress_->Save();
2932 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002933
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002934 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002935
Dieter Hsu105ad0c2020-09-29 15:23:33 +08002936 if (control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002937 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002938 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002939 }
2940
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002941 tombstone_data_.clear();
2942 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002943
Nandana Duttd2f5f082019-01-18 17:13:52 +00002944 return (consent_callback_ != nullptr &&
2945 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2946 ? USER_CONSENT_TIMED_OUT
2947 : RunStatus::OK;
2948}
2949
Paul Chang0d2aad72020-02-13 20:04:03 +08002950void Dumpstate::MaybeTakeEarlyScreenshot() {
2951 if (!options_->do_screenshot || !do_early_screenshot_) {
2952 return;
2953 }
2954
2955 TakeScreenshot();
2956}
2957
Paul Chang5702b482020-05-28 22:05:47 +08002958void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08002959 if (calling_uid == AID_SHELL || !CalledByApi()) {
2960 return;
2961 }
2962 if (listener_ != nullptr) {
2963 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2964 // handling if required.
Paul Chang5702b482020-05-28 22:05:47 +08002965 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08002966 }
2967}
2968
Jichao Lie89d9c12019-11-21 19:02:51 -08002969void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2970 if (calling_uid == AID_SHELL || !CalledByApi()) {
2971 // No need to get consent for shell triggered dumpstates, or not through
2972 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002973 return;
2974 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002975 consent_callback_ = new ConsentCallback();
2976 const String16 incidentcompanion("incidentcompanion");
2977 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002978 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002979 if (ics != nullptr) {
2980 MYLOGD("Checking user consent via incidentcompanion service\n");
2981 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002982 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002983 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002984 } else {
2985 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2986 }
2987}
2988
Nandana Dutt5c390032019-03-12 10:52:56 +00002989bool Dumpstate::IsUserConsentDenied() const {
2990 return ds.consent_callback_ != nullptr &&
2991 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2992}
2993
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002994bool Dumpstate::CalledByApi() const {
2995 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2996}
2997
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002998void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002999 android::os::UnlinkAndLogOnError(tmp_path_);
3000 android::os::UnlinkAndLogOnError(screenshot_path_);
3001 android::os::UnlinkAndLogOnError(path_);
3002}
3003
Rhed Jao1c855122020-07-16 17:37:39 +08003004void Dumpstate::EnableParallelRunIfNeeded() {
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003005 if (!PropertiesHelper::IsParallelRun()) {
Rhed Jao1c855122020-07-16 17:37:39 +08003006 return;
3007 }
3008 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao4875aa62020-07-20 17:46:29 +08003009 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao1c855122020-07-16 17:37:39 +08003010}
3011
3012void Dumpstate::ShutdownDumpPool() {
3013 if (dump_pool_) {
3014 dump_pool_->shutdown();
3015 dump_pool_ = nullptr;
3016 }
Rhed Jao4875aa62020-07-20 17:46:29 +08003017 if (zip_entry_tasks_) {
3018 zip_entry_tasks_->run(/* do_cancel = */true);
3019 zip_entry_tasks_ = nullptr;
3020 }
3021}
3022
3023void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3024 const std::string& entry_path) {
3025 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3026 if (!task_cancelled) {
3027 AddZipEntry(entry_name, entry_path);
3028 }
3029 android::os::UnlinkAndLogOnError(entry_path);
3030 };
3031 if (zip_entry_tasks_) {
3032 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3033 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3034 } else {
3035 // Invokes AddZipEntryAndCleanup immediately
3036 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3037 }
Rhed Jao1c855122020-07-16 17:37:39 +08003038}
3039
Nandana Duttd2f5f082019-01-18 17:13:52 +00003040Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3041 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003042 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003043 return USER_CONSENT_DENIED;
3044}
3045
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003046Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003047 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003048 // user consent (unless the caller is Shell).
3049 UserConsentResult consent_result;
3050 if (calling_uid == AID_SHELL) {
3051 consent_result = UserConsentResult::APPROVED;
3052 } else {
3053 consent_result = consent_callback_->getResult();
3054 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003055 if (consent_result == UserConsentResult::UNAVAILABLE) {
3056 // User has not responded yet.
3057 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003058 // Telephony is a fast report type, particularly on user builds where information may be
3059 // more aggressively limited. To give the user time to read the consent dialog, increase the
3060 // timeout.
3061 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3062 : USER_CONSENT_TIMEOUT_MS;
3063 if (elapsed_ms < timeout_ms) {
3064 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003065 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3066 sleep(delay_seconds);
3067 }
3068 consent_result = consent_callback_->getResult();
3069 }
3070 if (consent_result == UserConsentResult::DENIED) {
3071 // User has explicitly denied sharing with the app. To be safe delete the
3072 // internal bugreport & tmp files.
3073 return HandleUserConsentDenied();
3074 }
3075 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003076 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3077 if (copy_succeeded) {
3078 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003079 if (options_->do_screenshot &&
3080 options_->screenshot_fd.get() != -1 &&
3081 !options_->is_screenshot_copied) {
3082 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3083 options_->screenshot_fd.get());
3084 options_->is_screenshot_copied = copy_succeeded;
3085 if (copy_succeeded) {
3086 android::os::UnlinkAndLogOnError(screenshot_path_);
3087 }
3088 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003089 }
3090 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3091 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3092 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3093 // Since we do not have user consent to share the bugreport it does not get
3094 // copied over to the calling app but remains in the internal directory from
3095 // where the user can manually pull it.
3096 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3097 }
3098 // Unknown result; must be a programming error.
3099 MYLOGE("Unknown user consent result:%d\n", consent_result);
3100 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003101}
3102
Nandana Duttf02564e2019-02-15 15:24:24 +00003103Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003104 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3105 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3106 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003107 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003108 // When directly running dumpstate binary, the output is not expected to be written
3109 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003110 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003111
3112 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003113 // an app; they are irrelevant here because bugreport is triggered via command line.
3114 // Update Last ID before calling Run().
3115 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003116 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003117 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003118 return status;
3119}
3120
3121/* Main entry point for dumpstate binary. */
3122int run_main(int argc, char* argv[]) {
3123 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003124
3125 switch (status) {
3126 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003127 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003128 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003129 ShowUsage();
3130 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003131 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003132 fprintf(stderr, "Invalid combination of args\n");
3133 ShowUsage();
3134 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003135 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003136 FALLTHROUGH_INTENDED;
3137 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3138 FALLTHROUGH_INTENDED;
3139 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003140 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003141 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003142}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003143
3144// TODO(111441001): Default DumpOptions to sensible values.
3145Dumpstate::Dumpstate(const std::string& version)
3146 : pid_(getpid()),
3147 options_(new Dumpstate::DumpOptions()),
Nandana Duttf02cd782019-06-14 14:25:13 +01003148 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003149 version_(version),
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003150 now_(time(nullptr)),
3151 open_socket_fn_(open_socket) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003152}
3153
3154Dumpstate& Dumpstate::GetInstance() {
3155 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3156 return singleton_;
3157}
3158
Rhed Jao1c855122020-07-16 17:37:39 +08003159DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3160 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3161 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003162 if (!title_.empty()) {
3163 started_ = Nanotime();
3164 }
3165}
3166
3167DurationReporter::~DurationReporter() {
3168 if (!title_.empty()) {
3169 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003170 if (elapsed >= .5f || verbose_) {
3171 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003172 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003173 if (!logcat_only_) {
3174 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao1c855122020-07-16 17:37:39 +08003175 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3176 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003177 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003178 }
3179}
3180
3181const int32_t Progress::kDefaultMax = 5000;
3182
3183Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3184}
3185
3186Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3187 : Progress(initial_max, growth_factor, "") {
3188 progress_ = progress;
3189}
3190
3191Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3192 : initial_max_(initial_max),
3193 progress_(0),
3194 max_(initial_max),
3195 growth_factor_(growth_factor),
3196 n_runs_(0),
3197 average_max_(0),
3198 path_(path) {
3199 if (!path_.empty()) {
3200 Load();
3201 }
3202}
3203
3204void Progress::Load() {
3205 MYLOGD("Loading stats from %s\n", path_.c_str());
3206 std::string content;
3207 if (!android::base::ReadFileToString(path_, &content)) {
3208 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3209 return;
3210 }
3211 if (content.empty()) {
3212 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3213 return;
3214 }
3215 std::vector<std::string> lines = android::base::Split(content, "\n");
3216
3217 if (lines.size() < 1) {
3218 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3219 (int)lines.size(), max_);
3220 return;
3221 }
3222 char* ptr;
3223 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3224 average_max_ = strtol(ptr, nullptr, 10);
3225 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3226 average_max_ > STATS_MAX_AVERAGE) {
3227 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3228 initial_max_ = Progress::kDefaultMax;
3229 } else {
3230 initial_max_ = average_max_;
3231 }
3232 max_ = initial_max_;
3233
3234 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3235}
3236
3237void Progress::Save() {
3238 int32_t total = n_runs_ * average_max_ + progress_;
3239 int32_t runs = n_runs_ + 1;
3240 int32_t average = floor(((float)total) / runs);
3241 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3242 path_.c_str());
3243 if (path_.empty()) {
3244 return;
3245 }
3246
3247 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3248 if (!android::base::WriteStringToFile(content, path_)) {
3249 MYLOGE("Could not save stats on %s\n", path_.c_str());
3250 }
3251}
3252
3253int32_t Progress::Get() const {
3254 return progress_;
3255}
3256
3257bool Progress::Inc(int32_t delta_sec) {
3258 bool changed = false;
3259 if (delta_sec >= 0) {
3260 progress_ += delta_sec;
3261 if (progress_ > max_) {
3262 int32_t old_max = max_;
3263 max_ = floor((float)progress_ * growth_factor_);
3264 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3265 changed = true;
3266 }
3267 }
3268 return changed;
3269}
3270
3271int32_t Progress::GetMax() const {
3272 return max_;
3273}
3274
3275int32_t Progress::GetInitialMax() const {
3276 return initial_max_;
3277}
3278
3279void Progress::Dump(int fd, const std::string& prefix) const {
3280 const char* pr = prefix.c_str();
3281 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3282 dprintf(fd, "%smax: %d\n", pr, max_);
3283 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3284 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3285 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3286 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3287 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3288}
3289
3290bool Dumpstate::IsZipping() const {
3291 return zip_writer_ != nullptr;
3292}
3293
3294std::string Dumpstate::GetPath(const std::string& suffix) const {
3295 return GetPath(bugreport_internal_dir_, suffix);
3296}
3297
3298std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3299 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3300 name_.c_str(), suffix.c_str());
3301}
3302
3303void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3304 progress_ = std::move(progress);
3305}
3306
3307void for_each_userid(void (*func)(int), const char *header) {
3308 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3309 "for_each_userid(%s)", header);
3310 DurationReporter duration_reporter(title);
3311 if (PropertiesHelper::IsDryRun()) return;
3312
3313 DIR *d;
3314 struct dirent *de;
3315
3316 if (header) printf("\n------ %s ------\n", header);
3317 func(0);
3318
3319 if (!(d = opendir("/data/system/users"))) {
3320 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3321 return;
3322 }
3323
3324 while ((de = readdir(d))) {
3325 int userid;
3326 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3327 continue;
3328 }
3329 func(userid);
3330 }
3331
3332 closedir(d);
3333}
3334
3335static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3336 DIR *d;
3337 struct dirent *de;
3338
3339 if (!(d = opendir("/proc"))) {
3340 printf("Failed to open /proc (%s)\n", strerror(errno));
3341 return;
3342 }
3343
3344 if (header) printf("\n------ %s ------\n", header);
3345 while ((de = readdir(d))) {
3346 if (ds.IsUserConsentDenied()) {
3347 MYLOGE(
3348 "Returning early because user denied consent to share bugreport with calling app.");
3349 closedir(d);
3350 return;
3351 }
3352 int pid;
3353 int fd;
3354 char cmdpath[255];
3355 char cmdline[255];
3356
3357 if (!(pid = atoi(de->d_name))) {
3358 continue;
3359 }
3360
3361 memset(cmdline, 0, sizeof(cmdline));
3362
3363 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3364 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3365 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3366 close(fd);
3367 if (cmdline[0]) {
3368 helper(pid, cmdline, arg);
3369 continue;
3370 }
3371 }
3372
3373 // if no cmdline, a kernel thread has comm
3374 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3375 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3376 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3377 close(fd);
3378 if (cmdline[1]) {
3379 cmdline[0] = '[';
3380 size_t len = strcspn(cmdline, "\f\b\r\n");
3381 cmdline[len] = ']';
3382 cmdline[len+1] = '\0';
3383 }
3384 }
3385 if (!cmdline[0]) {
3386 strcpy(cmdline, "N/A");
3387 }
3388 helper(pid, cmdline, arg);
3389 }
3390
3391 closedir(d);
3392}
3393
3394static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3395 for_each_pid_func *func = (for_each_pid_func*) arg;
3396 func(pid, cmdline);
3397}
3398
3399void for_each_pid(for_each_pid_func func, const char *header) {
3400 std::string title = header == nullptr ? "for_each_pid"
3401 : android::base::StringPrintf("for_each_pid(%s)", header);
3402 DurationReporter duration_reporter(title);
3403 if (PropertiesHelper::IsDryRun()) return;
3404
3405 __for_each_pid(for_each_pid_helper, header, (void *) func);
3406}
3407
3408static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3409 DIR *d;
3410 struct dirent *de;
3411 char taskpath[255];
3412 for_each_tid_func *func = (for_each_tid_func *) arg;
3413
3414 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3415
3416 if (!(d = opendir(taskpath))) {
3417 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3418 return;
3419 }
3420
3421 func(pid, pid, cmdline);
3422
3423 while ((de = readdir(d))) {
3424 if (ds.IsUserConsentDenied()) {
3425 MYLOGE(
3426 "Returning early because user denied consent to share bugreport with calling app.");
3427 closedir(d);
3428 return;
3429 }
3430 int tid;
3431 int fd;
3432 char commpath[255];
3433 char comm[255];
3434
3435 if (!(tid = atoi(de->d_name))) {
3436 continue;
3437 }
3438
3439 if (tid == pid)
3440 continue;
3441
3442 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3443 memset(comm, 0, sizeof(comm));
3444 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3445 strcpy(comm, "N/A");
3446 } else {
3447 char *c;
3448 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3449 close(fd);
3450
3451 c = strrchr(comm, '\n');
3452 if (c) {
3453 *c = '\0';
3454 }
3455 }
3456 func(pid, tid, comm);
3457 }
3458
3459 closedir(d);
3460}
3461
3462void for_each_tid(for_each_tid_func func, const char *header) {
3463 std::string title = header == nullptr ? "for_each_tid"
3464 : android::base::StringPrintf("for_each_tid(%s)", header);
3465 DurationReporter duration_reporter(title);
3466
3467 if (PropertiesHelper::IsDryRun()) return;
3468
3469 __for_each_pid(for_each_tid_helper, header, (void *) func);
3470}
3471
3472void show_wchan(int pid, int tid, const char *name) {
3473 if (PropertiesHelper::IsDryRun()) return;
3474
3475 char path[255];
3476 char buffer[255];
3477 int fd, ret, save_errno;
3478 char name_buffer[255];
3479
3480 memset(buffer, 0, sizeof(buffer));
3481
3482 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3483 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3484 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3485 return;
3486 }
3487
3488 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3489 save_errno = errno;
3490 close(fd);
3491
3492 if (ret < 0) {
3493 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3494 return;
3495 }
3496
3497 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3498 pid == tid ? 0 : 3, "", name);
3499
3500 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3501
3502 return;
3503}
3504
3505// print time in centiseconds
3506static void snprcent(char *buffer, size_t len, size_t spc,
3507 unsigned long long time) {
3508 static long hz; // cache discovered hz
3509
3510 if (hz <= 0) {
3511 hz = sysconf(_SC_CLK_TCK);
3512 if (hz <= 0) {
3513 hz = 1000;
3514 }
3515 }
3516
3517 // convert to centiseconds
3518 time = (time * 100 + (hz / 2)) / hz;
3519
3520 char str[16];
3521
3522 snprintf(str, sizeof(str), " %llu.%02u",
3523 time / 100, (unsigned)(time % 100));
3524 size_t offset = strlen(buffer);
3525 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3526 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3527}
3528
3529// print permille as a percent
3530static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3531 char str[16];
3532
3533 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3534 size_t offset = strlen(buffer);
3535 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3536 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3537}
3538
3539void show_showtime(int pid, const char *name) {
3540 if (PropertiesHelper::IsDryRun()) return;
3541
3542 char path[255];
3543 char buffer[1023];
3544 int fd, ret, save_errno;
3545
3546 memset(buffer, 0, sizeof(buffer));
3547
3548 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3549 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3550 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3551 return;
3552 }
3553
3554 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3555 save_errno = errno;
3556 close(fd);
3557
3558 if (ret < 0) {
3559 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3560 return;
3561 }
3562
3563 // field 14 is utime
3564 // field 15 is stime
3565 // field 42 is iotime
3566 unsigned long long utime = 0, stime = 0, iotime = 0;
3567 if (sscanf(buffer,
3568 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3569 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3570 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3571 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3572 &utime, &stime, &iotime) != 3) {
3573 return;
3574 }
3575
3576 unsigned long long total = utime + stime;
3577 if (!total) {
3578 return;
3579 }
3580
3581 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3582 if (permille > 1000) {
3583 permille = 1000;
3584 }
3585
3586 // try to beautify and stabilize columns at <80 characters
3587 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3588 if ((name[0] != '[') || utime) {
3589 snprcent(buffer, sizeof(buffer), 57, utime);
3590 }
3591 snprcent(buffer, sizeof(buffer), 65, stime);
3592 if ((name[0] != '[') || iotime) {
3593 snprcent(buffer, sizeof(buffer), 73, iotime);
3594 }
3595 if (iotime) {
3596 snprdec(buffer, sizeof(buffer), 79, permille);
3597 }
3598 puts(buffer); // adds a trailing newline
3599
3600 return;
3601}
3602
3603void do_dmesg() {
3604 const char *title = "KERNEL LOG (dmesg)";
3605 DurationReporter duration_reporter(title);
3606 printf("------ %s ------\n", title);
3607
3608 if (PropertiesHelper::IsDryRun()) return;
3609
3610 /* Get size of kernel buffer */
3611 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3612 if (size <= 0) {
3613 printf("Unexpected klogctl return value: %d\n\n", size);
3614 return;
3615 }
3616 char *buf = (char *) malloc(size + 1);
3617 if (buf == nullptr) {
3618 printf("memory allocation failed\n\n");
3619 return;
3620 }
3621 int retval = klogctl(KLOG_READ_ALL, buf, size);
3622 if (retval < 0) {
3623 printf("klogctl failure\n\n");
3624 free(buf);
3625 return;
3626 }
3627 buf[retval] = '\0';
3628 printf("%s\n\n", buf);
3629 free(buf);
3630 return;
3631}
3632
3633void do_showmap(int pid, const char *name) {
3634 char title[255];
3635 char arg[255];
3636
3637 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3638 snprintf(arg, sizeof(arg), "%d", pid);
3639 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3640}
3641
3642int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3643 DurationReporter duration_reporter(title);
3644
3645 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3646
3647 UpdateProgress(WEIGHT_FILE);
3648
3649 return status;
3650}
3651
3652int read_file_as_long(const char *path, long int *output) {
3653 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3654 if (fd < 0) {
3655 int err = errno;
3656 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3657 return -1;
3658 }
3659 char buffer[50];
3660 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3661 if (bytes_read == -1) {
3662 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3663 return -2;
3664 }
3665 if (bytes_read == 0) {
3666 MYLOGE("File %s is empty\n", path);
3667 return -3;
3668 }
3669 *output = atoi(buffer);
3670 return 0;
3671}
3672
3673/* calls skip to gate calling dump_from_fd recursively
3674 * in the specified directory. dump_from_fd defaults to
3675 * dump_file_from_fd above when set to NULL. skip defaults
3676 * to false when set to NULL. dump_from_fd will always be
3677 * called with title NULL.
3678 */
3679int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3680 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3681 DurationReporter duration_reporter(title);
3682 DIR *dirp;
3683 struct dirent *d;
3684 char *newpath = nullptr;
3685 const char *slash = "/";
3686 int retval = 0;
3687
3688 if (!title.empty()) {
3689 printf("------ %s (%s) ------\n", title.c_str(), dir);
3690 }
3691 if (PropertiesHelper::IsDryRun()) return 0;
3692
3693 if (dir[strlen(dir) - 1] == '/') {
3694 ++slash;
3695 }
3696 dirp = opendir(dir);
3697 if (dirp == nullptr) {
3698 retval = -errno;
3699 MYLOGE("%s: %s\n", dir, strerror(errno));
3700 return retval;
3701 }
3702
3703 if (!dump_from_fd) {
3704 dump_from_fd = dump_file_from_fd;
3705 }
3706 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3707 if ((d->d_name[0] == '.')
3708 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3709 || (d->d_name[1] == '\0'))) {
3710 continue;
3711 }
3712 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3713 (d->d_type == DT_DIR) ? "/" : "");
3714 if (!newpath) {
3715 retval = -errno;
3716 continue;
3717 }
3718 if (skip && (*skip)(newpath)) {
3719 continue;
3720 }
3721 if (d->d_type == DT_DIR) {
3722 int ret = dump_files("", newpath, skip, dump_from_fd);
3723 if (ret < 0) {
3724 retval = ret;
3725 }
3726 continue;
3727 }
3728 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3729 if (fd.get() < 0) {
3730 retval = -1;
3731 printf("*** %s: %s\n", newpath, strerror(errno));
3732 continue;
3733 }
3734 (*dump_from_fd)(nullptr, newpath, fd.get());
3735 }
3736 closedir(dirp);
3737 if (!title.empty()) {
3738 printf("\n");
3739 }
3740 return retval;
3741}
3742
3743/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3744 * it's possible to avoid issues where opening the file itself can get
3745 * stuck.
3746 */
3747int dump_file_from_fd(const char *title, const char *path, int fd) {
3748 if (PropertiesHelper::IsDryRun()) return 0;
3749
3750 int flags = fcntl(fd, F_GETFL);
3751 if (flags == -1) {
3752 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3753 return -1;
3754 } else if (!(flags & O_NONBLOCK)) {
3755 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3756 return -1;
3757 }
3758 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3759}
3760
3761int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao4875aa62020-07-20 17:46:29 +08003762 const CommandOptions& options, bool verbose_duration, int out_fd) {
3763 DurationReporter duration_reporter(title, false /* logcat_only */,
3764 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003765
Rhed Jao4875aa62020-07-20 17:46:29 +08003766 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003767
3768 /* TODO: for now we're simplifying the progress calculation by using the
3769 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3770 * where its weight should be much higher proportionally to its timeout.
3771 * Ideally, it should use a options.EstimatedDuration() instead...*/
3772 UpdateProgress(options.Timeout());
3773
3774 return status;
3775}
3776
3777void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08003778 const CommandOptions& options, long dumpsysTimeoutMs, int out_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003779 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3780 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3781 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
Rhed Jao6b1ea2d2020-07-21 17:58:41 +08003782 RunCommand(title, dumpsys, options, false, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003783}
3784
Dieter Hsu105ad0c2020-09-29 15:23:33 +08003785static int open_socket(const char* service) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003786 int s = android_get_control_socket(service);
3787 if (s < 0) {
3788 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3789 return -1;
3790 }
3791 fcntl(s, F_SETFD, FD_CLOEXEC);
3792
3793 // Set backlog to 0 to make sure that queue size will be minimum.
3794 // In Linux, because the minimum queue will be 1, connect() will be blocked
3795 // if the other clients already called connect() and the connection request was not accepted.
3796 if (listen(s, 0) < 0) {
3797 MYLOGE("listen(control socket): %s\n", strerror(errno));
3798 return -1;
3799 }
3800
3801 struct sockaddr addr;
3802 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003803 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003804
3805 // Close socket just after accept(), to make sure that connect() by client will get error
3806 // when the socket is used by the other services.
3807 // There is still a race condition possibility between accept and close, but there is no way
3808 // to close-on-accept atomically.
3809 // See detail; b/123306389#comment25
3810 close(s);
3811
3812 if (fd < 0) {
3813 MYLOGE("accept(control socket): %s\n", strerror(errno));
3814 return -1;
3815 }
3816
3817 return fd;
3818}
3819
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003820// TODO: should call is_valid_output_file and/or be merged into it.
3821void create_parent_dirs(const char *path) {
3822 char *chp = const_cast<char *> (path);
3823
3824 /* skip initial slash */
3825 if (chp[0] == '/')
3826 chp++;
3827
3828 /* create leading directories, if necessary */
3829 struct stat dir_stat;
3830 while (chp && chp[0]) {
3831 chp = strchr(chp, '/');
3832 if (chp) {
3833 *chp = 0;
3834 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3835 MYLOGI("Creating directory %s\n", path);
3836 if (mkdir(path, 0770)) { /* drwxrwx--- */
3837 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3838 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3839 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3840 }
3841 }
3842 *chp++ = '/';
3843 }
3844 }
3845}
3846
3847bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3848 create_parent_dirs(path);
3849
3850 int fd = TEMP_FAILURE_RETRY(open(path,
3851 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3852 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3853 if (fd < 0) {
3854 MYLOGE("%s: %s\n", path, strerror(errno));
3855 return false;
3856 }
3857
3858 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3859 close(fd);
3860 return true;
3861}
3862
3863bool redirect_to_file(FILE* redirect, char* path) {
3864 return _redirect_to_file(redirect, path, O_TRUNC);
3865}
3866
3867bool redirect_to_existing_file(FILE* redirect, char* path) {
3868 return _redirect_to_file(redirect, path, O_APPEND);
3869}
3870
3871void dump_route_tables() {
3872 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3873 if (PropertiesHelper::IsDryRun()) return;
3874 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3875 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3876 FILE* fp = fopen(RT_TABLES_PATH, "re");
3877 if (!fp) {
3878 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3879 return;
3880 }
3881 char table[16];
3882 // Each line has an integer (the table number), a space, and a string (the table name). We only
3883 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3884 // Add a fixed max limit so this doesn't go awry.
3885 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3886 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3887 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3888 }
3889 fclose(fp);
3890}
3891
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003892void Dumpstate::UpdateProgress(int32_t delta_sec) {
3893 if (progress_ == nullptr) {
3894 MYLOGE("UpdateProgress: progress_ not set\n");
3895 return;
3896 }
Rhed Jao2cc4eec2020-07-21 15:42:55 +08003897 // This function updates progress related members of the dumpstate and reports
3898 // progress percentage to the bugreport client. Since it could be called by
3899 // different dump tasks at the same time if the parallel run is enabled, a
3900 // mutex lock is necessary here to synchronize the call.
3901 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003902
3903 // Always update progess so stats can be tuned...
Nandana Duttf02cd782019-06-14 14:25:13 +01003904 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003905
3906 // ...but only notifiy listeners when necessary.
3907 if (!options_->do_progress_updates) return;
3908
3909 int progress = progress_->Get();
3910 int max = progress_->GetMax();
Nandana Duttf02cd782019-06-14 14:25:13 +01003911 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003912
Nandana Duttf02cd782019-06-14 14:25:13 +01003913 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003914 return;
3915 }
Nandana Duttf02cd782019-06-14 14:25:13 +01003916 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003917
3918 if (control_socket_fd_ >= 0) {
3919 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3920 fsync(control_socket_fd_);
3921 }
3922
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003923 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003924 if (percent % 10 == 0) {
3925 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003926 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003927 } else {
3928 // stderr is ignored on normal invocations, but useful when calling
3929 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003930 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003931 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003932
3933 listener_->onProgress(percent);
3934 }
3935}
3936
3937void Dumpstate::TakeScreenshot(const std::string& path) {
3938 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3939 int status =
3940 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3941 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3942 if (status == 0) {
3943 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3944 } else {
3945 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3946 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003947 if (listener_ != nullptr) {
3948 // Show a visual indication to indicate screenshot is taken via
3949 // IDumpstateListener.onScreenshotTaken()
3950 listener_->onScreenshotTaken(status == 0);
3951 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003952}
3953
3954bool is_dir(const char* pathname) {
3955 struct stat info;
3956 if (stat(pathname, &info) == -1) {
3957 return false;
3958 }
3959 return S_ISDIR(info.st_mode);
3960}
3961
3962time_t get_mtime(int fd, time_t default_mtime) {
3963 struct stat info;
3964 if (fstat(fd, &info) == -1) {
3965 return default_mtime;
3966 }
3967 return info.st_mtime;
3968}