blob: d7700acbc2f94ea1a951a6176518f938b183dc9c [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 Jao5377d792020-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 Jao5377d792020-07-16 17:37:39 +0800117using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800118using android::os::dumpstate::PropertiesHelper;
Rhed Jao3c2fdbd2020-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 Jao3c2fdbd2020-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 Juravlef84d3692020-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 Jao5377d792020-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 Jao3c2fdbd2020-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 Jao5377d792020-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 Jao3c2fdbd2020-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 Jao5377d792020-07-16 17:37:39 +0800229
Nandana Dutt979388e2018-11-30 16:48:55 +0000230namespace android {
231namespace os {
232namespace {
233
234static int Open(std::string path, int flags, mode_t mode = 0) {
235 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
236 if (fd == -1) {
237 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
238 }
239 return fd;
240}
241
mhasank2d75c442020-06-11 15:05:25 -0700242static int OpenForWrite(std::string path) {
243 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
244 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
245}
Nandana Dutt979388e2018-11-30 16:48:55 +0000246
247static int OpenForRead(std::string path) {
248 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
249}
250
251bool CopyFile(int in_fd, int out_fd) {
252 char buf[4096];
253 ssize_t byte_count;
254 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
255 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
256 return false;
257 }
258 }
259 return (byte_count != -1);
260}
261
262static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000263 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000264
265 // Obtain a handle to the source file.
266 android::base::unique_fd in_fd(OpenForRead(input_file));
267 if (out_fd != -1 && in_fd.get() != -1) {
268 if (CopyFile(in_fd.get(), out_fd)) {
269 return true;
270 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000271 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000272 }
273 return false;
274}
275
Nandana Duttd2f5f082019-01-18 17:13:52 +0000276static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000277 if (file.empty()) {
278 return false;
279 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000280 if (unlink(file.c_str())) {
281 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000282 return false;
283 }
284 return true;
285}
Nandana Dutt979388e2018-11-30 16:48:55 +0000286
Nikita Ioffea325a572019-05-16 19:49:47 +0100287int64_t GetModuleMetadataVersion() {
288 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
289 if (binder == nullptr) {
290 MYLOGE("Failed to retrieve package_native service");
291 return 0L;
292 }
293 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
294 std::string package_name;
295 auto status = package_service->getModuleMetadataPackageName(&package_name);
296 if (!status.isOk()) {
297 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
298 return 0L;
299 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100300 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100301 int64_t version_code;
302 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
303 &version_code);
304 if (!status.isOk()) {
305 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
306 return 0L;
307 }
308 return version_code;
309}
310
mhasank2d75c442020-06-11 15:05:25 -0700311static bool PathExists(const std::string& path) {
312 struct stat sb;
313 return stat(path.c_str(), &sb) == 0;
314}
315
316static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
317 if (input_file == output_file) {
318 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
319 output_file.c_str());
320 return false;
321 }
322 else if (PathExists(output_file)) {
323 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
324 return false;
325 }
326
327 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
328 android::base::unique_fd out_fd(OpenForWrite(output_file));
329 return CopyFileToFd(input_file, out_fd.get());
330}
331
Nandana Dutt979388e2018-11-30 16:48:55 +0000332} // namespace
333} // namespace os
334} // namespace android
335
Felipe Leme678727a2016-09-21 17:22:11 -0700336static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800337 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800338 long dumpsysTimeoutMs = 0) {
339 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700340}
341static int DumpFile(const std::string& title, const std::string& path) {
342 return ds.DumpFile(title, path);
343}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800344
Felipe Lemee844a9d2016-09-21 15:01:39 -0700345// Relative directory (inside the zip) for all files copied as-is into the bugreport.
346static const std::string ZIP_ROOT_DIR = "FS";
347
Vishnu Naire97d6122018-01-18 13:58:56 -0800348static const std::string kProtoPath = "proto/";
349static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700350static const std::string kDumpstateBoardFiles[] = {
351 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700352 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700353};
354static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
355
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700356static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700357static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700358
Felipe Lemef0292972016-11-22 13:57:05 -0800359static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
360
Narayan Kamath8f788292017-05-25 13:20:39 +0100361/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100362 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800363 * The returned vector is sorted by the mtimes of the dumps with descending
364 * order. If |limit_by_mtime| is set, the vector only contains files that
365 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100366 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700367static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
368 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700369 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100370 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
371
Narayan Kamathbd863722017-06-01 18:50:12 +0100372 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100373
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700374 if (dump_dir == nullptr) {
375 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700376 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700377 }
378
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700379 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100380 struct dirent* entry = nullptr;
381 while ((entry = readdir(dump_dir.get()))) {
382 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100383 continue;
384 }
385
Narayan Kamathbd863722017-06-01 18:50:12 +0100386 const std::string base_name(entry->d_name);
387 if (base_name.find(file_prefix) != 0) {
388 continue;
389 }
390
391 const std::string abs_path = dir_path + base_name;
392 android::base::unique_fd fd(
393 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
394 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700395 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100396 break;
397 }
398
399 struct stat st = {};
400 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700401 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100402 continue;
403 }
404
Narayan Kamath3f31b632018-02-22 19:42:36 +0000405 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100406 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100407 continue;
408 }
409
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700410 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700411 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800412 if (!dump_data.empty()) {
413 std::sort(dump_data.begin(), dump_data.end(),
414 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
415 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100416
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700417 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100418}
419
Narayan Kamathbd863722017-06-01 18:50:12 +0100420static bool AddDumps(const std::vector<DumpData>::const_iterator start,
421 const std::vector<DumpData>::const_iterator end,
422 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100423 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100424 for (auto it = start; it != end; ++it) {
425 const std::string& name = it->name;
426 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100427 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100428
429 // Seek to the beginning of the file before dumping any data. A given
430 // DumpData entry might be dumped multiple times in the report.
431 //
432 // For example, the most recent ANR entry is dumped to the body of the
433 // main entry and it also shows up as a separate entry in the bugreport
434 // ZIP file.
435 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
436 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
437 strerror(errno));
438 }
439
Narayan Kamath8f788292017-05-25 13:20:39 +0100440 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800441 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100442 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100443 }
444 } else {
445 dump_file_from_fd(type_name, name.c_str(), fd);
446 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100447 }
448
449 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700450}
451
Felipe Leme635ca312016-01-05 14:23:02 -0800452// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700453void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800454 char path[PATH_MAX];
455
456 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
457 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700458 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800459 char linkname[PATH_MAX];
460 ssize_t r = readlink(path, linkname, PATH_MAX);
461 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800462 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800463 return;
464 }
465 linkname[r] = '\0';
466
467 if (mount_points.find(linkname) == mount_points.end()) {
468 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700469 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700470 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800471 mount_points.insert(linkname);
472 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800473 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800474 }
475 }
476}
477
478void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700479 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700480 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800481 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800482 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700483 for_each_pid(do_mountinfo, nullptr);
484 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800485}
486
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700487static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
488{
489 DIR *d;
490 struct dirent *de;
491 char path[PATH_MAX];
492
493 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700494 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700495 return;
496 }
497
498 while ((de = readdir(d))) {
499 if (de->d_type != DT_LNK) {
500 continue;
501 }
502 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700503 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700504 }
505
506 closedir(d);
507}
508
Mark Salyzyn326842f2015-04-30 09:49:41 -0700509static bool skip_not_stat(const char *path) {
510 static const char stat[] = "/stat";
511 size_t len = strlen(path);
512 if (path[len - 1] == '/') { /* Directory? */
513 return false;
514 }
515 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
516}
517
Felipe Leme4c2d6632016-09-28 14:32:00 -0700518static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800519 return false;
520}
521
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700522unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800524//
525// stat offsets
526// Name units description
527// ---- ----- -----------
528// read I/Os requests number of read I/Os processed
529#define __STAT_READ_IOS 0
530// read merges requests number of read I/Os merged with in-queue I/O
531#define __STAT_READ_MERGES 1
532// read sectors sectors number of sectors read
533#define __STAT_READ_SECTORS 2
534// read ticks milliseconds total wait time for read requests
535#define __STAT_READ_TICKS 3
536// write I/Os requests number of write I/Os processed
537#define __STAT_WRITE_IOS 4
538// write merges requests number of write I/Os merged with in-queue I/O
539#define __STAT_WRITE_MERGES 5
540// write sectors sectors number of sectors written
541#define __STAT_WRITE_SECTORS 6
542// write ticks milliseconds total wait time for write requests
543#define __STAT_WRITE_TICKS 7
544// in_flight requests number of I/Os currently in flight
545#define __STAT_IN_FLIGHT 8
546// io_ticks milliseconds total time this block device has been active
547#define __STAT_IO_TICKS 9
548// time_in_queue milliseconds total wait time for all requests
549#define __STAT_IN_QUEUE 10
550#define __STAT_NUMBER_FIELD 11
551//
552// read I/Os, write I/Os
553// =====================
554//
555// These values increment when an I/O request completes.
556//
557// read merges, write merges
558// =========================
559//
560// These values increment when an I/O request is merged with an
561// already-queued I/O request.
562//
563// read sectors, write sectors
564// ===========================
565//
566// These values count the number of sectors read from or written to this
567// block device. The "sectors" in question are the standard UNIX 512-byte
568// sectors, not any device- or filesystem-specific block size. The
569// counters are incremented when the I/O completes.
570#define SECTOR_SIZE 512
571//
572// read ticks, write ticks
573// =======================
574//
575// These values count the number of milliseconds that I/O requests have
576// waited on this block device. If there are multiple I/O requests waiting,
577// these values will increase at a rate greater than 1000/second; for
578// example, if 60 read requests wait for an average of 30 ms, the read_ticks
579// field will increase by 60*30 = 1800.
580//
581// in_flight
582// =========
583//
584// This value counts the number of I/O requests that have been issued to
585// the device driver but have not yet completed. It does not include I/O
586// requests that are in the queue but not yet issued to the device driver.
587//
588// io_ticks
589// ========
590//
591// This value counts the number of milliseconds during which the device has
592// had I/O requests queued.
593//
594// time_in_queue
595// =============
596//
597// This value counts the number of milliseconds that I/O requests have waited
598// on this block device. If there are multiple I/O requests waiting, this
599// value will increase as the product of the number of milliseconds times the
600// number of requests waiting (see "read ticks" above for an example).
601#define S_TO_MS 1000
602//
603
Mark Salyzyn326842f2015-04-30 09:49:41 -0700604static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800605 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700606 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700607 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700608 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700609 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700610 getline(&buffer, &i, fp);
611 fclose(fp);
612 if (!buffer) {
613 return -errno;
614 }
615 i = strlen(buffer);
616 while ((i > 0) && (buffer[i - 1] == '\n')) {
617 buffer[--i] = '\0';
618 }
619 if (!*buffer) {
620 free(buffer);
621 return 0;
622 }
623 z = true;
624 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800625 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700626 if (fields[i] != 0) {
627 z = false;
628 }
629 }
630 if (z) { /* never accessed */
631 free(buffer);
632 return 0;
633 }
634
Wei Wang509bb5d2017-06-09 14:42:12 -0700635 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
636 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700638
639 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
640 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
641 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700642 free(buffer);
643
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800644 if (fields[__STAT_IO_TICKS]) {
645 unsigned long read_perf = 0;
646 unsigned long read_ios = 0;
647 if (fields[__STAT_READ_TICKS]) {
648 unsigned long long divisor = fields[__STAT_READ_TICKS]
649 * fields[__STAT_IO_TICKS];
650 read_perf = ((unsigned long long)SECTOR_SIZE
651 * fields[__STAT_READ_SECTORS]
652 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
653 / divisor;
654 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
655 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
656 / divisor;
657 }
658
659 unsigned long write_perf = 0;
660 unsigned long write_ios = 0;
661 if (fields[__STAT_WRITE_TICKS]) {
662 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
663 * fields[__STAT_IO_TICKS];
664 write_perf = ((unsigned long long)SECTOR_SIZE
665 * fields[__STAT_WRITE_SECTORS]
666 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
667 / divisor;
668 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
669 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
670 / divisor;
671 }
672
673 unsigned queue = (fields[__STAT_IN_QUEUE]
674 + (fields[__STAT_IO_TICKS] >> 1))
675 / fields[__STAT_IO_TICKS];
676
677 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700678 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800679 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700680 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800681 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800682 }
683
684 /* bugreport timeout factor adjustment */
685 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
686 worst_write_perf = write_perf;
687 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700688 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700689 return 0;
690}
691
Yao Chenbe3bbc12018-01-17 16:31:10 -0800692static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
693
Tom Cherryf4472f32020-08-05 09:31:17 -0700694// Returns the actual readable size of the given buffer or -1 on error.
695static long logcat_buffer_readable_size(const std::string& buffer) {
696 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
697 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
698 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
699
700 return android_logger_get_log_readable_size(logger);
701}
702
703// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800704static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
705 unsigned long timeout_ms = 0;
706 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700707 long readable_size = logcat_buffer_readable_size(buffer);
708 if (readable_size > 0) {
709 // Engineering margin is ten-fold our guess.
710 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
711 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800712 }
713 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700714}
715
Nandana Duttd2f5f082019-01-18 17:13:52 +0000716Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
717}
718
719android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
720 std::lock_guard<std::mutex> lock(lock_);
721 result_ = APPROVED;
722 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800723
724 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
725 // consent is granted.
726 if (ds.options_->is_screenshot_copied) {
727 return android::binder::Status::ok();
728 }
729
730 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
731 !ds.do_early_screenshot_) {
732 return android::binder::Status::ok();
733 }
734
735 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
736 ds.options_->screenshot_fd.get());
737 ds.options_->is_screenshot_copied = copy_succeeded;
738 if (copy_succeeded) {
739 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
740 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000741 return android::binder::Status::ok();
742}
743
744android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
745 std::lock_guard<std::mutex> lock(lock_);
746 result_ = DENIED;
747 MYLOGW("User denied consent to share bugreport\n");
748 return android::binder::Status::ok();
749}
750
751UserConsentResult Dumpstate::ConsentCallback::getResult() {
752 std::lock_guard<std::mutex> lock(lock_);
753 return result_;
754}
755
756uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800757 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000758}
759
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700760void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700761 std::string build, fingerprint, radio, bootloader, network;
762 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700763
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700764 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
765 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700766 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
767 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
768 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700769 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700770
Felipe Lemed8b94e52016-12-08 10:21:44 -0800771 printf("========================================================\n");
772 printf("== dumpstate: %s\n", date);
773 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700774
Felipe Lemed8b94e52016-12-08 10:21:44 -0800775 printf("\n");
776 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700777 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800778 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
779 printf("Bootloader: %s\n", bootloader.c_str());
780 printf("Radio: %s\n", radio.c_str());
781 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100782 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
783 if (module_metadata_version != 0) {
784 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
785 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700786
Felipe Lemed8b94e52016-12-08 10:21:44 -0800787 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800788 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800789 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800790 printf("Uptime: ");
791 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
792 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800793 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao5377d792020-07-16 17:37:39 +0800794 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
795 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
796 options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800797 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800798}
799
Felipe Leme24b66ee2016-06-16 10:55:26 -0700800// List of file extensions that can cause a zip file attachment to be rejected by some email
801// service providers.
802static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
803 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
804 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
805 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
806};
807
Vishnu Naire97d6122018-01-18 13:58:56 -0800808status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
809 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700810 if (!IsZipping()) {
811 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
812 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800813 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800814 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700815 std::string valid_name = entry_name;
816
817 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700818 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700819 if (idx != std::string::npos) {
820 std::string extension = entry_name.substr(idx);
821 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
822 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
823 valid_name = entry_name + ".renamed";
824 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
825 }
826 }
827
Felipe Leme6fe9db62016-02-12 09:04:16 -0800828 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
829 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700830 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
831 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700832 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700833 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700834 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800835 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800836 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000837 bool finished_entry = false;
838 auto finish_entry = [this, &finished_entry] {
839 if (!finished_entry) {
840 // This should only be called when we're going to return an earlier error,
841 // which would've been logged. This may imply the file is already corrupt
842 // and any further logging from FinishEntry is more likely to mislead than
843 // not.
844 this->zip_writer_->FinishEntry();
845 }
846 };
847 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800848 auto start = std::chrono::steady_clock::now();
849 auto end = start + timeout;
850 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800851
Felipe Leme770410d2016-01-26 17:07:14 -0800852 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800853 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800854 if (timeout.count() > 0) {
855 // lambda to recalculate the timeout.
856 auto time_left_ms = [end]() {
857 auto now = std::chrono::steady_clock::now();
858 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
859 return std::max(diff.count(), 0LL);
860 };
861
862 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
863 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000864 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
865 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800866 return -errno;
867 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000868 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800869 entry_name.c_str(), strerror(errno), timeout.count());
870 return TIMED_OUT;
871 }
872 }
873
Zach Riggle22200402016-08-18 01:01:24 -0400874 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800875 if (bytes_read == 0) {
876 break;
877 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800878 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800879 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800880 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700881 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800882 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700883 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800884 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800885 }
886 }
887
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700888 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000889 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700890 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700891 MYLOGE("zip_writer_->FinishEntry(): %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
Vishnu Naire97d6122018-01-18 13:58:56 -0800895 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800896}
897
Felipe Leme1d486fe2016-10-14 18:06:47 -0700898bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
899 android::base::unique_fd fd(
900 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700901 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800902 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800903 return false;
904 }
905
Vishnu Naire97d6122018-01-18 13:58:56 -0800906 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800907}
908
909/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700910static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800911 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800912}
913
Felipe Leme1d486fe2016-10-14 18:06:47 -0700914void Dumpstate::AddDir(const std::string& dir, bool recursive) {
915 if (!IsZipping()) {
916 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800917 return;
918 }
Felipe Leme678727a2016-09-21 17:22:11 -0700919 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800920 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700921 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800922}
923
Felipe Leme1d486fe2016-10-14 18:06:47 -0700924bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
925 if (!IsZipping()) {
926 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
927 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800928 return false;
929 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800930 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700931 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700933 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700934 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800935 return false;
936 }
937
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700938 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700939 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700940 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700941 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800942 return false;
943 }
944
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700945 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700946 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700947 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800948 return false;
949 }
950
951 return true;
952}
953
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800954static void DoKmsg() {
955 struct stat st;
956 if (!stat(PSTORE_LAST_KMSG, &st)) {
957 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
958 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
959 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
960 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
961 } else {
962 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
963 DumpFile("LAST KMSG", "/proc/last_kmsg");
964 }
965}
966
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800967static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800968 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800969 RunCommand(
970 "KERNEL LOG",
971 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
972 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
973}
974
Nandana Duttdb379fa2019-10-09 16:54:41 +0100975static void DoSystemLogcat(time_t since) {
976 char since_str[80];
977 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
978
979 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
980 RunCommand("SYSTEM LOG",
981 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
982 since_str},
983 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
984}
985
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800986static void DoRadioLogcat() {
987 unsigned long timeout_ms = logcat_timeout({"radio"});
988 RunCommand(
989 "RADIO LOG",
990 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
991 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
992}
993
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800994static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800995 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800996 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
997 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800998 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100999 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -08001000 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1001 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -08001002 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001003 RunCommand(
1004 "EVENT LOG",
1005 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001006 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -08001007 timeout_ms = logcat_timeout({"stats"});
1008 RunCommand(
1009 "STATS LOG",
1010 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001011 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001012 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001013
1014 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1015
1016 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001017 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1018 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001019}
1020
Mike Ma5c267872019-08-21 11:31:34 -07001021static void DumpIncidentReport() {
1022 if (!ds.IsZipping()) {
1023 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1024 return;
1025 }
Mike Ma5c267872019-08-21 11:31:34 -07001026 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1027 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1028 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1029 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1030 if (fd < 0) {
1031 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1032 return;
1033 }
1034 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1035 bool empty = 0 == lseek(fd, 0, SEEK_END);
1036 if (!empty) {
1037 // Use a different name from "incident.proto"
1038 // /proto/incident.proto is reserved for incident service dump
1039 // i.e. metadata for debugging.
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001040 ds.EnqueueAddZipEntryAndCleanupIfNeeded(kProtoPath + "incident_report" + kProtoExt,
1041 path);
1042 } else {
1043 unlink(path.c_str());
Mike Ma5c267872019-08-21 11:31:34 -07001044 }
Mike Ma5c267872019-08-21 11:31:34 -07001045}
1046
Sunny Goyal35949782019-11-19 15:54:36 -08001047static void DumpVisibleWindowViews() {
1048 if (!ds.IsZipping()) {
1049 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1050 return;
1051 }
1052 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1053 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1054 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1055 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1056 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1057 if (fd < 0) {
1058 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1059 return;
1060 }
1061 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1062 CommandOptions::WithTimeout(120).Build());
1063 bool empty = 0 == lseek(fd, 0, SEEK_END);
1064 if (!empty) {
1065 ds.AddZipEntry("visible_windows.zip", path);
1066 } else {
1067 MYLOGW("Failed to dump visible windows\n");
1068 }
1069 unlink(path.c_str());
1070}
1071
Jayachandran Ca94c7172017-06-10 15:08:12 -07001072static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001073 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1074 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001075 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001076 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001077 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1078 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1079 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1080 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001081}
1082
David Andersond9ba4752018-12-11 18:26:59 -08001083static void DumpDynamicPartitionInfo() {
1084 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1085 return;
1086 }
1087
1088 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001089 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001090}
1091
Narayan Kamath8f788292017-05-25 13:20:39 +01001092static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1093 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1094 anr_traces_dir.c_str());
1095
1096 // If we're here, dump_traces_path will always be a temporary file
1097 // (created with mkostemp or similar) that contains dumps taken earlier
1098 // on in the process.
1099 if (dump_traces_path != nullptr) {
1100 if (add_to_zip) {
1101 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1102 } else {
1103 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1104 dump_traces_path);
1105 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1106 }
1107
1108 const int ret = unlink(dump_traces_path);
1109 if (ret == -1) {
1110 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1111 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001112 }
1113 }
1114
Narayan Kamathbd863722017-06-01 18:50:12 +01001115 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001116 if (ds.anr_data_.size() > 0) {
1117 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001118 "VM TRACES AT LAST ANR", add_to_zip);
1119
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001120 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1121 // it will be present in the body of the main entry if |add_to_zip| == false.
1122 //
1123 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001124 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001125 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001126 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001127 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1128 }
1129}
1130
1131static void AddAnrTraceFiles() {
1132 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1133
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001134 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001135
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001136 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001137
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001138 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1139
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001140 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001141 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001142 int i = 0;
1143 while (true) {
1144 const std::string slow_trace_path =
1145 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1146 if (stat(slow_trace_path.c_str(), &st)) {
1147 // No traces file at this index, done with the files.
1148 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001149 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001150 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1151 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001152 }
1153}
1154
Wei Wang509bb5d2017-06-09 14:42:12 -07001155static void DumpBlockStatFiles() {
1156 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001157
Wei Wang1dc1ef52017-06-12 11:28:37 -07001158 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1159
1160 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001161 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1162 return;
1163 }
1164
1165 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001166 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001167 if ((d->d_name[0] == '.')
1168 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1169 || (d->d_name[1] == '\0'))) {
1170 continue;
1171 }
1172 const std::string new_path =
1173 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1174 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1175 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1176 printf("\n");
1177 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001178 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001179}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001180
1181static void DumpPacketStats() {
1182 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1183 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1184 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1185 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1186 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1187}
1188
1189static void DumpIpAddrAndRules() {
1190 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1191 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1192 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1193 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1194 RunCommand("IP RULES", {"ip", "rule", "show"});
1195 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1196}
1197
Nandana Dutt5c390032019-03-12 10:52:56 +00001198static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1199 std::chrono::milliseconds timeout,
1200 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001201 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001202 sp<android::IServiceManager> sm = defaultServiceManager();
1203 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001204 Vector<String16> args;
1205 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001206 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1207 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001208 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001209 std::string path(title);
1210 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001211 size_t bytes_written = 0;
Steven Moreland5a30d342019-10-08 13:53:28 -07001212 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001213 if (status == OK) {
1214 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1215 std::chrono::duration<double> elapsed_seconds;
1216 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1217 /* as_proto = */ false, elapsed_seconds, bytes_written);
Vishnu Naire97d6122018-01-18 13:58:56 -08001218 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1219 bool dump_complete = (status == OK);
1220 dumpsys.stopDumpThread(dump_complete);
1221 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001222
1223 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1224 std::chrono::steady_clock::now() - start);
1225 if (elapsed_duration > timeout) {
1226 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1227 elapsed_duration.count());
1228 break;
1229 }
1230 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001231 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001232}
1233
Vishnu Nair64afc022018-02-01 15:29:34 -08001234static void RunDumpsysText(const std::string& title, int priority,
1235 std::chrono::milliseconds timeout,
1236 std::chrono::milliseconds service_timeout) {
1237 DurationReporter duration_reporter(title);
1238 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1239 fsync(STDOUT_FILENO);
1240 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1241}
1242
1243/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001244static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1245 std::chrono::milliseconds timeout,
1246 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001247 DurationReporter duration_reporter(title);
1248 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1249 fsync(STDOUT_FILENO);
1250 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1251 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001252
1253 RETURN_IF_USER_DENIED_CONSENT();
1254
1255 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1256 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001257}
1258
Nandana Dutt5c390032019-03-12 10:52:56 +00001259static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1260 std::chrono::milliseconds timeout,
1261 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001262 if (!ds.IsZipping()) {
1263 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001264 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001265 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 sp<android::IServiceManager> sm = defaultServiceManager();
1267 Dumpsys dumpsys(sm.get());
1268 Vector<String16> args;
1269 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1270 DurationReporter duration_reporter(title);
1271
1272 auto start = std::chrono::steady_clock::now();
1273 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1274 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001275 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001276 std::string path(kProtoPath);
1277 path.append(String8(service).c_str());
1278 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1279 path.append("_CRITICAL");
1280 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1281 path.append("_HIGH");
1282 }
1283 path.append(kProtoExt);
Steven Moreland5a30d342019-10-08 13:53:28 -07001284 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001285 if (status == OK) {
1286 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1287 bool dumpTerminated = (status == OK);
1288 dumpsys.stopDumpThread(dumpTerminated);
1289 }
1290 ZipWriter::FileEntry file_entry;
1291 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001292
1293 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1294 std::chrono::steady_clock::now() - start);
1295 if (elapsed_duration > timeout) {
1296 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1297 elapsed_duration.count());
1298 break;
1299 }
1300 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001301 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001302}
1303
Nandana Dutta7db6342018-11-21 14:53:34 +00001304// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001305static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001306 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1307 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001308
1309 RETURN_IF_USER_DENIED_CONSENT();
1310
1311 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1312 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001313}
1314
1315// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001316static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001317 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1318 // high priority. Reduce timeout once they are able to dump in a shorter time or
1319 // moved to a parallel task.
1320 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1321 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001322
1323 RETURN_IF_USER_DENIED_CONSENT();
1324
1325 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1326 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001327}
1328
1329// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001330static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001331 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001332
1333 RETURN_IF_USER_DENIED_CONSENT();
1334
1335 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1336 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001337}
1338
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001339/*
1340 * |out_fd| A fd to support the DumpPool to output results to a temporary file.
1341 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO
1342 * if it's not running in the parallel task.
1343 */
1344static void DumpHals(int out_fd = STDOUT_FILENO) {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001345 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001346 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001347 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1348 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001349 return;
1350 }
Yifan Hong30528a22020-08-07 18:24:06 -07001351 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001352 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build(),
1353 false, out_fd);
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001354
Steven Moreland44cd9482018-01-04 16:24:13 -08001355 using android::hidl::manager::V1_0::IServiceManager;
1356 using android::hardware::defaultServiceManager;
1357
1358 sp<IServiceManager> sm = defaultServiceManager();
1359 if (sm == nullptr) {
1360 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1361 return;
1362 }
1363
1364 auto ret = sm->list([&](const auto& interfaces) {
1365 for (const std::string& interface : interfaces) {
1366 std::string cleanName = interface;
1367 std::replace_if(cleanName.begin(),
1368 cleanName.end(),
1369 [](char c) {
1370 return !isalnum(c) &&
1371 std::string("@-_:.").find(c) == std::string::npos;
1372 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001373 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001374
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001375 bool empty = false;
Steven Moreland44cd9482018-01-04 16:24:13 -08001376 {
1377 auto fd = android::base::unique_fd(
1378 TEMP_FAILURE_RETRY(open(path.c_str(),
1379 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1380 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1381 if (fd < 0) {
1382 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1383 continue;
1384 }
1385 RunCommandToFd(fd,
1386 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001387 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001388 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1389
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001390 empty = 0 == lseek(fd, 0, SEEK_END);
Steven Moreland44cd9482018-01-04 16:24:13 -08001391 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001392 if (!empty) {
1393 ds.EnqueueAddZipEntryAndCleanupIfNeeded("lshal-debug/" + cleanName + ".txt",
1394 path);
1395 } else {
1396 unlink(path.c_str());
1397 }
Steven Moreland44cd9482018-01-04 16:24:13 -08001398 }
1399 });
1400
1401 if (!ret.isOk()) {
1402 MYLOGE("Could not list hals from hwservicemanager.\n");
1403 }
1404}
1405
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001406static void DumpExternalFragmentationInfo() {
1407 struct stat st;
1408 if (stat("/proc/buddyinfo", &st) != 0) {
1409 MYLOGE("Unable to dump external fragmentation info\n");
1410 return;
1411 }
1412
1413 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1414 std::ifstream ifs("/proc/buddyinfo");
1415 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1416 for (std::string line; std::getline(ifs, line);) {
1417 std::smatch match_results;
1418 if (std::regex_match(line, match_results, unusable_index_regex)) {
1419 std::stringstream free_pages(std::string{match_results[3]});
1420 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1421 std::istream_iterator<int>());
1422
1423 int total_free_pages = 0;
1424 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1425 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1426 }
1427
1428 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1429 match_results[2].str().c_str());
1430
1431 int usable_free_pages = total_free_pages;
1432 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1433 auto unusable_index = (total_free_pages - usable_free_pages) /
1434 static_cast<double>(total_free_pages);
1435 printf(" %5.3f", unusable_index);
1436 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1437 }
1438
1439 printf("\n");
1440 }
1441 }
1442 printf("\n");
1443}
1444
mhasankd451a472020-05-26 18:02:39 -07001445static void DumpstateLimitedOnly() {
1446 // Trimmed-down version of dumpstate to only include a whitelisted
1447 // set of logs (system log, event log, and system server / system app
1448 // crashes, and networking logs). See b/136273873 and b/138459828
1449 // for context.
1450 DurationReporter duration_reporter("DUMPSTATE");
1451 unsigned long timeout_ms;
1452 // calculate timeout
1453 timeout_ms = logcat_timeout({"main", "system", "crash"});
1454 RunCommand("SYSTEM LOG",
1455 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1456 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1457 timeout_ms = logcat_timeout({"events"});
1458 RunCommand(
1459 "EVENT LOG",
1460 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1461 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1462
1463 printf("========================================================\n");
1464 printf("== Networking Service\n");
1465 printf("========================================================\n");
1466
1467 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1468 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1469
1470 printf("========================================================\n");
1471 printf("== Dropbox crashes\n");
1472 printf("========================================================\n");
1473
1474 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1475 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1476
1477 printf("========================================================\n");
1478 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1479 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1480 printf("========================================================\n");
1481 printf("== dumpstate: done (id %d)\n", ds.id_);
1482 printf("========================================================\n");
1483}
1484
Nandana Dutt5c390032019-03-12 10:52:56 +00001485// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1486// via the consent they are shown. Ignores other errors that occur while running various
1487// commands. The consent checking is currently done around long running tasks, which happen to
1488// be distributed fairly evenly throughout the function.
1489static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001490 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001491
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001492 // Enqueue slow functions into the thread pool, if the parallel run is enabled.
1493 if (ds.dump_pool_) {
1494 // Pool was shutdown in DumpstateDefaultAfterCritical method in order to
1495 // drop root user. Restarts it with two threads for the parallel run.
1496 ds.dump_pool_->start(/* thread_counts = */2);
1497
1498 ds.dump_pool_->enqueueTaskWithFd(DUMP_HALS_TASK, &DumpHals, _1);
1499 ds.dump_pool_->enqueueTask(DUMP_INCIDENT_REPORT_TASK, &DumpIncidentReport);
1500 ds.dump_pool_->enqueueTaskWithFd(DUMP_BOARD_TASK, &Dumpstate::DumpstateBoard, &ds, _1);
1501 }
1502
Nandana Dutt5c390032019-03-12 10:52:56 +00001503 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1504 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1505 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001506 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001507 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001508 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001509 DumpFile("MEMORY INFO", "/proc/meminfo");
1510 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001511 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001512
1513 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1514
Sunny Goyal35949782019-11-19 15:54:36 -08001515 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1516
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001517 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1518 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1519 DumpFile("SLAB INFO", "/proc/slabinfo");
1520 DumpFile("ZONEINFO", "/proc/zoneinfo");
1521 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1522 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001523 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001524
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001525 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1526 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001527
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001528 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001529 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001530
1531 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1532 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001533
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001534 if (ds.dump_pool_) {
1535 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_HALS_TASK, ds.dump_pool_);
1536 } else {
1537 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_HALS_TASK, DumpHals);
1538 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001539
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001540 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001541 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001542 struct stat s;
1543 if (stat("/proc/modules", &s) != 0) {
1544 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1545 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001546 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001547 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001548
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001549 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001550 DoKernelLogcat();
1551 } else {
1552 do_dmesg();
1553 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001554
Felipe Lemef0292972016-11-22 13:57:05 -08001555 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001556
1557 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1558
Jeff Brown1dc94e32014-09-11 14:15:27 -07001559 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001560 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001561
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001562 /* Dump Bluetooth HCI logs */
1563 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001564
Paul Chang0d2aad72020-02-13 20:04:03 +08001565 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001566 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001567 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001568 }
1569
Felipe Lemee184f662016-10-27 10:04:47 -07001570 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001571
Narayan Kamath8f788292017-05-25 13:20:39 +01001572 // NOTE: tombstones are always added as separate entries in the zip archive
1573 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001574 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001575 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001576 if (!tombstones_dumped) {
1577 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001578 }
1579
Jayachandran Ca94c7172017-06-10 15:08:12 -07001580 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001581
Chenbo Feng276a3b62018-08-07 11:44:49 -07001582 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1583
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001584 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001585
Jayachandran Ca94c7172017-06-10 15:08:12 -07001586 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001587
1588 dump_route_tables();
1589
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001590 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1591 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1592 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001593
Nandana Dutt5c390032019-03-12 10:52:56 +00001594 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001595
Elliott Hughes23ccc622017-02-28 10:14:22 -08001596 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001597
Jin Qianf334d662017-10-10 14:41:37 -07001598 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001599
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001600 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001601
Colin Crossf45fa6b2012-03-26 12:38:26 -07001602 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001603 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1604 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1605
1606 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1607 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1608 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1609 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1610 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001611
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001612 /* Add window and surface trace files. */
1613 if (!PropertiesHelper::IsUserBuild()) {
1614 ds.AddDir(WMTRACE_DATA_DIR, false);
1615 }
1616
Yifan Hongd90cc652020-02-08 16:52:02 -08001617 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1618
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001619 if (ds.dump_pool_) {
1620 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_BOARD_TASK, ds.dump_pool_);
1621 } else {
1622 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_BOARD_TASK, ds.DumpstateBoard);
1623 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001624
Steven Moreland7440ddb2016-12-15 16:13:39 -08001625 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001626 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1627 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001628 // su does not exist on user builds, so try running without it.
1629 // This way any implementations of vril-dump that do not require
1630 // root can run on user builds.
1631 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001632 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001633 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001634 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001635 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001636 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001637 }
1638
Felipe Lemed8b94e52016-12-08 10:21:44 -08001639 printf("========================================================\n");
1640 printf("== Android Framework Services\n");
1641 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001642
Nandana Dutt5c390032019-03-12 10:52:56 +00001643 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001644
Felipe Lemed8b94e52016-12-08 10:21:44 -08001645 printf("========================================================\n");
1646 printf("== Checkins\n");
1647 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001648
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001649 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001650
1651 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1652
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001653 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1654 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1655 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1656 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001657
Felipe Lemed8b94e52016-12-08 10:21:44 -08001658 printf("========================================================\n");
1659 printf("== Running Application Activities\n");
1660 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001661
Makoto Onuki60780982018-04-16 15:34:00 -07001662 // The following dumpsys internally collects output from running apps, so it can take a long
1663 // time. So let's extend the timeout.
1664
1665 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1666
1667 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001668
Felipe Lemed8b94e52016-12-08 10:21:44 -08001669 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001670 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001671 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001672
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001673 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001674 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001675
Felipe Lemed8b94e52016-12-08 10:21:44 -08001676 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001677 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001678 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001679
Makoto Onuki60780982018-04-16 15:34:00 -07001680 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1681 DUMPSYS_COMPONENTS_OPTIONS);
1682
1683 printf("========================================================\n");
1684 printf("== Running Application Providers (platform)\n");
1685 printf("========================================================\n");
1686
1687 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1688 DUMPSYS_COMPONENTS_OPTIONS);
1689
1690 printf("========================================================\n");
1691 printf("== Running Application Providers (non-platform)\n");
1692 printf("========================================================\n");
1693
1694 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1695 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001696
Adrian Roos8b397ab2017-04-04 16:35:44 -07001697 printf("========================================================\n");
1698 printf("== Dropbox crashes\n");
1699 printf("========================================================\n");
1700
1701 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1702 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1703
Felipe Lemed8b94e52016-12-08 10:21:44 -08001704 printf("========================================================\n");
1705 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1706 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1707 printf("========================================================\n");
1708 printf("== dumpstate: done (id %d)\n", ds.id_);
1709 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001710
1711 printf("========================================================\n");
1712 printf("== Obtaining statsd metadata\n");
1713 printf("========================================================\n");
1714 // This differs from the usual dumpsys stats, which is the stats report data.
1715 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001716
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001717 // Add linker configuration directory
1718 ds.AddDir(LINKERCONFIG_DIR, true);
1719
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001720 if (ds.dump_pool_) {
1721 WAIT_TASK_WITH_CONSENT_CHECK(DUMP_INCIDENT_REPORT_TASK, ds.dump_pool_);
1722 } else {
1723 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_INCIDENT_REPORT_TASK,
1724 DumpIncidentReport);
1725 }
Mike Ma5c267872019-08-21 11:31:34 -07001726
Nandana Dutt5c390032019-03-12 10:52:56 +00001727 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001728}
1729
Nandana Dutt5c390032019-03-12 10:52:56 +00001730/*
1731 * Dumps state for the default case; drops root after it's no longer necessary.
1732 *
1733 * Returns RunStatus::OK if everything went fine.
1734 * Returns RunStatus::ERROR if there was an error.
1735 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1736 * with the caller.
1737 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001738Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001739 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1740 // buffer.
1741 DoLogcat();
1742 // Capture timestamp after first logcat to use in next logcat
1743 time_t logcat_ts = time(nullptr);
1744
Nandana Dutt4be45d12018-09-26 15:04:23 +01001745 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao5377d792020-07-16 17:37:39 +08001746 if (dump_pool_) {
1747 RETURN_IF_USER_DENIED_CONSENT();
1748 // One thread is enough since we only need to enqueue DumpTraces here.
1749 dump_pool_->start(/* thread_counts = */1);
1750
1751 // DumpTraces takes long time, post it to the another thread in the
1752 // pool, if pool is available
1753 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1754 } else {
1755 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1756 &dump_traces_path);
1757 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001758
1759 /* Run some operations that require root. */
1760 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1761 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1762
1763 ds.AddDir(RECOVERY_DIR, true);
1764 ds.AddDir(RECOVERY_DATA_DIR, true);
1765 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1766 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1767 if (!PropertiesHelper::IsUserBuild()) {
1768 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1769 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001770 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001771 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001772 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001773 add_mountinfo();
1774 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001775 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001776 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001777
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001778 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001779 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1780
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001781 // Dump IPsec stats. No keys are exposed here.
1782 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1783
Nandana Dutt4be45d12018-09-26 15:04:23 +01001784 // Run ss as root so we can see socket marks.
1785 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1786
1787 // Run iotop as root to show top 100 IO threads
1788 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1789
Erick Reyese68df822019-02-11 14:46:36 -08001790 // Gather shared memory buffer info if the product implements it
1791 struct stat st;
1792 if (!stat("/product/bin/dmabuf_dump", &st)) {
1793 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1794 }
1795
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001796 DumpFile("PSI cpu", "/proc/pressure/cpu");
1797 DumpFile("PSI memory", "/proc/pressure/memory");
1798 DumpFile("PSI io", "/proc/pressure/io");
1799
Rhed Jao5377d792020-07-16 17:37:39 +08001800 if (dump_pool_) {
1801 RETURN_IF_USER_DENIED_CONSENT();
1802 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1803
1804 // Current running thread in the pool is the root user also. Shutdown
1805 // the pool and restart later to ensure all threads in the pool could
1806 // drop the root user.
1807 dump_pool_->shutdown();
1808 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001809 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001810 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001811 }
1812
Nandana Dutt5c390032019-03-12 10:52:56 +00001813 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001814 Dumpstate::RunStatus status = dumpstate();
1815 // Capture logcat since the last time we did it.
1816 DoSystemLogcat(logcat_ts);
1817 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001818}
1819
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001820// This method collects common dumpsys for telephony and wifi. Typically, wifi
1821// reports are fine to include all information, but telephony reports on user
1822// builds need to strip some content (see DumpstateTelephonyOnly).
1823static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001824 DumpIpTablesAsRoot();
1825
Jayachandran Cb4389d92019-07-08 09:46:05 -07001826 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1827
Jayachandran Ca94c7172017-06-10 15:08:12 -07001828 if (!DropRootUser()) {
1829 return;
1830 }
1831
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001832 // We need to be picky about some stuff for telephony reports on user builds.
1833 if (!include_sensitive_info) {
1834 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1835 DoRadioLogcat();
1836 } else {
1837 // Contains various system properties and process startup info.
1838 do_dmesg();
1839 // Logs other than the radio buffer may contain package/component names and potential PII.
1840 DoLogcat();
1841 // Too broad for connectivity problems.
1842 DoKmsg();
1843 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08001844 // TODO(b/136262402) Using thread pool for DumpHals
1845 RUN_SLOW_FUNCTION_AND_LOG(DUMP_HALS_TASK, DumpHals);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001846 }
1847
Jayachandran Ca94c7172017-06-10 15:08:12 -07001848 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001849 DumpIpAddrAndRules();
1850 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001851 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1852 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001853}
1854
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001855// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1856// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1857// for what can be included on user builds: all reported information MUST directly relate to
1858// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1859// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1860// names are not), and MUST NOT contain logs of user application traffic.
1861// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001862static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001863 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001864
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001865 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001866
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001867 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001868
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001869 DumpstateRadioCommon(include_sensitive_info);
1870
1871 if (include_sensitive_info) {
1872 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1873 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1874 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1875 // way.
1876 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1877 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001878
1879 printf("========================================================\n");
1880 printf("== Android Framework Services\n");
1881 printf("========================================================\n");
1882
Vishnu Nair652cc802017-11-30 15:18:30 -08001883 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1884 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001885 if (include_sensitive_info) {
1886 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1887 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1888 SEC_TO_MSEC(10));
1889 } else {
1890 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1891 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1892 // give a higher timeout as well.
1893 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1894 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1895 }
1896 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001897 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1898 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001899 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001900 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1901 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001902 if (include_sensitive_info) {
1903 // Contains raw IP addresses, omit from reports on user builds.
1904 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1905 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1906 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1907 SEC_TO_MSEC(10));
1908 // Contains package/component names, omit from reports on user builds.
1909 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1910 SEC_TO_MSEC(10));
1911 // Contains package names, but should be relatively simple to remove them (also contains
1912 // UIDs already), omit from reports on user builds.
1913 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1914 SEC_TO_MSEC(10));
1915 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001916
1917 printf("========================================================\n");
1918 printf("== Running Application Services\n");
1919 printf("========================================================\n");
1920
1921 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1922
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001923 if (include_sensitive_info) {
1924 printf("========================================================\n");
1925 printf("== Running Application Services (non-platform)\n");
1926 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001927
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001928 // Contains package/component names and potential PII, omit from reports on user builds.
1929 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1930 // carrier_config dumpsys instead.
1931 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1932 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001933
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001934 printf("========================================================\n");
1935 printf("== Checkins\n");
1936 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001937
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001938 // Contains package/component names, omit from reports on user builds.
1939 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1940 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001941
1942 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001943 printf("== dumpstate: done (id %d)\n", ds.id_);
1944 printf("========================================================\n");
1945}
1946
mukesh agrawal253dad42018-01-23 21:59:59 -08001947// This method collects dumpsys for wifi debugging only
1948static void DumpstateWifiOnly() {
1949 DurationReporter duration_reporter("DUMPSTATE");
1950
1951 DumpstateRadioCommon();
1952
1953 printf("========================================================\n");
1954 printf("== Android Framework Services\n");
1955 printf("========================================================\n");
1956
1957 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1958 SEC_TO_MSEC(10));
1959 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1960 SEC_TO_MSEC(10));
1961
1962 printf("========================================================\n");
1963 printf("== dumpstate: done (id %d)\n", ds.id_);
1964 printf("========================================================\n");
1965}
1966
Nandana Duttcf419a72019-03-14 10:40:17 +00001967Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001968 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1969 const size_t buf_size = temp_file_pattern.length() + 1;
1970 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1971 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1972
1973 // Create a new, empty file to receive all trace dumps.
1974 //
1975 // TODO: This can be simplified once we remove support for the old style
1976 // dumps. We can have a file descriptor passed in to dump_traces instead
1977 // of creating a file, closing it and then reopening it again.
1978 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1979 if (fd < 0) {
1980 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001981 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001982 }
1983
1984 // Nobody should have access to this temporary file except dumpstate, but we
1985 // temporarily grant 'read' to 'others' here because this file is created
1986 // when tombstoned is still running as root, but dumped after dropping. This
1987 // can go away once support for old style dumping has.
1988 const int chmod_ret = fchmod(fd, 0666);
1989 if (chmod_ret < 0) {
1990 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001991 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001992 }
1993
1994 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1995 if (proc.get() == nullptr) {
1996 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001997 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001998 }
1999
2000 // Number of times process dumping has timed out. If we encounter too many
2001 // failures, we'll give up.
2002 int timeout_failures = 0;
2003 bool dalvik_found = false;
2004
2005 const std::set<int> hal_pids = get_interesting_hal_pids();
2006
2007 struct dirent* d;
2008 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00002009 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00002010 int pid = atoi(d->d_name);
2011 if (pid <= 0) {
2012 continue;
2013 }
2014
2015 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
2016 std::string exe;
2017 if (!android::base::Readlink(link_name, &exe)) {
2018 continue;
2019 }
2020
2021 bool is_java_process;
2022 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
2023 // Don't bother dumping backtraces for the zygote.
2024 if (IsZygote(pid)) {
2025 continue;
2026 }
2027
2028 dalvik_found = true;
2029 is_java_process = true;
2030 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
2031 is_java_process = false;
2032 } else {
2033 // Probably a native process we don't care about, continue.
2034 continue;
2035 }
2036
2037 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
2038 if (timeout_failures == 3) {
2039 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
2040 break;
2041 }
2042
2043 const uint64_t start = Nanotime();
2044 const int ret = dump_backtrace_to_file_timeout(
2045 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2046 is_java_process ? 5 : 20, fd);
2047
2048 if (ret == -1) {
2049 // For consistency, the header and footer to this message match those
2050 // dumped by debuggerd in the success case.
2051 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2052 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2053 dprintf(fd, "---- end %d ----", pid);
2054 timeout_failures++;
2055 continue;
2056 }
2057
2058 // We've successfully dumped stack traces, reset the failure count
2059 // and write a summary of the elapsed time to the file and continue with the
2060 // next process.
2061 timeout_failures = 0;
2062
2063 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2064 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2065 }
2066
2067 if (!dalvik_found) {
2068 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2069 }
2070
Nandana Duttcf419a72019-03-14 10:40:17 +00002071 *path = file_name_buf.release();
2072 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002073}
2074
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002075void Dumpstate::DumpstateBoard(int out_fd) {
2076 dprintf(out_fd, "========================================================\n");
2077 dprintf(out_fd, "== Board\n");
2078 dprintf(out_fd, "========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002079
Felipe Leme6f674ae2016-11-18 17:10:33 -08002080 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002081 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002082 return;
2083 }
2084
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002085 std::vector<std::string> paths;
2086 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002087 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002088 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2089 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002090 remover.emplace_back(android::base::make_scope_guard(
2091 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002092 }
Jie Song9fbfad02017-06-20 16:29:42 -07002093
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002094 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2095 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002096 MYLOGE("No IDumpstateDevice implementation\n");
2097 return;
2098 }
2099
2100 using ScopedNativeHandle =
2101 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2102 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2103 [](native_handle_t* handle) {
2104 native_handle_close(handle);
2105 native_handle_delete(handle);
2106 });
2107 if (handle == nullptr) {
2108 MYLOGE("Could not create native_handle\n");
2109 return;
2110 }
2111
Nandana Dutt5c390032019-03-12 10:52:56 +00002112 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002113 for (size_t i = 0; i < paths.size(); i++) {
2114 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2115
2116 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2117 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2118 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2119 if (fd < 0) {
2120 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2121 return;
2122 }
2123 handle.get()->data[i] = fd.release();
2124 }
2125
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002126 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2127 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2128 // will kill the HAL and grab whatever it dumped in time.
2129 constexpr size_t timeout_sec = 30;
2130 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2131 // implement just 1.0.
2132 const char* descriptor_to_kill;
2133 using DumpstateBoardTask = std::packaged_task<bool()>;
2134 DumpstateBoardTask dumpstate_board_task;
2135 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2136 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2137 if (dumpstate_device_1_1 != nullptr) {
2138 MYLOGI("Using IDumpstateDevice v1.1");
2139 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2140 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2141 ::android::hardware::Return<DumpstateStatus> status =
2142 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2143 SEC_TO_MSEC(timeout_sec));
2144 if (!status.isOk()) {
2145 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2146 return false;
2147 } else if (status != DumpstateStatus::OK) {
2148 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2149 return false;
2150 }
2151 return true;
2152 });
2153 } else {
2154 MYLOGI("Using IDumpstateDevice v1.0");
2155 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2156 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2157 ::android::hardware::Return<void> status =
2158 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002159 if (!status.isOk()) {
2160 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002161 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002162 }
Wei Wang587eac92018-04-05 12:17:20 -07002163 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002164 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002165 }
2166 auto result = dumpstate_board_task.get_future();
2167 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002168
Wei Wang587eac92018-04-05 12:17:20 -07002169 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2170 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002171 if (!android::base::SetProperty(
2172 "ctl.interface_restart",
2173 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002174 MYLOGE("Couldn't restart dumpstate HAL\n");
2175 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002176 }
Wei Wang587eac92018-04-05 12:17:20 -07002177 // Wait some time for init to kill dumpstate vendor HAL
2178 constexpr size_t killing_timeout_sec = 10;
2179 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2180 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2181 "there might be racing in content\n", killing_timeout_sec);
2182 }
2183
2184 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2185 for (size_t i = 0; i < paths.size(); i++) {
2186 struct stat s;
2187 if (fstat(handle.get()->data[i], &s) == -1) {
2188 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2189 strerror(errno));
2190 file_sizes[i] = -1;
2191 continue;
2192 }
2193 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002194 }
2195
2196 for (size_t i = 0; i < paths.size(); i++) {
2197 if (file_sizes[i] == -1) {
2198 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002199 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002200 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002201 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002202 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002203 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002204 remover[i].Disable();
2205 EnqueueAddZipEntryAndCleanupIfNeeded(kDumpstateBoardFiles[i], paths[i]);
2206 dprintf(out_fd, "*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002207 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002208}
2209
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002210static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002211 fprintf(stderr,
mhasank2d75c442020-06-11 15:05:25 -07002212 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-d] [-p] "
mhasankd451a472020-05-26 18:02:39 -07002213 "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002214 " -h: display this help message\n"
2215 " -b: play sound file instead of vibrate, at beginning of job\n"
2216 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002217 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002218 " -d: append date to filename\n"
2219 " -p: capture screenshot to filename.png\n"
2220 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002221 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002222 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002223 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002224 " -P: send broadcast when started and do progress updates\n"
2225 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002226 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002227 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002228 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002229}
2230
Wei Liuf87959e2016-08-26 14:51:42 -07002231static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002232 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002233}
2234
Felipe Leme1d486fe2016-10-14 18:06:47 -07002235bool Dumpstate::FinishZipFile() {
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002236 // Runs all enqueued adding zip entry and cleanup tasks before finishing the zip file.
2237 if (zip_entry_tasks_) {
2238 zip_entry_tasks_->run(/* do_cancel = */false);
2239 }
2240
Felipe Leme9a523ae2016-10-20 15:10:33 -07002241 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002242 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002243 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002244 // Final timestamp
2245 char date[80];
2246 time_t the_real_now_please_stand_up = time(nullptr);
2247 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002248 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002249 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002250
Felipe Leme9a523ae2016-10-20 15:10:33 -07002251 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002252 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002253 return false;
2254 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002255 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002256 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002257 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002258 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002259
Felipe Leme0f3fb202016-06-10 17:10:53 -07002260 // Add log file (which contains stderr output) to zip...
2261 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002262 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002263 MYLOGE("Failed to add dumpstate log to .zip file\n");
2264 return false;
2265 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002266 // TODO: Should truncate the existing file.
2267 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002268 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2269 return false;
2270 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002271 fprintf(stderr, "\n");
2272
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002273 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002274 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002275 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002276 return false;
2277 }
2278
Felipe Leme1d486fe2016-10-14 18:06:47 -07002279 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2280 ds.zip_file.reset(nullptr);
2281
Felipe Lemee9d2c542016-11-15 11:48:26 -08002282 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002283 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002284
Felipe Leme1e9edc62015-12-21 16:02:13 -08002285 return true;
2286}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002287
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002288static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2289 // clang-format off
2290 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2291 "--receiver-foreground", "--receiver-include-background", "-a", action};
2292 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002293
2294 am.insert(am.end(), args.begin(), args.end());
2295
Felipe Leme8d2410e2017-02-08 09:46:08 -08002296 RunCommand("", am,
2297 CommandOptions::WithTimeout(20)
2298 .Log("Sending broadcast: '%s'\n")
2299 .Always()
2300 .DropRoot()
2301 .RedirectStderr()
2302 .Build());
2303}
2304
Felipe Leme35b8cf12017-02-10 15:47:29 -08002305static void Vibrate(int duration_ms) {
2306 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002307 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002308 CommandOptions::WithTimeout(10)
2309 .Log("Vibrate: '%s'\n")
2310 .Always()
2311 .Build());
2312 // clang-format on
2313}
2314
Nandana Dutt979388e2018-11-30 16:48:55 +00002315static void MaybeResolveSymlink(std::string* path) {
2316 std::string resolved_path;
2317 if (android::base::Readlink(*path, &resolved_path)) {
2318 *path = resolved_path;
2319 }
2320}
2321
Nandana Dutt4be45d12018-09-26 15:04:23 +01002322/*
2323 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2324 * if we are writing zip files and adds the version file.
2325 */
2326static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002327 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2328
Nandana Dutt4be45d12018-09-26 15:04:23 +01002329 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2330 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002331 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002332 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002333 char date[80];
2334 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2335 ds.name_ = date;
2336 } else {
2337 ds.name_ = "undated";
2338 }
2339
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002340 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002341 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002342 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002343 ds.base_name_ += "-wifi";
2344 }
2345
Paul Chang0d2aad72020-02-13 20:04:03 +08002346 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002347 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002348 }
2349 ds.tmp_path_ = ds.GetPath(".tmp");
2350 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2351
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002352 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002353 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002354 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002355 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002356 "Bugreport dir: [%s] "
2357 "Base name: [%s] "
2358 "Suffix: [%s] "
2359 "Log path: [%s] "
2360 "Temporary path: [%s] "
2361 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002362 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2363 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002364
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002365 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002366 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002367 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2368 create_parent_dirs(ds.path_.c_str());
2369 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2370 if (ds.zip_file == nullptr) {
2371 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2372 } else {
2373 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2374 }
2375 ds.AddTextZipEntry("version.txt", ds.version_);
2376 }
2377}
2378
2379/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002380 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002381 * printing zipped file status, etc.
2382 */
2383static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002384 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002385 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002386 if (!ds.FinishZipFile()) {
2387 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2388 do_text_file = true;
2389 } else {
2390 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002391 }
2392 }
mhasank2d75c442020-06-11 15:05:25 -07002393
2394 std::string final_path = ds.path_;
2395 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002396 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002397 android::os::CopyFileToFile(ds.path_, final_path);
2398 }
2399
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002400 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002401 if (do_text_file) {
2402 dprintf(ds.control_socket_fd_,
2403 "FAIL:could not create zip file, check %s "
2404 "for more details\n",
2405 ds.log_path_.c_str());
2406 } else {
mhasank2d75c442020-06-11 15:05:25 -07002407 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002408 }
2409 }
2410}
2411
Nandana Dutt4be45d12018-09-26 15:04:23 +01002412
Nandana Dutt58d72e22018-11-16 10:30:48 +00002413static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2414 switch (mode) {
2415 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2416 return "BUGREPORT_FULL";
2417 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2418 return "BUGREPORT_INTERACTIVE";
2419 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2420 return "BUGREPORT_REMOTE";
2421 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2422 return "BUGREPORT_WEAR";
2423 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2424 return "BUGREPORT_TELEPHONY";
2425 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2426 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002427 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2428 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002429 }
2430}
2431
Paul Changf59c2b72020-03-10 02:08:55 +08002432static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2433 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002434 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2435 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002436 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002437 switch (mode) {
2438 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002439 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002440 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002441 break;
2442 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002443 // Currently, the dumpstate binder is only used by Shell to update progress.
2444 options->do_start_service = true;
2445 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002446 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002447 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002448 break;
2449 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002450 options->do_vibrate = false;
2451 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002452 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002453 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002454 break;
2455 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002456 options->do_start_service = true;
2457 options->do_progress_updates = true;
2458 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002459 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002460 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002461 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002462 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002463 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002464 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002465 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002466 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002467 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002468 break;
2469 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002470 options->wifi_only = true;
2471 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002472 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002473 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002474 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002475 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2476 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002477 }
2478}
2479
Nandana Dutt58d72e22018-11-16 10:30:48 +00002480static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002481 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002482 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002483 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002484 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002485 "limited_only: %d args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002486 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002487 options.do_screenshot, options.is_remote_mode, options.show_header_only,
mhasankd451a472020-05-26 18:02:39 -07002488 options.do_start_service, options.telephony_only, options.wifi_only,
2489 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2490 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002491}
2492
Nandana Dutt54dbd672019-01-11 12:58:05 +00002493void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2494 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002495 const android::base::unique_fd& screenshot_fd_in,
2496 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002497 // In the new API world, date is always added; output is always a zip file.
2498 // TODO(111441001): remove these options once they are obsolete.
2499 do_add_date = true;
2500 do_zip_file = true;
2501
Nandana Dutt54dbd672019-01-11 12:58:05 +00002502 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2503 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2504 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002505
Paul Changf59c2b72020-03-10 02:08:55 +08002506 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002507}
2508
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002509Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2510 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002511 int c;
mhasankd451a472020-05-26 18:02:39 -07002512 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002513 switch (c) {
2514 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002515 case 'd': do_add_date = true; break;
2516 case 'z': do_zip_file = true; break;
mhasank3a4cfb42020-06-15 18:06:43 -07002517 case 'o': out_dir = optarg; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002518 case 's': use_socket = true; break;
2519 case 'S': use_control_socket = true; break;
2520 case 'v': show_header_only = true; break;
2521 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002522 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002523 case 'P': do_progress_updates = true; break;
2524 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002525 case 'L': limited_only = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002526 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002527 case 'w':
2528 // This was already processed
2529 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002530 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002531 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002532 break;
2533 default:
2534 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002535 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002536 break;
2537 // clang-format on
2538 }
2539 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002540
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002541 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002542 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002543 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002544 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002545 }
2546 }
2547
2548 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2549 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002550
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002551 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002552}
2553
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002554bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002555 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002556 return false;
2557 }
2558
Abhijeet Kaure370d682019-10-01 16:49:30 +01002559 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002560 return false;
2561 }
2562
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002563 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002564 return false;
2565 }
2566
Abhijeet Kaure370d682019-10-01 16:49:30 +01002567 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002568 return false;
2569 }
2570 return true;
2571}
2572
Nandana Dutt197661d2018-11-16 16:40:21 +00002573void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2574 options_ = std::move(options);
2575}
2576
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002577void Dumpstate::Initialize() {
2578 /* gets the sequential id */
2579 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2580 id_ = ++last_id;
2581 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2582}
2583
Nandana Duttd2f5f082019-01-18 17:13:52 +00002584Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2585 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002586 if (listener_ != nullptr) {
2587 switch (status) {
2588 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002589 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002590 break;
2591 case Dumpstate::RunStatus::HELP:
2592 break;
2593 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002594 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002595 break;
2596 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002597 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2598 break;
2599 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2600 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2601 break;
2602 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2603 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002604 break;
2605 }
2606 }
2607 return status;
2608}
2609
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002610void Dumpstate::Cancel() {
2611 CleanupTmpFiles();
2612 android::os::UnlinkAndLogOnError(log_path_);
2613 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2614 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2615 kDumpstateBoardFiles[i]);
2616 }
2617 tombstone_data_.clear();
2618 anr_data_.clear();
2619}
2620
Nandana Dutt979388e2018-11-30 16:48:55 +00002621/*
2622 * Dumps relevant information to a bugreport based on the given options.
2623 *
2624 * The bugreport can be dumped to a file or streamed to a socket.
2625 *
2626 * How dumping to file works:
2627 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2628 * stderr is redirected a log file.
2629 *
2630 * The temporary bugreport is then populated via printfs, dumping contents of files and
2631 * output of commands to stdout.
2632 *
2633 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2634 * text file.
2635 *
2636 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2637 * gets added to the archive.
2638 *
mhasank2d75c442020-06-11 15:05:25 -07002639 * Bugreports are first generated in a local directory and later copied to the caller's fd
2640 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002641 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002642Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2643 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002644 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002645 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002646 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002647 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002648 return RunStatus::INVALID_INPUT;
2649 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002650 /* set as high priority, and protect from OOM killer */
2651 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002652
Felipe Lemed071c682016-10-20 16:48:00 -07002653 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002654 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002655 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002656 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002657 } else {
2658 /* fallback to kernels <= 2.6.35 */
2659 oom_adj = fopen("/proc/self/oom_adj", "we");
2660 if (oom_adj) {
2661 fputs("-17", oom_adj);
2662 fclose(oom_adj);
2663 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002664 }
2665
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002666 if (version_ == VERSION_DEFAULT) {
2667 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002668 }
2669
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002670 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002671 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002672 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002673 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002674 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002675 }
2676
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002677 if (options_->show_header_only) {
2678 PrintHeader();
2679 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002680 }
2681
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002682 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2683 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002684
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002685 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002686 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002687
2688 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002689 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002690 is_redirecting
2691 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2692 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002693 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002694
Sahana Raof35ed432019-07-12 10:47:52 +01002695 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2696 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2697 } else {
2698 // Wake lock will be released automatically on process death
2699 MYLOGD("Wake lock acquired.\n");
2700 }
2701
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002702 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002703
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002704 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002705 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002706 MYLOGI("Starting 'dumpstate' service\n");
2707 android::status_t ret;
2708 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2709 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2710 }
2711 }
2712
Felipe Lemef0292972016-11-22 13:57:05 -08002713 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002714 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2715 }
2716
Nandana Dutt235c6672019-11-14 15:22:32 +00002717 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2718 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002719
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002720 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002721
Christopher Ferrised9354f2014-10-01 17:35:01 -07002722 // If we are going to use a socket, do it as early as possible
2723 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002724 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002725 if (!redirect_to_socket(stdout, "dumpstate")) {
2726 return ERROR;
2727 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002728 }
2729
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002730 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002731 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002732 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002733 if (control_socket_fd_ == -1) {
2734 return ERROR;
2735 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002736 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002737 }
2738
Felipe Leme71bbfc52015-11-23 14:14:51 -08002739 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002740 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002741
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002742 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002743 // clang-format off
2744 std::vector<std::string> am_args = {
2745 "--receiver-permission", "android.permission.DUMP",
2746 };
2747 // clang-format on
2748 // Send STARTED broadcast for apps that listen to bugreport generation events
2749 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002750 if (options_->use_control_socket) {
2751 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002752 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002753 }
2754 }
2755
Nick Kralevichf3599b32016-01-25 15:05:16 -08002756 /* read /proc/cmdline before dropping root */
2757 FILE *cmdline = fopen("/proc/cmdline", "re");
2758 if (cmdline) {
2759 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2760 fclose(cmdline);
2761 }
2762
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002763 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002764 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002765 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002766
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002767 if (options_->do_zip_file && zip_file != nullptr) {
2768 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2769 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002770 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002771 }
2772 }
2773
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002774 int dup_stdout_fd;
2775 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002776 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002777 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002778 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002779 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2780 return ERROR;
2781 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002782 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2783 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2784 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002785 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002786
2787 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2788 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002789 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002790 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002791 /* TODO: rather than generating a text file now and zipping it later,
2792 it would be more efficient to redirect stdout to the zip entry
2793 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002794 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2795 return ERROR;
2796 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002797 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002798 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002799 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002800 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002801 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002802
2803 // Don't buffer stdout
2804 setvbuf(stdout, nullptr, _IONBF, 0);
2805
Rhed Jao5377d792020-07-16 17:37:39 +08002806 // Enable the parallel run if the client requests to output to a file.
2807 EnableParallelRunIfNeeded();
2808 // Using scope guard to make sure the dump pool can be shut down correctly.
2809 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2810 ShutdownDumpPool();
2811 });
2812
Felipe Leme608385d2016-02-01 10:35:38 -08002813 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2814 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002815 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002816 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002817
mhasankd451a472020-05-26 18:02:39 -07002818 // TODO(b/158737089) reduce code repetition in if branches
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002819 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002820 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002821 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002822 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002823 DumpstateTelephonyOnly(calling_package);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002824 // TODO(b/136262402) Using thread pool for DumpstateBoard
2825 RUN_SLOW_FUNCTION_AND_LOG(DUMP_BOARD_TASK, DumpstateBoard);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002826 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002827 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002828 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002829 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002830 DumpstateWifiOnly();
mhasankd451a472020-05-26 18:02:39 -07002831 } else if (options_->limited_only) {
2832 MaybeTakeEarlyScreenshot();
2833 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
2834 MaybeCheckUserConsent(calling_uid, calling_package);
2835 DumpstateLimitedOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002836 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002837 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002838 RunDumpsysCritical();
2839
Paul Chang0d2aad72020-02-13 20:04:03 +08002840 // Take screenshot and get consent only after critical dumpsys has finished.
2841 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002842 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002843 MaybeCheckUserConsent(calling_uid, calling_package);
2844
Nandana Dutt4be45d12018-09-26 15:04:23 +01002845 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002846 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002847 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002848 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002849 HandleUserConsentDenied();
2850 }
2851 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002852 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002853 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002854
Felipe Leme55b42a62015-11-10 17:39:08 -08002855 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002856 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002857 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002858 }
2859
Abhijeet Kaure370d682019-10-01 16:49:30 +01002860 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002861 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002862 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002863 }
2864
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002865 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002866 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002867 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002868 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002869 if (status != Dumpstate::RunStatus::OK &&
2870 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2871 // Do an early return if there were errors. We make an exception for consent
2872 // timing out because it's possible the user got distracted. In this case the
2873 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002874 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002875 return status;
2876 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002877 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2878 MYLOGI(
2879 "Did not receive user consent yet."
2880 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002881 const String16 incidentcompanion("incidentcompanion");
2882 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2883 if (ics != nullptr) {
2884 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2885 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2886 consent_callback_.get());
2887 } else {
2888 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2889 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002890 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002891 }
2892
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002893 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002894 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002895 for (int i = 0; i < 3; i++) {
2896 Vibrate(75);
2897 usleep((75 + 50) * 1000);
2898 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002899 }
2900
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002901 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2902 progress_->GetInitialMax());
2903 progress_->Save();
2904 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002905
Felipe Leme107a05f2016-03-08 15:11:15 -08002906 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002907 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002908 }
2909
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002910 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002911 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002912 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002913 }
2914
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002915 tombstone_data_.clear();
2916 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002917
Nandana Duttd2f5f082019-01-18 17:13:52 +00002918 return (consent_callback_ != nullptr &&
2919 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2920 ? USER_CONSENT_TIMED_OUT
2921 : RunStatus::OK;
2922}
2923
Paul Chang0d2aad72020-02-13 20:04:03 +08002924void Dumpstate::MaybeTakeEarlyScreenshot() {
2925 if (!options_->do_screenshot || !do_early_screenshot_) {
2926 return;
2927 }
2928
2929 TakeScreenshot();
2930}
2931
Paul Changc490e662020-04-11 18:14:09 +08002932void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
2933 const std::string& calling_package) {
2934 if (calling_uid == AID_SHELL || !CalledByApi()) {
2935 return;
2936 }
2937 if (listener_ != nullptr) {
2938 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2939 // handling if required.
2940 android::String16 package(calling_package.c_str());
2941 listener_->onUiIntensiveBugreportDumpsFinished(package);
2942 }
2943}
2944
Jichao Lie89d9c12019-11-21 19:02:51 -08002945void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2946 if (calling_uid == AID_SHELL || !CalledByApi()) {
2947 // No need to get consent for shell triggered dumpstates, or not through
2948 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002949 return;
2950 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002951 consent_callback_ = new ConsentCallback();
2952 const String16 incidentcompanion("incidentcompanion");
2953 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002954 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002955 if (ics != nullptr) {
2956 MYLOGD("Checking user consent via incidentcompanion service\n");
2957 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002958 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002959 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002960 } else {
2961 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2962 }
2963}
2964
Nandana Dutt5c390032019-03-12 10:52:56 +00002965bool Dumpstate::IsUserConsentDenied() const {
2966 return ds.consent_callback_ != nullptr &&
2967 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2968}
2969
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002970bool Dumpstate::CalledByApi() const {
2971 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2972}
2973
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002974void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002975 android::os::UnlinkAndLogOnError(tmp_path_);
2976 android::os::UnlinkAndLogOnError(screenshot_path_);
2977 android::os::UnlinkAndLogOnError(path_);
2978}
2979
Rhed Jao5377d792020-07-16 17:37:39 +08002980void Dumpstate::EnableParallelRunIfNeeded() {
2981 // The thread pool needs to create temporary files to receive dump results.
2982 // That's why we only enable it when the bugreport client chooses to output
2983 // to a file.
2984 if (!PropertiesHelper::IsParallelRun() || !options_->OutputToFile()) {
2985 return;
2986 }
2987 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002988 zip_entry_tasks_ = std::make_unique<TaskQueue>();
Rhed Jao5377d792020-07-16 17:37:39 +08002989}
2990
2991void Dumpstate::ShutdownDumpPool() {
2992 if (dump_pool_) {
2993 dump_pool_->shutdown();
2994 dump_pool_ = nullptr;
2995 }
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08002996 if (zip_entry_tasks_) {
2997 zip_entry_tasks_->run(/* do_cancel = */true);
2998 zip_entry_tasks_ = nullptr;
2999 }
3000}
3001
3002void Dumpstate::EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name,
3003 const std::string& entry_path) {
3004 auto func_add_zip_entry_and_cleanup = [=](bool task_cancelled) {
3005 if (!task_cancelled) {
3006 AddZipEntry(entry_name, entry_path);
3007 }
3008 android::os::UnlinkAndLogOnError(entry_path);
3009 };
3010 if (zip_entry_tasks_) {
3011 // Enqueues AddZipEntryAndCleanup function if the parallel run is enabled.
3012 zip_entry_tasks_->add(func_add_zip_entry_and_cleanup, _1);
3013 } else {
3014 // Invokes AddZipEntryAndCleanup immediately
3015 std::invoke(func_add_zip_entry_and_cleanup, /* task_cancelled = */false);
3016 }
Rhed Jao5377d792020-07-16 17:37:39 +08003017}
3018
Nandana Duttd2f5f082019-01-18 17:13:52 +00003019Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
3020 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00003021 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00003022 return USER_CONSENT_DENIED;
3023}
3024
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003025Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00003026 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01003027 // user consent (unless the caller is Shell).
3028 UserConsentResult consent_result;
3029 if (calling_uid == AID_SHELL) {
3030 consent_result = UserConsentResult::APPROVED;
3031 } else {
3032 consent_result = consent_callback_->getResult();
3033 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003034 if (consent_result == UserConsentResult::UNAVAILABLE) {
3035 // User has not responded yet.
3036 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08003037 // Telephony is a fast report type, particularly on user builds where information may be
3038 // more aggressively limited. To give the user time to read the consent dialog, increase the
3039 // timeout.
3040 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
3041 : USER_CONSENT_TIMEOUT_MS;
3042 if (elapsed_ms < timeout_ms) {
3043 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00003044 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
3045 sleep(delay_seconds);
3046 }
3047 consent_result = consent_callback_->getResult();
3048 }
3049 if (consent_result == UserConsentResult::DENIED) {
3050 // User has explicitly denied sharing with the app. To be safe delete the
3051 // internal bugreport & tmp files.
3052 return HandleUserConsentDenied();
3053 }
3054 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00003055 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
3056 if (copy_succeeded) {
3057 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01003058 if (options_->do_screenshot &&
3059 options_->screenshot_fd.get() != -1 &&
3060 !options_->is_screenshot_copied) {
3061 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
3062 options_->screenshot_fd.get());
3063 options_->is_screenshot_copied = copy_succeeded;
3064 if (copy_succeeded) {
3065 android::os::UnlinkAndLogOnError(screenshot_path_);
3066 }
3067 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00003068 }
3069 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3070 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3071 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3072 // Since we do not have user consent to share the bugreport it does not get
3073 // copied over to the calling app but remains in the internal directory from
3074 // where the user can manually pull it.
3075 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3076 }
3077 // Unknown result; must be a programming error.
3078 MYLOGE("Unknown user consent result:%d\n", consent_result);
3079 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003080}
3081
Nandana Duttf02564e2019-02-15 15:24:24 +00003082Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003083 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3084 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3085 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003086 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003087 // When directly running dumpstate binary, the output is not expected to be written
3088 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003089 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003090
3091 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003092 // an app; they are irrelevant here because bugreport is triggered via command line.
3093 // Update Last ID before calling Run().
3094 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003095 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003096 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003097 return status;
3098}
3099
3100/* Main entry point for dumpstate binary. */
3101int run_main(int argc, char* argv[]) {
3102 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003103
3104 switch (status) {
3105 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003106 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003107 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003108 ShowUsage();
3109 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003110 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003111 fprintf(stderr, "Invalid combination of args\n");
3112 ShowUsage();
3113 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003114 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003115 FALLTHROUGH_INTENDED;
3116 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3117 FALLTHROUGH_INTENDED;
3118 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003119 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003120 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003121}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003122
3123// TODO(111441001): Default DumpOptions to sensible values.
3124Dumpstate::Dumpstate(const std::string& version)
3125 : pid_(getpid()),
3126 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003127 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003128 version_(version),
3129 now_(time(nullptr)) {
3130}
3131
3132Dumpstate& Dumpstate::GetInstance() {
3133 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3134 return singleton_;
3135}
3136
Rhed Jao5377d792020-07-16 17:37:39 +08003137DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3138 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3139 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003140 if (!title_.empty()) {
3141 started_ = Nanotime();
3142 }
3143}
3144
3145DurationReporter::~DurationReporter() {
3146 if (!title_.empty()) {
3147 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003148 if (elapsed >= .5f || verbose_) {
3149 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003150 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003151 if (!logcat_only_) {
3152 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003153 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3154 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003155 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003156 }
3157}
3158
3159const int32_t Progress::kDefaultMax = 5000;
3160
3161Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3162}
3163
3164Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3165 : Progress(initial_max, growth_factor, "") {
3166 progress_ = progress;
3167}
3168
3169Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3170 : initial_max_(initial_max),
3171 progress_(0),
3172 max_(initial_max),
3173 growth_factor_(growth_factor),
3174 n_runs_(0),
3175 average_max_(0),
3176 path_(path) {
3177 if (!path_.empty()) {
3178 Load();
3179 }
3180}
3181
3182void Progress::Load() {
3183 MYLOGD("Loading stats from %s\n", path_.c_str());
3184 std::string content;
3185 if (!android::base::ReadFileToString(path_, &content)) {
3186 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3187 return;
3188 }
3189 if (content.empty()) {
3190 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3191 return;
3192 }
3193 std::vector<std::string> lines = android::base::Split(content, "\n");
3194
3195 if (lines.size() < 1) {
3196 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3197 (int)lines.size(), max_);
3198 return;
3199 }
3200 char* ptr;
3201 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3202 average_max_ = strtol(ptr, nullptr, 10);
3203 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3204 average_max_ > STATS_MAX_AVERAGE) {
3205 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3206 initial_max_ = Progress::kDefaultMax;
3207 } else {
3208 initial_max_ = average_max_;
3209 }
3210 max_ = initial_max_;
3211
3212 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3213}
3214
3215void Progress::Save() {
3216 int32_t total = n_runs_ * average_max_ + progress_;
3217 int32_t runs = n_runs_ + 1;
3218 int32_t average = floor(((float)total) / runs);
3219 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3220 path_.c_str());
3221 if (path_.empty()) {
3222 return;
3223 }
3224
3225 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3226 if (!android::base::WriteStringToFile(content, path_)) {
3227 MYLOGE("Could not save stats on %s\n", path_.c_str());
3228 }
3229}
3230
3231int32_t Progress::Get() const {
3232 return progress_;
3233}
3234
3235bool Progress::Inc(int32_t delta_sec) {
3236 bool changed = false;
3237 if (delta_sec >= 0) {
3238 progress_ += delta_sec;
3239 if (progress_ > max_) {
3240 int32_t old_max = max_;
3241 max_ = floor((float)progress_ * growth_factor_);
3242 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3243 changed = true;
3244 }
3245 }
3246 return changed;
3247}
3248
3249int32_t Progress::GetMax() const {
3250 return max_;
3251}
3252
3253int32_t Progress::GetInitialMax() const {
3254 return initial_max_;
3255}
3256
3257void Progress::Dump(int fd, const std::string& prefix) const {
3258 const char* pr = prefix.c_str();
3259 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3260 dprintf(fd, "%smax: %d\n", pr, max_);
3261 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3262 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3263 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3264 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3265 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3266}
3267
3268bool Dumpstate::IsZipping() const {
3269 return zip_writer_ != nullptr;
3270}
3271
3272std::string Dumpstate::GetPath(const std::string& suffix) const {
3273 return GetPath(bugreport_internal_dir_, suffix);
3274}
3275
3276std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3277 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3278 name_.c_str(), suffix.c_str());
3279}
3280
3281void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3282 progress_ = std::move(progress);
3283}
3284
3285void for_each_userid(void (*func)(int), const char *header) {
3286 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3287 "for_each_userid(%s)", header);
3288 DurationReporter duration_reporter(title);
3289 if (PropertiesHelper::IsDryRun()) return;
3290
3291 DIR *d;
3292 struct dirent *de;
3293
3294 if (header) printf("\n------ %s ------\n", header);
3295 func(0);
3296
3297 if (!(d = opendir("/data/system/users"))) {
3298 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3299 return;
3300 }
3301
3302 while ((de = readdir(d))) {
3303 int userid;
3304 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3305 continue;
3306 }
3307 func(userid);
3308 }
3309
3310 closedir(d);
3311}
3312
3313static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3314 DIR *d;
3315 struct dirent *de;
3316
3317 if (!(d = opendir("/proc"))) {
3318 printf("Failed to open /proc (%s)\n", strerror(errno));
3319 return;
3320 }
3321
3322 if (header) printf("\n------ %s ------\n", header);
3323 while ((de = readdir(d))) {
3324 if (ds.IsUserConsentDenied()) {
3325 MYLOGE(
3326 "Returning early because user denied consent to share bugreport with calling app.");
3327 closedir(d);
3328 return;
3329 }
3330 int pid;
3331 int fd;
3332 char cmdpath[255];
3333 char cmdline[255];
3334
3335 if (!(pid = atoi(de->d_name))) {
3336 continue;
3337 }
3338
3339 memset(cmdline, 0, sizeof(cmdline));
3340
3341 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3342 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3343 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3344 close(fd);
3345 if (cmdline[0]) {
3346 helper(pid, cmdline, arg);
3347 continue;
3348 }
3349 }
3350
3351 // if no cmdline, a kernel thread has comm
3352 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3353 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3354 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3355 close(fd);
3356 if (cmdline[1]) {
3357 cmdline[0] = '[';
3358 size_t len = strcspn(cmdline, "\f\b\r\n");
3359 cmdline[len] = ']';
3360 cmdline[len+1] = '\0';
3361 }
3362 }
3363 if (!cmdline[0]) {
3364 strcpy(cmdline, "N/A");
3365 }
3366 helper(pid, cmdline, arg);
3367 }
3368
3369 closedir(d);
3370}
3371
3372static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3373 for_each_pid_func *func = (for_each_pid_func*) arg;
3374 func(pid, cmdline);
3375}
3376
3377void for_each_pid(for_each_pid_func func, const char *header) {
3378 std::string title = header == nullptr ? "for_each_pid"
3379 : android::base::StringPrintf("for_each_pid(%s)", header);
3380 DurationReporter duration_reporter(title);
3381 if (PropertiesHelper::IsDryRun()) return;
3382
3383 __for_each_pid(for_each_pid_helper, header, (void *) func);
3384}
3385
3386static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3387 DIR *d;
3388 struct dirent *de;
3389 char taskpath[255];
3390 for_each_tid_func *func = (for_each_tid_func *) arg;
3391
3392 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3393
3394 if (!(d = opendir(taskpath))) {
3395 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3396 return;
3397 }
3398
3399 func(pid, pid, cmdline);
3400
3401 while ((de = readdir(d))) {
3402 if (ds.IsUserConsentDenied()) {
3403 MYLOGE(
3404 "Returning early because user denied consent to share bugreport with calling app.");
3405 closedir(d);
3406 return;
3407 }
3408 int tid;
3409 int fd;
3410 char commpath[255];
3411 char comm[255];
3412
3413 if (!(tid = atoi(de->d_name))) {
3414 continue;
3415 }
3416
3417 if (tid == pid)
3418 continue;
3419
3420 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3421 memset(comm, 0, sizeof(comm));
3422 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3423 strcpy(comm, "N/A");
3424 } else {
3425 char *c;
3426 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3427 close(fd);
3428
3429 c = strrchr(comm, '\n');
3430 if (c) {
3431 *c = '\0';
3432 }
3433 }
3434 func(pid, tid, comm);
3435 }
3436
3437 closedir(d);
3438}
3439
3440void for_each_tid(for_each_tid_func func, const char *header) {
3441 std::string title = header == nullptr ? "for_each_tid"
3442 : android::base::StringPrintf("for_each_tid(%s)", header);
3443 DurationReporter duration_reporter(title);
3444
3445 if (PropertiesHelper::IsDryRun()) return;
3446
3447 __for_each_pid(for_each_tid_helper, header, (void *) func);
3448}
3449
3450void show_wchan(int pid, int tid, const char *name) {
3451 if (PropertiesHelper::IsDryRun()) return;
3452
3453 char path[255];
3454 char buffer[255];
3455 int fd, ret, save_errno;
3456 char name_buffer[255];
3457
3458 memset(buffer, 0, sizeof(buffer));
3459
3460 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3461 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3462 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3463 return;
3464 }
3465
3466 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3467 save_errno = errno;
3468 close(fd);
3469
3470 if (ret < 0) {
3471 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3472 return;
3473 }
3474
3475 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3476 pid == tid ? 0 : 3, "", name);
3477
3478 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3479
3480 return;
3481}
3482
3483// print time in centiseconds
3484static void snprcent(char *buffer, size_t len, size_t spc,
3485 unsigned long long time) {
3486 static long hz; // cache discovered hz
3487
3488 if (hz <= 0) {
3489 hz = sysconf(_SC_CLK_TCK);
3490 if (hz <= 0) {
3491 hz = 1000;
3492 }
3493 }
3494
3495 // convert to centiseconds
3496 time = (time * 100 + (hz / 2)) / hz;
3497
3498 char str[16];
3499
3500 snprintf(str, sizeof(str), " %llu.%02u",
3501 time / 100, (unsigned)(time % 100));
3502 size_t offset = strlen(buffer);
3503 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3504 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3505}
3506
3507// print permille as a percent
3508static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3509 char str[16];
3510
3511 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3512 size_t offset = strlen(buffer);
3513 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3514 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3515}
3516
3517void show_showtime(int pid, const char *name) {
3518 if (PropertiesHelper::IsDryRun()) return;
3519
3520 char path[255];
3521 char buffer[1023];
3522 int fd, ret, save_errno;
3523
3524 memset(buffer, 0, sizeof(buffer));
3525
3526 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3527 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3528 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3529 return;
3530 }
3531
3532 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3533 save_errno = errno;
3534 close(fd);
3535
3536 if (ret < 0) {
3537 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3538 return;
3539 }
3540
3541 // field 14 is utime
3542 // field 15 is stime
3543 // field 42 is iotime
3544 unsigned long long utime = 0, stime = 0, iotime = 0;
3545 if (sscanf(buffer,
3546 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3547 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3548 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3549 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3550 &utime, &stime, &iotime) != 3) {
3551 return;
3552 }
3553
3554 unsigned long long total = utime + stime;
3555 if (!total) {
3556 return;
3557 }
3558
3559 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3560 if (permille > 1000) {
3561 permille = 1000;
3562 }
3563
3564 // try to beautify and stabilize columns at <80 characters
3565 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3566 if ((name[0] != '[') || utime) {
3567 snprcent(buffer, sizeof(buffer), 57, utime);
3568 }
3569 snprcent(buffer, sizeof(buffer), 65, stime);
3570 if ((name[0] != '[') || iotime) {
3571 snprcent(buffer, sizeof(buffer), 73, iotime);
3572 }
3573 if (iotime) {
3574 snprdec(buffer, sizeof(buffer), 79, permille);
3575 }
3576 puts(buffer); // adds a trailing newline
3577
3578 return;
3579}
3580
3581void do_dmesg() {
3582 const char *title = "KERNEL LOG (dmesg)";
3583 DurationReporter duration_reporter(title);
3584 printf("------ %s ------\n", title);
3585
3586 if (PropertiesHelper::IsDryRun()) return;
3587
3588 /* Get size of kernel buffer */
3589 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3590 if (size <= 0) {
3591 printf("Unexpected klogctl return value: %d\n\n", size);
3592 return;
3593 }
3594 char *buf = (char *) malloc(size + 1);
3595 if (buf == nullptr) {
3596 printf("memory allocation failed\n\n");
3597 return;
3598 }
3599 int retval = klogctl(KLOG_READ_ALL, buf, size);
3600 if (retval < 0) {
3601 printf("klogctl failure\n\n");
3602 free(buf);
3603 return;
3604 }
3605 buf[retval] = '\0';
3606 printf("%s\n\n", buf);
3607 free(buf);
3608 return;
3609}
3610
3611void do_showmap(int pid, const char *name) {
3612 char title[255];
3613 char arg[255];
3614
3615 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3616 snprintf(arg, sizeof(arg), "%d", pid);
3617 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3618}
3619
3620int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3621 DurationReporter duration_reporter(title);
3622
3623 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3624
3625 UpdateProgress(WEIGHT_FILE);
3626
3627 return status;
3628}
3629
3630int read_file_as_long(const char *path, long int *output) {
3631 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3632 if (fd < 0) {
3633 int err = errno;
3634 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3635 return -1;
3636 }
3637 char buffer[50];
3638 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3639 if (bytes_read == -1) {
3640 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3641 return -2;
3642 }
3643 if (bytes_read == 0) {
3644 MYLOGE("File %s is empty\n", path);
3645 return -3;
3646 }
3647 *output = atoi(buffer);
3648 return 0;
3649}
3650
3651/* calls skip to gate calling dump_from_fd recursively
3652 * in the specified directory. dump_from_fd defaults to
3653 * dump_file_from_fd above when set to NULL. skip defaults
3654 * to false when set to NULL. dump_from_fd will always be
3655 * called with title NULL.
3656 */
3657int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3658 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3659 DurationReporter duration_reporter(title);
3660 DIR *dirp;
3661 struct dirent *d;
3662 char *newpath = nullptr;
3663 const char *slash = "/";
3664 int retval = 0;
3665
3666 if (!title.empty()) {
3667 printf("------ %s (%s) ------\n", title.c_str(), dir);
3668 }
3669 if (PropertiesHelper::IsDryRun()) return 0;
3670
3671 if (dir[strlen(dir) - 1] == '/') {
3672 ++slash;
3673 }
3674 dirp = opendir(dir);
3675 if (dirp == nullptr) {
3676 retval = -errno;
3677 MYLOGE("%s: %s\n", dir, strerror(errno));
3678 return retval;
3679 }
3680
3681 if (!dump_from_fd) {
3682 dump_from_fd = dump_file_from_fd;
3683 }
3684 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3685 if ((d->d_name[0] == '.')
3686 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3687 || (d->d_name[1] == '\0'))) {
3688 continue;
3689 }
3690 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3691 (d->d_type == DT_DIR) ? "/" : "");
3692 if (!newpath) {
3693 retval = -errno;
3694 continue;
3695 }
3696 if (skip && (*skip)(newpath)) {
3697 continue;
3698 }
3699 if (d->d_type == DT_DIR) {
3700 int ret = dump_files("", newpath, skip, dump_from_fd);
3701 if (ret < 0) {
3702 retval = ret;
3703 }
3704 continue;
3705 }
3706 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3707 if (fd.get() < 0) {
3708 retval = -1;
3709 printf("*** %s: %s\n", newpath, strerror(errno));
3710 continue;
3711 }
3712 (*dump_from_fd)(nullptr, newpath, fd.get());
3713 }
3714 closedir(dirp);
3715 if (!title.empty()) {
3716 printf("\n");
3717 }
3718 return retval;
3719}
3720
3721/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3722 * it's possible to avoid issues where opening the file itself can get
3723 * stuck.
3724 */
3725int dump_file_from_fd(const char *title, const char *path, int fd) {
3726 if (PropertiesHelper::IsDryRun()) return 0;
3727
3728 int flags = fcntl(fd, F_GETFL);
3729 if (flags == -1) {
3730 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3731 return -1;
3732 } else if (!(flags & O_NONBLOCK)) {
3733 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3734 return -1;
3735 }
3736 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3737}
3738
3739int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003740 const CommandOptions& options, bool verbose_duration, int out_fd) {
3741 DurationReporter duration_reporter(title, false /* logcat_only */,
3742 verbose_duration, out_fd);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003743
Rhed Jao3c2fdbd2020-07-20 17:46:29 +08003744 int status = RunCommandToFd(out_fd, title, full_command, options);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003745
3746 /* TODO: for now we're simplifying the progress calculation by using the
3747 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3748 * where its weight should be much higher proportionally to its timeout.
3749 * Ideally, it should use a options.EstimatedDuration() instead...*/
3750 UpdateProgress(options.Timeout());
3751
3752 return status;
3753}
3754
3755void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3756 const CommandOptions& options, long dumpsysTimeoutMs) {
3757 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3758 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3759 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3760 RunCommand(title, dumpsys, options);
3761}
3762
3763int open_socket(const char *service) {
3764 int s = android_get_control_socket(service);
3765 if (s < 0) {
3766 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3767 return -1;
3768 }
3769 fcntl(s, F_SETFD, FD_CLOEXEC);
3770
3771 // Set backlog to 0 to make sure that queue size will be minimum.
3772 // In Linux, because the minimum queue will be 1, connect() will be blocked
3773 // if the other clients already called connect() and the connection request was not accepted.
3774 if (listen(s, 0) < 0) {
3775 MYLOGE("listen(control socket): %s\n", strerror(errno));
3776 return -1;
3777 }
3778
3779 struct sockaddr addr;
3780 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003781 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003782
3783 // Close socket just after accept(), to make sure that connect() by client will get error
3784 // when the socket is used by the other services.
3785 // There is still a race condition possibility between accept and close, but there is no way
3786 // to close-on-accept atomically.
3787 // See detail; b/123306389#comment25
3788 close(s);
3789
3790 if (fd < 0) {
3791 MYLOGE("accept(control socket): %s\n", strerror(errno));
3792 return -1;
3793 }
3794
3795 return fd;
3796}
3797
3798/* redirect output to a service control socket */
3799bool redirect_to_socket(FILE* redirect, const char* service) {
3800 int fd = open_socket(service);
3801 if (fd == -1) {
3802 return false;
3803 }
3804 fflush(redirect);
3805 // TODO: handle dup2 failure
3806 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3807 close(fd);
3808 return true;
3809}
3810
3811// TODO: should call is_valid_output_file and/or be merged into it.
3812void create_parent_dirs(const char *path) {
3813 char *chp = const_cast<char *> (path);
3814
3815 /* skip initial slash */
3816 if (chp[0] == '/')
3817 chp++;
3818
3819 /* create leading directories, if necessary */
3820 struct stat dir_stat;
3821 while (chp && chp[0]) {
3822 chp = strchr(chp, '/');
3823 if (chp) {
3824 *chp = 0;
3825 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3826 MYLOGI("Creating directory %s\n", path);
3827 if (mkdir(path, 0770)) { /* drwxrwx--- */
3828 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3829 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3830 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3831 }
3832 }
3833 *chp++ = '/';
3834 }
3835 }
3836}
3837
3838bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3839 create_parent_dirs(path);
3840
3841 int fd = TEMP_FAILURE_RETRY(open(path,
3842 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3843 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3844 if (fd < 0) {
3845 MYLOGE("%s: %s\n", path, strerror(errno));
3846 return false;
3847 }
3848
3849 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3850 close(fd);
3851 return true;
3852}
3853
3854bool redirect_to_file(FILE* redirect, char* path) {
3855 return _redirect_to_file(redirect, path, O_TRUNC);
3856}
3857
3858bool redirect_to_existing_file(FILE* redirect, char* path) {
3859 return _redirect_to_file(redirect, path, O_APPEND);
3860}
3861
3862void dump_route_tables() {
3863 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3864 if (PropertiesHelper::IsDryRun()) return;
3865 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3866 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3867 FILE* fp = fopen(RT_TABLES_PATH, "re");
3868 if (!fp) {
3869 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3870 return;
3871 }
3872 char table[16];
3873 // Each line has an integer (the table number), a space, and a string (the table name). We only
3874 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3875 // Add a fixed max limit so this doesn't go awry.
3876 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3877 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3878 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3879 }
3880 fclose(fp);
3881}
3882
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003883void Dumpstate::UpdateProgress(int32_t delta_sec) {
3884 if (progress_ == nullptr) {
3885 MYLOGE("UpdateProgress: progress_ not set\n");
3886 return;
3887 }
Rhed Jaobf63d8a2020-07-21 15:42:55 +08003888 // This function updates progress related members of the dumpstate and reports
3889 // progress percentage to the bugreport client. Since it could be called by
3890 // different dump tasks at the same time if the parallel run is enabled, a
3891 // mutex lock is necessary here to synchronize the call.
3892 std::lock_guard<std::recursive_mutex> lock(mutex_);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003893
3894 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01003895 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003896
3897 // ...but only notifiy listeners when necessary.
3898 if (!options_->do_progress_updates) return;
3899
3900 int progress = progress_->Get();
3901 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01003902 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003903
Nandana Dutt402a8392019-06-14 14:25:13 +01003904 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003905 return;
3906 }
Nandana Dutt402a8392019-06-14 14:25:13 +01003907 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003908
3909 if (control_socket_fd_ >= 0) {
3910 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3911 fsync(control_socket_fd_);
3912 }
3913
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003914 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003915 if (percent % 10 == 0) {
3916 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003917 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003918 } else {
3919 // stderr is ignored on normal invocations, but useful when calling
3920 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003921 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003922 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003923
3924 listener_->onProgress(percent);
3925 }
3926}
3927
3928void Dumpstate::TakeScreenshot(const std::string& path) {
3929 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3930 int status =
3931 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3932 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3933 if (status == 0) {
3934 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3935 } else {
3936 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3937 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003938 if (listener_ != nullptr) {
3939 // Show a visual indication to indicate screenshot is taken via
3940 // IDumpstateListener.onScreenshotTaken()
3941 listener_->onScreenshotTaken(status == 0);
3942 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003943}
3944
3945bool is_dir(const char* pathname) {
3946 struct stat info;
3947 if (stat(pathname, &info) == -1) {
3948 return false;
3949 }
3950 return S_ISDIR(info.st_mode);
3951}
3952
3953time_t get_mtime(int fd, time_t default_mtime) {
3954 struct stat info;
3955 if (fstat(fd, &info) == -1) {
3956 return default_mtime;
3957 }
3958 return info.st_mtime;
3959}