blob: 472a0f1b2e3c1c38d985e1d04cc83ea48a406e57 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010022#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070024#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010025#include <math.h>
26#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070027#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080031#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070032#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070033#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/time.h>
36#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010037#include <signal.h>
38#include <stdarg.h>
39#include <string.h>
40#include <sys/capability.h>
41#include <sys/inotify.h>
42#include <sys/klog.h>
43#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070045
46#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070047#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000048#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070049#include <functional>
50#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010051#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070052#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <regex>
54#include <set>
55#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070056#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010057#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070058
Felipe Leme96c2bbb2016-09-26 09:21:21 -070059#include <android-base/file.h>
60#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070061#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080062#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070063#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070064#include <android-base/unique_fd.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010065#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080066#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080067#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
68#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080069#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000070#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070073#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010074#include <cutils/sockets.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000075#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080076#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000077#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010078#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080079#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070081#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070082#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070083#include <private/android_filesystem_config.h>
84#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080085#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070086#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080087#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070088#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070089#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080090
Hunter Knepshield8540faf2020-02-04 19:47:20 -080091using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
92using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
93using ::android::hardware::dumpstate::V1_1::DumpstateMode;
94using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
95using ::android::hardware::dumpstate::V1_1::toString;
Vishnu Naire97d6122018-01-18 13:58:56 -080096using ::std::literals::chrono_literals::operator""ms;
97using ::std::literals::chrono_literals::operator""s;
Rhed Jao1c855122020-07-16 17:37:39 +080098using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -080099
Felipe Leme47e9be22016-12-21 15:37:07 -0800100// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800101using android::defaultServiceManager;
102using android::Dumpsys;
103using android::INVALID_OPERATION;
104using android::IServiceManager;
105using android::OK;
106using android::sp;
107using android::status_t;
108using android::String16;
109using android::String8;
110using android::TIMED_OUT;
111using android::UNKNOWN_ERROR;
112using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000113using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000114using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800115using android::os::dumpstate::CommandOptions;
116using android::os::dumpstate::DumpFileToFd;
Rhed Jao1c855122020-07-16 17:37:39 +0800117using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800118using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -0800119
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100120// Keep in sync with
121// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
122static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
123
124/* Most simple commands have 10 as timeout, so 5 is a good estimate */
125static const int32_t WEIGHT_FILE = 5;
126
127// TODO: temporary variables and functions used during C++ refactoring
128static Dumpstate& ds = Dumpstate::GetInstance();
129static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100130 const CommandOptions& options = CommandOptions::DEFAULT,
131 bool verbose_duration = false) {
132 return ds.RunCommand(title, full_command, options, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100133}
134
135// Reasonable value for max stats.
136static const int STATS_MAX_N_RUNS = 1000;
137static const long STATS_MAX_AVERAGE = 100000;
138
139CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
140
Nandana Duttd2f5f082019-01-18 17:13:52 +0000141typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
142
Colin Crossf45fa6b2012-03-26 12:38:26 -0700143/* read before root is shed */
144static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700145static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000146static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800147// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
148// it's often the case that they time out far too quickly for consent with such a hefty dialog for
149// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
150// roughly match full reports' durations.
151static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700152
Felipe Leme1d486fe2016-10-14 18:06:47 -0700153// TODO: variables and functions below should be part of dumpstate object
154
Felipe Leme635ca312016-01-05 14:23:02 -0800155static std::set<std::string> mount_points;
156void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800157
Todd Poynor2a83daa2013-11-22 15:44:22 -0800158#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700159#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700160#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800161
Felipe Lemee82a27d2016-01-05 13:35:44 -0800162#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700163#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700164#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700165#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800166#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100167#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
168#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800169#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900170#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800171#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700172#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800173#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900174#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravle78a0d842020-04-28 15:31:12 -0700175#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700176
Narayan Kamath8f788292017-05-25 13:20:39 +0100177// TODO(narayan): Since this information has to be kept in sync
178// with tombstoned, we should just put it in a common header.
179//
180// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100181static const std::string TOMBSTONE_DIR = "/data/tombstones/";
182static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
183static const std::string ANR_DIR = "/data/anr/";
184static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700185
Felipe Lemee844a9d2016-09-21 15:01:39 -0700186// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000187
Nandana Dutt5c390032019-03-12 10:52:56 +0000188#define RETURN_IF_USER_DENIED_CONSENT() \
189 if (ds.IsUserConsentDenied()) { \
190 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
191 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
192 }
193
194// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
195// if consent is found to be denied.
196#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
197 RETURN_IF_USER_DENIED_CONSENT(); \
198 func_ptr(__VA_ARGS__); \
199 RETURN_IF_USER_DENIED_CONSENT();
200
Rhed Jao1c855122020-07-16 17:37:39 +0800201// Runs func_ptr, and logs a duration report after it's finished.
202#define RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, ...) \
203 { \
204 DurationReporter duration_reporter_in_macro(log_title); \
205 func_ptr(__VA_ARGS__); \
206 }
207
208// Similar with RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK, an additional duration report
209// is output after a slow function is finished.
210#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(log_title, func_ptr, ...) \
211 RETURN_IF_USER_DENIED_CONSENT(); \
212 RUN_SLOW_FUNCTION_AND_LOG(log_title, func_ptr, __VA_ARGS__); \
213 RETURN_IF_USER_DENIED_CONSENT();
214
Sahana Raof35ed432019-07-12 10:47:52 +0100215static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
216
Rhed Jao1c855122020-07-16 17:37:39 +0800217// Names of parallel tasks, they are used for the DumpPool to identify the dump
218// task and the log title of the duration report.
219static const std::string DUMP_TRACES_TASK = "DUMP TRACES";
220
Nandana Dutt979388e2018-11-30 16:48:55 +0000221namespace android {
222namespace os {
223namespace {
224
225static int Open(std::string path, int flags, mode_t mode = 0) {
226 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
227 if (fd == -1) {
228 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
229 }
230 return fd;
231}
232
mhasank2d75c442020-06-11 15:05:25 -0700233static int OpenForWrite(std::string path) {
234 return Open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
235 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
236}
Nandana Dutt979388e2018-11-30 16:48:55 +0000237
238static int OpenForRead(std::string path) {
239 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
240}
241
242bool CopyFile(int in_fd, int out_fd) {
243 char buf[4096];
244 ssize_t byte_count;
245 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
246 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
247 return false;
248 }
249 }
250 return (byte_count != -1);
251}
252
253static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000254 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000255
256 // Obtain a handle to the source file.
257 android::base::unique_fd in_fd(OpenForRead(input_file));
258 if (out_fd != -1 && in_fd.get() != -1) {
259 if (CopyFile(in_fd.get(), out_fd)) {
260 return true;
261 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000262 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000263 }
264 return false;
265}
266
Nandana Duttd2f5f082019-01-18 17:13:52 +0000267static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000268 if (file.empty()) {
269 return false;
270 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000271 if (unlink(file.c_str())) {
272 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000273 return false;
274 }
275 return true;
276}
Nandana Dutt979388e2018-11-30 16:48:55 +0000277
Nikita Ioffea325a572019-05-16 19:49:47 +0100278int64_t GetModuleMetadataVersion() {
279 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
280 if (binder == nullptr) {
281 MYLOGE("Failed to retrieve package_native service");
282 return 0L;
283 }
284 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
285 std::string package_name;
286 auto status = package_service->getModuleMetadataPackageName(&package_name);
287 if (!status.isOk()) {
288 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
289 return 0L;
290 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100291 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100292 int64_t version_code;
293 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
294 &version_code);
295 if (!status.isOk()) {
296 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
297 return 0L;
298 }
299 return version_code;
300}
301
mhasank2d75c442020-06-11 15:05:25 -0700302static bool PathExists(const std::string& path) {
303 struct stat sb;
304 return stat(path.c_str(), &sb) == 0;
305}
306
307static bool CopyFileToFile(const std::string& input_file, const std::string& output_file) {
308 if (input_file == output_file) {
309 MYLOGD("Skipping copying bugreport file since the destination is the same (%s)\n",
310 output_file.c_str());
311 return false;
312 }
313 else if (PathExists(output_file)) {
314 MYLOGD("Cannot overwrite an existing file (%s)\n", output_file.c_str());
315 return false;
316 }
317
318 MYLOGD("Going to copy bugreport file (%s) to %s\n", input_file.c_str(), output_file.c_str());
319 android::base::unique_fd out_fd(OpenForWrite(output_file));
320 return CopyFileToFd(input_file, out_fd.get());
321}
322
Nandana Dutt979388e2018-11-30 16:48:55 +0000323} // namespace
324} // namespace os
325} // namespace android
326
Felipe Leme678727a2016-09-21 17:22:11 -0700327static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800328 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800329 long dumpsysTimeoutMs = 0) {
330 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700331}
332static int DumpFile(const std::string& title, const std::string& path) {
333 return ds.DumpFile(title, path);
334}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800335
Felipe Lemee844a9d2016-09-21 15:01:39 -0700336// Relative directory (inside the zip) for all files copied as-is into the bugreport.
337static const std::string ZIP_ROOT_DIR = "FS";
338
Vishnu Naire97d6122018-01-18 13:58:56 -0800339static const std::string kProtoPath = "proto/";
340static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700341static const std::string kDumpstateBoardFiles[] = {
342 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700343 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700344};
345static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
346
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700347static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700348static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700349
Felipe Lemef0292972016-11-22 13:57:05 -0800350static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
351
Narayan Kamath8f788292017-05-25 13:20:39 +0100352/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100353 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800354 * The returned vector is sorted by the mtimes of the dumps with descending
355 * order. If |limit_by_mtime| is set, the vector only contains files that
356 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100357 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700358static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
359 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700360 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100361 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
362
Narayan Kamathbd863722017-06-01 18:50:12 +0100363 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100364
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700365 if (dump_dir == nullptr) {
366 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700367 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700368 }
369
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700370 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100371 struct dirent* entry = nullptr;
372 while ((entry = readdir(dump_dir.get()))) {
373 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100374 continue;
375 }
376
Narayan Kamathbd863722017-06-01 18:50:12 +0100377 const std::string base_name(entry->d_name);
378 if (base_name.find(file_prefix) != 0) {
379 continue;
380 }
381
382 const std::string abs_path = dir_path + base_name;
383 android::base::unique_fd fd(
384 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
385 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700386 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100387 break;
388 }
389
390 struct stat st = {};
391 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700392 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100393 continue;
394 }
395
Narayan Kamath3f31b632018-02-22 19:42:36 +0000396 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100397 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100398 continue;
399 }
400
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700401 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700402 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800403 if (!dump_data.empty()) {
404 std::sort(dump_data.begin(), dump_data.end(),
405 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
406 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100407
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700408 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100409}
410
Narayan Kamathbd863722017-06-01 18:50:12 +0100411static bool AddDumps(const std::vector<DumpData>::const_iterator start,
412 const std::vector<DumpData>::const_iterator end,
413 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100414 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100415 for (auto it = start; it != end; ++it) {
416 const std::string& name = it->name;
417 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100418 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100419
420 // Seek to the beginning of the file before dumping any data. A given
421 // DumpData entry might be dumped multiple times in the report.
422 //
423 // For example, the most recent ANR entry is dumped to the body of the
424 // main entry and it also shows up as a separate entry in the bugreport
425 // ZIP file.
426 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
427 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
428 strerror(errno));
429 }
430
Narayan Kamath8f788292017-05-25 13:20:39 +0100431 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800432 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100433 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100434 }
435 } else {
436 dump_file_from_fd(type_name, name.c_str(), fd);
437 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100438 }
439
440 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700441}
442
Felipe Leme635ca312016-01-05 14:23:02 -0800443// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700444void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800445 char path[PATH_MAX];
446
447 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
448 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700449 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800450 char linkname[PATH_MAX];
451 ssize_t r = readlink(path, linkname, PATH_MAX);
452 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800453 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800454 return;
455 }
456 linkname[r] = '\0';
457
458 if (mount_points.find(linkname) == mount_points.end()) {
459 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700460 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700461 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800462 mount_points.insert(linkname);
463 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800464 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800465 }
466 }
467}
468
469void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700470 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700471 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800472 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800473 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700474 for_each_pid(do_mountinfo, nullptr);
475 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800476}
477
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700478static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
479{
480 DIR *d;
481 struct dirent *de;
482 char path[PATH_MAX];
483
484 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700485 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700486 return;
487 }
488
489 while ((de = readdir(d))) {
490 if (de->d_type != DT_LNK) {
491 continue;
492 }
493 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700494 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700495 }
496
497 closedir(d);
498}
499
Mark Salyzyn326842f2015-04-30 09:49:41 -0700500static bool skip_not_stat(const char *path) {
501 static const char stat[] = "/stat";
502 size_t len = strlen(path);
503 if (path[len - 1] == '/') { /* Directory? */
504 return false;
505 }
506 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
507}
508
Felipe Leme4c2d6632016-09-28 14:32:00 -0700509static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800510 return false;
511}
512
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700513unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700514
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800515//
516// stat offsets
517// Name units description
518// ---- ----- -----------
519// read I/Os requests number of read I/Os processed
520#define __STAT_READ_IOS 0
521// read merges requests number of read I/Os merged with in-queue I/O
522#define __STAT_READ_MERGES 1
523// read sectors sectors number of sectors read
524#define __STAT_READ_SECTORS 2
525// read ticks milliseconds total wait time for read requests
526#define __STAT_READ_TICKS 3
527// write I/Os requests number of write I/Os processed
528#define __STAT_WRITE_IOS 4
529// write merges requests number of write I/Os merged with in-queue I/O
530#define __STAT_WRITE_MERGES 5
531// write sectors sectors number of sectors written
532#define __STAT_WRITE_SECTORS 6
533// write ticks milliseconds total wait time for write requests
534#define __STAT_WRITE_TICKS 7
535// in_flight requests number of I/Os currently in flight
536#define __STAT_IN_FLIGHT 8
537// io_ticks milliseconds total time this block device has been active
538#define __STAT_IO_TICKS 9
539// time_in_queue milliseconds total wait time for all requests
540#define __STAT_IN_QUEUE 10
541#define __STAT_NUMBER_FIELD 11
542//
543// read I/Os, write I/Os
544// =====================
545//
546// These values increment when an I/O request completes.
547//
548// read merges, write merges
549// =========================
550//
551// These values increment when an I/O request is merged with an
552// already-queued I/O request.
553//
554// read sectors, write sectors
555// ===========================
556//
557// These values count the number of sectors read from or written to this
558// block device. The "sectors" in question are the standard UNIX 512-byte
559// sectors, not any device- or filesystem-specific block size. The
560// counters are incremented when the I/O completes.
561#define SECTOR_SIZE 512
562//
563// read ticks, write ticks
564// =======================
565//
566// These values count the number of milliseconds that I/O requests have
567// waited on this block device. If there are multiple I/O requests waiting,
568// these values will increase at a rate greater than 1000/second; for
569// example, if 60 read requests wait for an average of 30 ms, the read_ticks
570// field will increase by 60*30 = 1800.
571//
572// in_flight
573// =========
574//
575// This value counts the number of I/O requests that have been issued to
576// the device driver but have not yet completed. It does not include I/O
577// requests that are in the queue but not yet issued to the device driver.
578//
579// io_ticks
580// ========
581//
582// This value counts the number of milliseconds during which the device has
583// had I/O requests queued.
584//
585// time_in_queue
586// =============
587//
588// This value counts the number of milliseconds that I/O requests have waited
589// on this block device. If there are multiple I/O requests waiting, this
590// value will increase as the product of the number of milliseconds times the
591// number of requests waiting (see "read ticks" above for an example).
592#define S_TO_MS 1000
593//
594
Mark Salyzyn326842f2015-04-30 09:49:41 -0700595static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800596 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700597 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700598 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700599 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700600 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700601 getline(&buffer, &i, fp);
602 fclose(fp);
603 if (!buffer) {
604 return -errno;
605 }
606 i = strlen(buffer);
607 while ((i > 0) && (buffer[i - 1] == '\n')) {
608 buffer[--i] = '\0';
609 }
610 if (!*buffer) {
611 free(buffer);
612 return 0;
613 }
614 z = true;
615 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800616 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700617 if (fields[i] != 0) {
618 z = false;
619 }
620 }
621 if (z) { /* never accessed */
622 free(buffer);
623 return 0;
624 }
625
Wei Wang509bb5d2017-06-09 14:42:12 -0700626 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
627 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700628 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700629
630 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
631 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
632 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700633 free(buffer);
634
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800635 if (fields[__STAT_IO_TICKS]) {
636 unsigned long read_perf = 0;
637 unsigned long read_ios = 0;
638 if (fields[__STAT_READ_TICKS]) {
639 unsigned long long divisor = fields[__STAT_READ_TICKS]
640 * fields[__STAT_IO_TICKS];
641 read_perf = ((unsigned long long)SECTOR_SIZE
642 * fields[__STAT_READ_SECTORS]
643 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
644 / divisor;
645 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
646 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
647 / divisor;
648 }
649
650 unsigned long write_perf = 0;
651 unsigned long write_ios = 0;
652 if (fields[__STAT_WRITE_TICKS]) {
653 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
654 * fields[__STAT_IO_TICKS];
655 write_perf = ((unsigned long long)SECTOR_SIZE
656 * fields[__STAT_WRITE_SECTORS]
657 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
658 / divisor;
659 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
660 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
661 / divisor;
662 }
663
664 unsigned queue = (fields[__STAT_IN_QUEUE]
665 + (fields[__STAT_IO_TICKS] >> 1))
666 / fields[__STAT_IO_TICKS];
667
668 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700669 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 -0800670 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700671 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 -0800672 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800673 }
674
675 /* bugreport timeout factor adjustment */
676 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
677 worst_write_perf = write_perf;
678 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700679 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700680 return 0;
681}
682
Yao Chenbe3bbc12018-01-17 16:31:10 -0800683static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
684
Tom Cherryf4472f32020-08-05 09:31:17 -0700685// Returns the actual readable size of the given buffer or -1 on error.
686static long logcat_buffer_readable_size(const std::string& buffer) {
687 std::unique_ptr<logger_list, decltype(&android_logger_list_free)> logger_list{
688 android_logger_list_alloc(0, 0, 0), &android_logger_list_free};
689 auto logger = android_logger_open(logger_list.get(), android_name_to_log_id(buffer.c_str()));
690
691 return android_logger_get_log_readable_size(logger);
692}
693
694// Returns timeout in ms to read a list of buffers.
Yao Chenbe3bbc12018-01-17 16:31:10 -0800695static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
696 unsigned long timeout_ms = 0;
697 for (const auto& buffer : buffers) {
Tom Cherryf4472f32020-08-05 09:31:17 -0700698 long readable_size = logcat_buffer_readable_size(buffer);
699 if (readable_size > 0) {
700 // Engineering margin is ten-fold our guess.
701 timeout_ms += 10 * (readable_size + worst_write_perf) / worst_write_perf;
702 }
Yao Chenbe3bbc12018-01-17 16:31:10 -0800703 }
704 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700705}
706
Nandana Duttd2f5f082019-01-18 17:13:52 +0000707Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
708}
709
710android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
711 std::lock_guard<std::mutex> lock(lock_);
712 result_ = APPROVED;
713 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800714
715 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
716 // consent is granted.
717 if (ds.options_->is_screenshot_copied) {
718 return android::binder::Status::ok();
719 }
720
721 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
722 !ds.do_early_screenshot_) {
723 return android::binder::Status::ok();
724 }
725
726 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
727 ds.options_->screenshot_fd.get());
728 ds.options_->is_screenshot_copied = copy_succeeded;
729 if (copy_succeeded) {
730 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
731 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000732 return android::binder::Status::ok();
733}
734
735android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
736 std::lock_guard<std::mutex> lock(lock_);
737 result_ = DENIED;
738 MYLOGW("User denied consent to share bugreport\n");
739 return android::binder::Status::ok();
740}
741
742UserConsentResult Dumpstate::ConsentCallback::getResult() {
743 std::lock_guard<std::mutex> lock(lock_);
744 return result_;
745}
746
747uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800748 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000749}
750
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700751void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700752 std::string build, fingerprint, radio, bootloader, network;
753 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700754
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700755 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
756 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700757 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
758 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
759 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700760 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700761
Felipe Lemed8b94e52016-12-08 10:21:44 -0800762 printf("========================================================\n");
763 printf("== dumpstate: %s\n", date);
764 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700765
Felipe Lemed8b94e52016-12-08 10:21:44 -0800766 printf("\n");
767 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700768 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800769 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
770 printf("Bootloader: %s\n", bootloader.c_str());
771 printf("Radio: %s\n", radio.c_str());
772 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100773 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
774 if (module_metadata_version != 0) {
775 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
776 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700777
Felipe Lemed8b94e52016-12-08 10:21:44 -0800778 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800779 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800780 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800781 printf("Uptime: ");
782 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
783 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800784 printf("Bugreport format version: %s\n", version_.c_str());
Rhed Jao1c855122020-07-16 17:37:39 +0800785 printf("Dumpstate info: id=%d pid=%d dry_run=%d parallel_run=%d args=%s bugreport_mode=%s\n",
786 id_, pid_, PropertiesHelper::IsDryRun(), PropertiesHelper::IsParallelRun(),
787 options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800788 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800789}
790
Felipe Leme24b66ee2016-06-16 10:55:26 -0700791// List of file extensions that can cause a zip file attachment to be rejected by some email
792// service providers.
793static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
794 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
795 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
796 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
797};
798
Vishnu Naire97d6122018-01-18 13:58:56 -0800799status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
800 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700801 if (!IsZipping()) {
802 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
803 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800804 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800805 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700806 std::string valid_name = entry_name;
807
808 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700809 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700810 if (idx != std::string::npos) {
811 std::string extension = entry_name.substr(idx);
812 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
813 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
814 valid_name = entry_name + ".renamed";
815 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
816 }
817 }
818
Felipe Leme6fe9db62016-02-12 09:04:16 -0800819 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
820 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700821 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
822 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700823 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700824 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700825 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800826 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800827 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000828 bool finished_entry = false;
829 auto finish_entry = [this, &finished_entry] {
830 if (!finished_entry) {
831 // This should only be called when we're going to return an earlier error,
832 // which would've been logged. This may imply the file is already corrupt
833 // and any further logging from FinishEntry is more likely to mislead than
834 // not.
835 this->zip_writer_->FinishEntry();
836 }
837 };
838 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800839 auto start = std::chrono::steady_clock::now();
840 auto end = start + timeout;
841 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800842
Felipe Leme770410d2016-01-26 17:07:14 -0800843 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800844 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800845 if (timeout.count() > 0) {
846 // lambda to recalculate the timeout.
847 auto time_left_ms = [end]() {
848 auto now = std::chrono::steady_clock::now();
849 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
850 return std::max(diff.count(), 0LL);
851 };
852
853 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
854 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000855 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
856 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800857 return -errno;
858 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000859 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800860 entry_name.c_str(), strerror(errno), timeout.count());
861 return TIMED_OUT;
862 }
863 }
864
Zach Riggle22200402016-08-18 01:01:24 -0400865 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800866 if (bytes_read == 0) {
867 break;
868 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800869 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800871 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700872 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800873 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700874 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800875 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800876 }
877 }
878
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700879 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000880 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700881 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700882 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800883 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884 }
885
Vishnu Naire97d6122018-01-18 13:58:56 -0800886 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800887}
888
Felipe Leme1d486fe2016-10-14 18:06:47 -0700889bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
890 android::base::unique_fd fd(
891 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700892 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800893 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800894 return false;
895 }
896
Vishnu Naire97d6122018-01-18 13:58:56 -0800897 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800898}
899
900/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700901static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800902 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800903}
904
Felipe Leme1d486fe2016-10-14 18:06:47 -0700905void Dumpstate::AddDir(const std::string& dir, bool recursive) {
906 if (!IsZipping()) {
907 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800908 return;
909 }
Felipe Leme678727a2016-09-21 17:22:11 -0700910 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800911 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700912 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800913}
914
Felipe Leme1d486fe2016-10-14 18:06:47 -0700915bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
916 if (!IsZipping()) {
917 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
918 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800919 return false;
920 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800921 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700922 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700923 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700924 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700925 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800926 return false;
927 }
928
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700929 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700930 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700931 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700932 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800933 return false;
934 }
935
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700936 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700937 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700938 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800939 return false;
940 }
941
942 return true;
943}
944
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800945static void DoKmsg() {
946 struct stat st;
947 if (!stat(PSTORE_LAST_KMSG, &st)) {
948 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
949 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
950 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
951 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
952 } else {
953 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
954 DumpFile("LAST KMSG", "/proc/last_kmsg");
955 }
956}
957
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800958static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800959 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800960 RunCommand(
961 "KERNEL LOG",
962 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
963 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
964}
965
Nandana Duttdb379fa2019-10-09 16:54:41 +0100966static void DoSystemLogcat(time_t since) {
967 char since_str[80];
968 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
969
970 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
971 RunCommand("SYSTEM LOG",
972 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
973 since_str},
974 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
975}
976
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800977static void DoRadioLogcat() {
978 unsigned long timeout_ms = logcat_timeout({"radio"});
979 RunCommand(
980 "RADIO LOG",
981 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
982 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
983}
984
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800985static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800986 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800987 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
988 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800989 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100990 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800991 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
992 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800993 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800994 RunCommand(
995 "EVENT LOG",
996 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +0100997 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -0800998 timeout_ms = logcat_timeout({"stats"});
999 RunCommand(
1000 "STATS LOG",
1001 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +01001002 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001003 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001004
1005 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
1006
1007 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001008 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
1009 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001010}
1011
Mike Ma5c267872019-08-21 11:31:34 -07001012static void DumpIncidentReport() {
1013 if (!ds.IsZipping()) {
1014 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
1015 return;
1016 }
1017 DurationReporter duration_reporter("INCIDENT REPORT");
1018 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
1019 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1020 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1021 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1022 if (fd < 0) {
1023 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
1024 return;
1025 }
1026 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
1027 bool empty = 0 == lseek(fd, 0, SEEK_END);
1028 if (!empty) {
1029 // Use a different name from "incident.proto"
1030 // /proto/incident.proto is reserved for incident service dump
1031 // i.e. metadata for debugging.
1032 ds.AddZipEntry(kProtoPath + "incident_report" + kProtoExt, path);
1033 }
1034 unlink(path.c_str());
1035}
1036
Sunny Goyal35949782019-11-19 15:54:36 -08001037static void DumpVisibleWindowViews() {
1038 if (!ds.IsZipping()) {
1039 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
1040 return;
1041 }
1042 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
1043 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
1044 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
1045 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1046 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1047 if (fd < 0) {
1048 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
1049 return;
1050 }
1051 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
1052 CommandOptions::WithTimeout(120).Build());
1053 bool empty = 0 == lseek(fd, 0, SEEK_END);
1054 if (!empty) {
1055 ds.AddZipEntry("visible_windows.zip", path);
1056 } else {
1057 MYLOGW("Failed to dump visible windows\n");
1058 }
1059 unlink(path.c_str());
1060}
1061
Jayachandran Ca94c7172017-06-10 15:08:12 -07001062static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001063 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1064 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001065 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001066 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001067 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1068 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1069 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1070 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001071}
1072
David Andersond9ba4752018-12-11 18:26:59 -08001073static void DumpDynamicPartitionInfo() {
1074 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1075 return;
1076 }
1077
1078 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001079 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001080}
1081
Narayan Kamath8f788292017-05-25 13:20:39 +01001082static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1083 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1084 anr_traces_dir.c_str());
1085
1086 // If we're here, dump_traces_path will always be a temporary file
1087 // (created with mkostemp or similar) that contains dumps taken earlier
1088 // on in the process.
1089 if (dump_traces_path != nullptr) {
1090 if (add_to_zip) {
1091 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1092 } else {
1093 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1094 dump_traces_path);
1095 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1096 }
1097
1098 const int ret = unlink(dump_traces_path);
1099 if (ret == -1) {
1100 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1101 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001102 }
1103 }
1104
Narayan Kamathbd863722017-06-01 18:50:12 +01001105 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001106 if (ds.anr_data_.size() > 0) {
1107 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001108 "VM TRACES AT LAST ANR", add_to_zip);
1109
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001110 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1111 // it will be present in the body of the main entry if |add_to_zip| == false.
1112 //
1113 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001114 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001115 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001116 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001117 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1118 }
1119}
1120
1121static void AddAnrTraceFiles() {
1122 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1123
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001124 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001125
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001126 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001127
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001128 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1129
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001130 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001131 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001132 int i = 0;
1133 while (true) {
1134 const std::string slow_trace_path =
1135 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1136 if (stat(slow_trace_path.c_str(), &st)) {
1137 // No traces file at this index, done with the files.
1138 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001139 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001140 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1141 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001142 }
1143}
1144
Wei Wang509bb5d2017-06-09 14:42:12 -07001145static void DumpBlockStatFiles() {
1146 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001147
Wei Wang1dc1ef52017-06-12 11:28:37 -07001148 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1149
1150 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001151 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1152 return;
1153 }
1154
1155 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001156 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001157 if ((d->d_name[0] == '.')
1158 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1159 || (d->d_name[1] == '\0'))) {
1160 continue;
1161 }
1162 const std::string new_path =
1163 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1164 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1165 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1166 printf("\n");
1167 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001168 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001169}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001170
1171static void DumpPacketStats() {
1172 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1173 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1174 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1175 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1176 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1177}
1178
1179static void DumpIpAddrAndRules() {
1180 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1181 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1182 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1183 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1184 RunCommand("IP RULES", {"ip", "rule", "show"});
1185 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1186}
1187
Nandana Dutt5c390032019-03-12 10:52:56 +00001188static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1189 std::chrono::milliseconds timeout,
1190 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001191 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001192 sp<android::IServiceManager> sm = defaultServiceManager();
1193 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001194 Vector<String16> args;
1195 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001196 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1197 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001198 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001199 std::string path(title);
1200 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001201 size_t bytes_written = 0;
Steven Moreland5a30d342019-10-08 13:53:28 -07001202 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001203 if (status == OK) {
1204 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1205 std::chrono::duration<double> elapsed_seconds;
1206 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1207 /* as_proto = */ false, elapsed_seconds, bytes_written);
Vishnu Naire97d6122018-01-18 13:58:56 -08001208 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1209 bool dump_complete = (status == OK);
1210 dumpsys.stopDumpThread(dump_complete);
1211 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001212
1213 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1214 std::chrono::steady_clock::now() - start);
1215 if (elapsed_duration > timeout) {
1216 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1217 elapsed_duration.count());
1218 break;
1219 }
1220 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001221 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001222}
1223
Vishnu Nair64afc022018-02-01 15:29:34 -08001224static void RunDumpsysText(const std::string& title, int priority,
1225 std::chrono::milliseconds timeout,
1226 std::chrono::milliseconds service_timeout) {
1227 DurationReporter duration_reporter(title);
1228 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1229 fsync(STDOUT_FILENO);
1230 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1231}
1232
1233/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001234static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1235 std::chrono::milliseconds timeout,
1236 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001237 DurationReporter duration_reporter(title);
1238 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1239 fsync(STDOUT_FILENO);
1240 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1241 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001242
1243 RETURN_IF_USER_DENIED_CONSENT();
1244
1245 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1246 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001247}
1248
Nandana Dutt5c390032019-03-12 10:52:56 +00001249static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1250 std::chrono::milliseconds timeout,
1251 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001252 if (!ds.IsZipping()) {
1253 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001254 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001255 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001256 sp<android::IServiceManager> sm = defaultServiceManager();
1257 Dumpsys dumpsys(sm.get());
1258 Vector<String16> args;
1259 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1260 DurationReporter duration_reporter(title);
1261
1262 auto start = std::chrono::steady_clock::now();
1263 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1264 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001265 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001266 std::string path(kProtoPath);
1267 path.append(String8(service).c_str());
1268 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1269 path.append("_CRITICAL");
1270 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1271 path.append("_HIGH");
1272 }
1273 path.append(kProtoExt);
Steven Moreland5a30d342019-10-08 13:53:28 -07001274 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001275 if (status == OK) {
1276 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1277 bool dumpTerminated = (status == OK);
1278 dumpsys.stopDumpThread(dumpTerminated);
1279 }
1280 ZipWriter::FileEntry file_entry;
1281 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001282
1283 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1284 std::chrono::steady_clock::now() - start);
1285 if (elapsed_duration > timeout) {
1286 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1287 elapsed_duration.count());
1288 break;
1289 }
1290 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001291 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001292}
1293
Nandana Dutta7db6342018-11-21 14:53:34 +00001294// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001295static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001296 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1297 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001298
1299 RETURN_IF_USER_DENIED_CONSENT();
1300
1301 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1302 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001303}
1304
1305// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001306static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001307 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1308 // high priority. Reduce timeout once they are able to dump in a shorter time or
1309 // moved to a parallel task.
1310 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1311 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001312
1313 RETURN_IF_USER_DENIED_CONSENT();
1314
1315 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1316 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001317}
1318
1319// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001320static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001321 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001322
1323 RETURN_IF_USER_DENIED_CONSENT();
1324
1325 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1326 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001327}
1328
Steven Moreland44cd9482018-01-04 16:24:13 -08001329static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001330 if (!ds.IsZipping()) {
Yifan Hong30528a22020-08-07 18:24:06 -07001331 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all", "--debug"},
Steven Moreland9de8a1f2020-09-23 17:26:33 +00001332 CommandOptions::WithTimeout(60).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001333 return;
1334 }
1335 DurationReporter duration_reporter("DUMP HALS");
Yifan Hong30528a22020-08-07 18:24:06 -07001336 RunCommand("HARDWARE HALS", {"lshal", "--all", "--types=all"},
Greg Kaiser3dfeda32019-05-16 10:32:51 -07001337 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001338
Steven Moreland44cd9482018-01-04 16:24:13 -08001339 using android::hidl::manager::V1_0::IServiceManager;
1340 using android::hardware::defaultServiceManager;
1341
1342 sp<IServiceManager> sm = defaultServiceManager();
1343 if (sm == nullptr) {
1344 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1345 return;
1346 }
1347
1348 auto ret = sm->list([&](const auto& interfaces) {
1349 for (const std::string& interface : interfaces) {
1350 std::string cleanName = interface;
1351 std::replace_if(cleanName.begin(),
1352 cleanName.end(),
1353 [](char c) {
1354 return !isalnum(c) &&
1355 std::string("@-_:.").find(c) == std::string::npos;
1356 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001357 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001358
1359 {
1360 auto fd = android::base::unique_fd(
1361 TEMP_FAILURE_RETRY(open(path.c_str(),
1362 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1363 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1364 if (fd < 0) {
1365 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1366 continue;
1367 }
1368 RunCommandToFd(fd,
1369 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001370 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001371 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1372
1373 bool empty = 0 == lseek(fd, 0, SEEK_END);
1374 if (!empty) {
1375 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1376 }
1377 }
1378
1379 unlink(path.c_str());
1380 }
1381 });
1382
1383 if (!ret.isOk()) {
1384 MYLOGE("Could not list hals from hwservicemanager.\n");
1385 }
1386}
1387
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001388static void DumpExternalFragmentationInfo() {
1389 struct stat st;
1390 if (stat("/proc/buddyinfo", &st) != 0) {
1391 MYLOGE("Unable to dump external fragmentation info\n");
1392 return;
1393 }
1394
1395 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1396 std::ifstream ifs("/proc/buddyinfo");
1397 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1398 for (std::string line; std::getline(ifs, line);) {
1399 std::smatch match_results;
1400 if (std::regex_match(line, match_results, unusable_index_regex)) {
1401 std::stringstream free_pages(std::string{match_results[3]});
1402 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1403 std::istream_iterator<int>());
1404
1405 int total_free_pages = 0;
1406 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1407 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1408 }
1409
1410 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1411 match_results[2].str().c_str());
1412
1413 int usable_free_pages = total_free_pages;
1414 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1415 auto unusable_index = (total_free_pages - usable_free_pages) /
1416 static_cast<double>(total_free_pages);
1417 printf(" %5.3f", unusable_index);
1418 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1419 }
1420
1421 printf("\n");
1422 }
1423 }
1424 printf("\n");
1425}
1426
mhasankd451a472020-05-26 18:02:39 -07001427static void DumpstateLimitedOnly() {
1428 // Trimmed-down version of dumpstate to only include a whitelisted
1429 // set of logs (system log, event log, and system server / system app
1430 // crashes, and networking logs). See b/136273873 and b/138459828
1431 // for context.
1432 DurationReporter duration_reporter("DUMPSTATE");
1433 unsigned long timeout_ms;
1434 // calculate timeout
1435 timeout_ms = logcat_timeout({"main", "system", "crash"});
1436 RunCommand("SYSTEM LOG",
1437 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1438 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1439 timeout_ms = logcat_timeout({"events"});
1440 RunCommand(
1441 "EVENT LOG",
1442 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1443 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1444
1445 printf("========================================================\n");
1446 printf("== Networking Service\n");
1447 printf("========================================================\n");
1448
1449 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1450 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1451
1452 printf("========================================================\n");
1453 printf("== Dropbox crashes\n");
1454 printf("========================================================\n");
1455
1456 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1457 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1458
1459 printf("========================================================\n");
1460 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1461 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1462 printf("========================================================\n");
1463 printf("== dumpstate: done (id %d)\n", ds.id_);
1464 printf("========================================================\n");
1465}
1466
Nandana Dutt5c390032019-03-12 10:52:56 +00001467// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1468// via the consent they are shown. Ignores other errors that occur while running various
1469// commands. The consent checking is currently done around long running tasks, which happen to
1470// be distributed fairly evenly throughout the function.
1471static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001472 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001473
Nandana Dutt5c390032019-03-12 10:52:56 +00001474 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1475 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1476 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001477 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001478 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001479 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001480 DumpFile("MEMORY INFO", "/proc/meminfo");
1481 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001482 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001483
1484 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1485
Sunny Goyal35949782019-11-19 15:54:36 -08001486 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1487
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001488 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1489 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1490 DumpFile("SLAB INFO", "/proc/slabinfo");
1491 DumpFile("ZONEINFO", "/proc/zoneinfo");
1492 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1493 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001494 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001495
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001496 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1497 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001498
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001499 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001500 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001501
1502 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1503 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001504
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001505 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001506
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001507 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001508 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001509 struct stat s;
1510 if (stat("/proc/modules", &s) != 0) {
1511 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1512 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001513 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001514 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001515
Tom Cherryb87dbfa2020-07-28 11:28:53 -07001516 if (android::base::GetBoolProperty("ro.logd.kernel", false)) {
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001517 DoKernelLogcat();
1518 } else {
1519 do_dmesg();
1520 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001521
Felipe Lemef0292972016-11-22 13:57:05 -08001522 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001523
1524 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1525
Jeff Brown1dc94e32014-09-11 14:15:27 -07001526 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001527 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001528
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001529 /* Dump Bluetooth HCI logs */
1530 ds.AddDir("/data/misc/bluetooth/logs", true);
Jack Yu5a6b2e22020-08-14 18:13:35 +08001531 /* Dump Nfc NCI logs */
1532 ds.AddDir("/data/misc/nfc/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001533
Paul Chang0d2aad72020-02-13 20:04:03 +08001534 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001535 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001536 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001537 }
1538
Felipe Lemee184f662016-10-27 10:04:47 -07001539 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001540
Narayan Kamath8f788292017-05-25 13:20:39 +01001541 // NOTE: tombstones are always added as separate entries in the zip archive
1542 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001543 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001544 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001545 if (!tombstones_dumped) {
1546 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001547 }
1548
Jayachandran Ca94c7172017-06-10 15:08:12 -07001549 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001550
Chenbo Feng276a3b62018-08-07 11:44:49 -07001551 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1552
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001553 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001554
Jayachandran Ca94c7172017-06-10 15:08:12 -07001555 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001556
1557 dump_route_tables();
1558
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001559 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1560 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1561 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001562
Nandana Dutt5c390032019-03-12 10:52:56 +00001563 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001564
Elliott Hughes23ccc622017-02-28 10:14:22 -08001565 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001566
Jin Qianf334d662017-10-10 14:41:37 -07001567 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001568
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001569 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001570
Colin Crossf45fa6b2012-03-26 12:38:26 -07001571 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001572 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1573 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1574
1575 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1576 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1577 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1578 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1579 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001580
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001581 /* Add window and surface trace files. */
1582 if (!PropertiesHelper::IsUserBuild()) {
1583 ds.AddDir(WMTRACE_DATA_DIR, false);
1584 }
1585
Yifan Hongcba0a4f2020-02-08 16:52:02 -08001586 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1587
Nandana Dutt5c390032019-03-12 10:52:56 +00001588 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001589
Steven Moreland7440ddb2016-12-15 16:13:39 -08001590 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001591 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1592 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001593 // su does not exist on user builds, so try running without it.
1594 // This way any implementations of vril-dump that do not require
1595 // root can run on user builds.
1596 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001597 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001598 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001599 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001600 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001601 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001602 }
1603
Felipe Lemed8b94e52016-12-08 10:21:44 -08001604 printf("========================================================\n");
1605 printf("== Android Framework Services\n");
1606 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001607
Nandana Dutt5c390032019-03-12 10:52:56 +00001608 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001609
Felipe Lemed8b94e52016-12-08 10:21:44 -08001610 printf("========================================================\n");
1611 printf("== Checkins\n");
1612 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001613
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001614 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001615
1616 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1617
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001618 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1619 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1620 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1621 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001622
Felipe Lemed8b94e52016-12-08 10:21:44 -08001623 printf("========================================================\n");
1624 printf("== Running Application Activities\n");
1625 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001626
Makoto Onuki60780982018-04-16 15:34:00 -07001627 // The following dumpsys internally collects output from running apps, so it can take a long
1628 // time. So let's extend the timeout.
1629
1630 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1631
1632 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001633
Felipe Lemed8b94e52016-12-08 10:21:44 -08001634 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001635 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001636 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001637
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001638 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001639 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001640
Felipe Lemed8b94e52016-12-08 10:21:44 -08001641 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001642 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001643 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001644
Makoto Onuki60780982018-04-16 15:34:00 -07001645 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1646 DUMPSYS_COMPONENTS_OPTIONS);
1647
1648 printf("========================================================\n");
1649 printf("== Running Application Providers (platform)\n");
1650 printf("========================================================\n");
1651
1652 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1653 DUMPSYS_COMPONENTS_OPTIONS);
1654
1655 printf("========================================================\n");
1656 printf("== Running Application Providers (non-platform)\n");
1657 printf("========================================================\n");
1658
1659 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1660 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001661
Adrian Roos8b397ab2017-04-04 16:35:44 -07001662 printf("========================================================\n");
1663 printf("== Dropbox crashes\n");
1664 printf("========================================================\n");
1665
1666 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1667 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1668
Felipe Lemed8b94e52016-12-08 10:21:44 -08001669 printf("========================================================\n");
1670 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1671 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1672 printf("========================================================\n");
1673 printf("== dumpstate: done (id %d)\n", ds.id_);
1674 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001675
1676 printf("========================================================\n");
1677 printf("== Obtaining statsd metadata\n");
1678 printf("========================================================\n");
1679 // This differs from the usual dumpsys stats, which is the stats report data.
1680 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001681
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001682 // Add linker configuration directory
1683 ds.AddDir(LINKERCONFIG_DIR, true);
1684
Mike Ma5c267872019-08-21 11:31:34 -07001685 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
1686
Nandana Dutt5c390032019-03-12 10:52:56 +00001687 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001688}
1689
Nandana Dutt5c390032019-03-12 10:52:56 +00001690/*
1691 * Dumps state for the default case; drops root after it's no longer necessary.
1692 *
1693 * Returns RunStatus::OK if everything went fine.
1694 * Returns RunStatus::ERROR if there was an error.
1695 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1696 * with the caller.
1697 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001698Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001699 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1700 // buffer.
1701 DoLogcat();
1702 // Capture timestamp after first logcat to use in next logcat
1703 time_t logcat_ts = time(nullptr);
1704
Nandana Dutt4be45d12018-09-26 15:04:23 +01001705 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao1c855122020-07-16 17:37:39 +08001706 if (dump_pool_) {
1707 RETURN_IF_USER_DENIED_CONSENT();
1708 // One thread is enough since we only need to enqueue DumpTraces here.
1709 dump_pool_->start(/* thread_counts = */1);
1710
1711 // DumpTraces takes long time, post it to the another thread in the
1712 // pool, if pool is available
1713 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1714 } else {
1715 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1716 &dump_traces_path);
1717 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001718
1719 /* Run some operations that require root. */
1720 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1721 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1722
1723 ds.AddDir(RECOVERY_DIR, true);
1724 ds.AddDir(RECOVERY_DATA_DIR, true);
1725 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1726 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1727 if (!PropertiesHelper::IsUserBuild()) {
1728 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1729 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravle78a0d842020-04-28 15:31:12 -07001730 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001731 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001732 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001733 add_mountinfo();
1734 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001735 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001736 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001737
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001738 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001739 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1740
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001741 // Dump IPsec stats. No keys are exposed here.
1742 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1743
Nandana Dutt4be45d12018-09-26 15:04:23 +01001744 // Run ss as root so we can see socket marks.
1745 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1746
1747 // Run iotop as root to show top 100 IO threads
1748 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1749
Erick Reyese68df822019-02-11 14:46:36 -08001750 // Gather shared memory buffer info if the product implements it
1751 struct stat st;
1752 if (!stat("/product/bin/dmabuf_dump", &st)) {
1753 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1754 }
1755
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001756 DumpFile("PSI cpu", "/proc/pressure/cpu");
1757 DumpFile("PSI memory", "/proc/pressure/memory");
1758 DumpFile("PSI io", "/proc/pressure/io");
1759
Rhed Jao1c855122020-07-16 17:37:39 +08001760 if (dump_pool_) {
1761 RETURN_IF_USER_DENIED_CONSENT();
1762 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1763
1764 // Current running thread in the pool is the root user also. Shutdown
1765 // the pool and restart later to ensure all threads in the pool could
1766 // drop the root user.
1767 dump_pool_->shutdown();
1768 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001769 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001770 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001771 }
1772
Nandana Dutt5c390032019-03-12 10:52:56 +00001773 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001774 Dumpstate::RunStatus status = dumpstate();
1775 // Capture logcat since the last time we did it.
1776 DoSystemLogcat(logcat_ts);
1777 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001778}
1779
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001780// This method collects common dumpsys for telephony and wifi. Typically, wifi
1781// reports are fine to include all information, but telephony reports on user
1782// builds need to strip some content (see DumpstateTelephonyOnly).
1783static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001784 DumpIpTablesAsRoot();
1785
Jayachandran C69968272019-07-08 09:46:05 -07001786 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1787
Jayachandran Ca94c7172017-06-10 15:08:12 -07001788 if (!DropRootUser()) {
1789 return;
1790 }
1791
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001792 // We need to be picky about some stuff for telephony reports on user builds.
1793 if (!include_sensitive_info) {
1794 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1795 DoRadioLogcat();
1796 } else {
1797 // Contains various system properties and process startup info.
1798 do_dmesg();
1799 // Logs other than the radio buffer may contain package/component names and potential PII.
1800 DoLogcat();
1801 // Too broad for connectivity problems.
1802 DoKmsg();
1803 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
1804 DumpHals();
1805 }
1806
Jayachandran Ca94c7172017-06-10 15:08:12 -07001807 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001808 DumpIpAddrAndRules();
1809 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001810 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1811 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001812}
1813
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001814// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1815// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1816// for what can be included on user builds: all reported information MUST directly relate to
1817// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1818// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1819// names are not), and MUST NOT contain logs of user application traffic.
1820// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001821static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001822 DurationReporter duration_reporter("DUMPSTATE");
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001823
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001824 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001825
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001826 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001827
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001828 DumpstateRadioCommon(include_sensitive_info);
1829
1830 if (include_sensitive_info) {
1831 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1832 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1833 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1834 // way.
1835 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1836 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001837
1838 printf("========================================================\n");
1839 printf("== Android Framework Services\n");
1840 printf("========================================================\n");
1841
Vishnu Nair652cc802017-11-30 15:18:30 -08001842 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1843 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001844 if (include_sensitive_info) {
1845 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1846 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1847 SEC_TO_MSEC(10));
1848 } else {
1849 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1850 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1851 // give a higher timeout as well.
1852 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1853 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1854 }
1855 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001856 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1857 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001858 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001859 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1860 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001861 if (include_sensitive_info) {
1862 // Contains raw IP addresses, omit from reports on user builds.
1863 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1864 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1865 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1866 SEC_TO_MSEC(10));
1867 // Contains package/component names, omit from reports on user builds.
1868 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1869 SEC_TO_MSEC(10));
1870 // Contains package names, but should be relatively simple to remove them (also contains
1871 // UIDs already), omit from reports on user builds.
1872 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1873 SEC_TO_MSEC(10));
1874 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001875
1876 printf("========================================================\n");
1877 printf("== Running Application Services\n");
1878 printf("========================================================\n");
1879
1880 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1881
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001882 if (include_sensitive_info) {
1883 printf("========================================================\n");
1884 printf("== Running Application Services (non-platform)\n");
1885 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001886
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001887 // Contains package/component names and potential PII, omit from reports on user builds.
1888 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1889 // carrier_config dumpsys instead.
1890 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1891 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001892
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001893 printf("========================================================\n");
1894 printf("== Checkins\n");
1895 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001896
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001897 // Contains package/component names, omit from reports on user builds.
1898 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1899 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001900
1901 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001902 printf("== dumpstate: done (id %d)\n", ds.id_);
1903 printf("========================================================\n");
1904}
1905
mukesh agrawal253dad42018-01-23 21:59:59 -08001906// This method collects dumpsys for wifi debugging only
1907static void DumpstateWifiOnly() {
1908 DurationReporter duration_reporter("DUMPSTATE");
1909
1910 DumpstateRadioCommon();
1911
1912 printf("========================================================\n");
1913 printf("== Android Framework Services\n");
1914 printf("========================================================\n");
1915
1916 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1917 SEC_TO_MSEC(10));
1918 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1919 SEC_TO_MSEC(10));
1920
1921 printf("========================================================\n");
1922 printf("== dumpstate: done (id %d)\n", ds.id_);
1923 printf("========================================================\n");
1924}
1925
Nandana Duttcf419a72019-03-14 10:40:17 +00001926Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001927 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1928 const size_t buf_size = temp_file_pattern.length() + 1;
1929 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1930 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1931
1932 // Create a new, empty file to receive all trace dumps.
1933 //
1934 // TODO: This can be simplified once we remove support for the old style
1935 // dumps. We can have a file descriptor passed in to dump_traces instead
1936 // of creating a file, closing it and then reopening it again.
1937 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1938 if (fd < 0) {
1939 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001940 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001941 }
1942
1943 // Nobody should have access to this temporary file except dumpstate, but we
1944 // temporarily grant 'read' to 'others' here because this file is created
1945 // when tombstoned is still running as root, but dumped after dropping. This
1946 // can go away once support for old style dumping has.
1947 const int chmod_ret = fchmod(fd, 0666);
1948 if (chmod_ret < 0) {
1949 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001950 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001951 }
1952
1953 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1954 if (proc.get() == nullptr) {
1955 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001956 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001957 }
1958
1959 // Number of times process dumping has timed out. If we encounter too many
1960 // failures, we'll give up.
1961 int timeout_failures = 0;
1962 bool dalvik_found = false;
1963
1964 const std::set<int> hal_pids = get_interesting_hal_pids();
1965
1966 struct dirent* d;
1967 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001968 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001969 int pid = atoi(d->d_name);
1970 if (pid <= 0) {
1971 continue;
1972 }
1973
1974 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1975 std::string exe;
1976 if (!android::base::Readlink(link_name, &exe)) {
1977 continue;
1978 }
1979
1980 bool is_java_process;
1981 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1982 // Don't bother dumping backtraces for the zygote.
1983 if (IsZygote(pid)) {
1984 continue;
1985 }
1986
1987 dalvik_found = true;
1988 is_java_process = true;
1989 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1990 is_java_process = false;
1991 } else {
1992 // Probably a native process we don't care about, continue.
1993 continue;
1994 }
1995
1996 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1997 if (timeout_failures == 3) {
1998 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1999 break;
2000 }
2001
2002 const uint64_t start = Nanotime();
2003 const int ret = dump_backtrace_to_file_timeout(
2004 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2005 is_java_process ? 5 : 20, fd);
2006
2007 if (ret == -1) {
2008 // For consistency, the header and footer to this message match those
2009 // dumped by debuggerd in the success case.
2010 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2011 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2012 dprintf(fd, "---- end %d ----", pid);
2013 timeout_failures++;
2014 continue;
2015 }
2016
2017 // We've successfully dumped stack traces, reset the failure count
2018 // and write a summary of the elapsed time to the file and continue with the
2019 // next process.
2020 timeout_failures = 0;
2021
2022 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2023 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2024 }
2025
2026 if (!dalvik_found) {
2027 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2028 }
2029
Nandana Duttcf419a72019-03-14 10:40:17 +00002030 *path = file_name_buf.release();
2031 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002032}
2033
Felipe Leme6f674ae2016-11-18 17:10:33 -08002034void Dumpstate::DumpstateBoard() {
2035 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08002036 printf("========================================================\n");
2037 printf("== Board\n");
2038 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002039
Felipe Leme6f674ae2016-11-18 17:10:33 -08002040 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002041 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002042 return;
2043 }
2044
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002045 std::vector<std::string> paths;
2046 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002047 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002048 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2049 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002050 remover.emplace_back(android::base::make_scope_guard(
2051 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002052 }
Jie Song9fbfad02017-06-20 16:29:42 -07002053
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002054 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2055 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002056 MYLOGE("No IDumpstateDevice implementation\n");
2057 return;
2058 }
2059
2060 using ScopedNativeHandle =
2061 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2062 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2063 [](native_handle_t* handle) {
2064 native_handle_close(handle);
2065 native_handle_delete(handle);
2066 });
2067 if (handle == nullptr) {
2068 MYLOGE("Could not create native_handle\n");
2069 return;
2070 }
2071
Nandana Dutt5c390032019-03-12 10:52:56 +00002072 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002073 for (size_t i = 0; i < paths.size(); i++) {
2074 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2075
2076 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2077 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2078 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2079 if (fd < 0) {
2080 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2081 return;
2082 }
2083 handle.get()->data[i] = fd.release();
2084 }
2085
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002086 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2087 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2088 // will kill the HAL and grab whatever it dumped in time.
2089 constexpr size_t timeout_sec = 30;
2090 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2091 // implement just 1.0.
2092 const char* descriptor_to_kill;
2093 using DumpstateBoardTask = std::packaged_task<bool()>;
2094 DumpstateBoardTask dumpstate_board_task;
2095 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2096 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2097 if (dumpstate_device_1_1 != nullptr) {
2098 MYLOGI("Using IDumpstateDevice v1.1");
2099 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2100 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2101 ::android::hardware::Return<DumpstateStatus> status =
2102 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2103 SEC_TO_MSEC(timeout_sec));
2104 if (!status.isOk()) {
2105 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2106 return false;
2107 } else if (status != DumpstateStatus::OK) {
2108 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2109 return false;
2110 }
2111 return true;
2112 });
2113 } else {
2114 MYLOGI("Using IDumpstateDevice v1.0");
2115 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2116 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2117 ::android::hardware::Return<void> status =
2118 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002119 if (!status.isOk()) {
2120 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002121 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002122 }
Wei Wang587eac92018-04-05 12:17:20 -07002123 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002124 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002125 }
2126 auto result = dumpstate_board_task.get_future();
2127 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002128
Wei Wang587eac92018-04-05 12:17:20 -07002129 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2130 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002131 if (!android::base::SetProperty(
2132 "ctl.interface_restart",
2133 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002134 MYLOGE("Couldn't restart dumpstate HAL\n");
2135 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002136 }
Wei Wang587eac92018-04-05 12:17:20 -07002137 // Wait some time for init to kill dumpstate vendor HAL
2138 constexpr size_t killing_timeout_sec = 10;
2139 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2140 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2141 "there might be racing in content\n", killing_timeout_sec);
2142 }
2143
2144 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2145 for (size_t i = 0; i < paths.size(); i++) {
2146 struct stat s;
2147 if (fstat(handle.get()->data[i], &s) == -1) {
2148 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2149 strerror(errno));
2150 file_sizes[i] = -1;
2151 continue;
2152 }
2153 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002154 }
2155
2156 for (size_t i = 0; i < paths.size(); i++) {
2157 if (file_sizes[i] == -1) {
2158 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002159 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002160 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002161 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002162 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002163 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002164 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002165 printf("*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002166 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002167}
2168
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002169static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002170 fprintf(stderr,
mhasank2d75c442020-06-11 15:05:25 -07002171 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-d] [-p] "
mhasankd451a472020-05-26 18:02:39 -07002172 "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002173 " -h: display this help message\n"
2174 " -b: play sound file instead of vibrate, at beginning of job\n"
2175 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002176 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002177 " -d: append date to filename\n"
2178 " -p: capture screenshot to filename.png\n"
2179 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002180 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002181 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002182 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002183 " -P: send broadcast when started and do progress updates\n"
2184 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002185 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002186 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002187 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002188}
2189
Wei Liuf87959e2016-08-26 14:51:42 -07002190static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002191 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002192}
2193
Felipe Leme1d486fe2016-10-14 18:06:47 -07002194bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002195 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002196 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002197 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002198 // Final timestamp
2199 char date[80];
2200 time_t the_real_now_please_stand_up = time(nullptr);
2201 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002202 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002203 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002204
Felipe Leme9a523ae2016-10-20 15:10:33 -07002205 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002206 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002207 return false;
2208 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002209 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002210 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002211 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002212 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002213
Felipe Leme0f3fb202016-06-10 17:10:53 -07002214 // Add log file (which contains stderr output) to zip...
2215 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002216 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002217 MYLOGE("Failed to add dumpstate log to .zip file\n");
2218 return false;
2219 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002220 // TODO: Should truncate the existing file.
2221 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002222 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2223 return false;
2224 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002225 fprintf(stderr, "\n");
2226
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002227 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002228 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002229 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002230 return false;
2231 }
2232
Felipe Leme1d486fe2016-10-14 18:06:47 -07002233 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2234 ds.zip_file.reset(nullptr);
2235
Felipe Lemee9d2c542016-11-15 11:48:26 -08002236 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002237 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002238
Felipe Leme1e9edc62015-12-21 16:02:13 -08002239 return true;
2240}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002241
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002242static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2243 // clang-format off
2244 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2245 "--receiver-foreground", "--receiver-include-background", "-a", action};
2246 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002247
2248 am.insert(am.end(), args.begin(), args.end());
2249
Felipe Leme8d2410e2017-02-08 09:46:08 -08002250 RunCommand("", am,
2251 CommandOptions::WithTimeout(20)
2252 .Log("Sending broadcast: '%s'\n")
2253 .Always()
2254 .DropRoot()
2255 .RedirectStderr()
2256 .Build());
2257}
2258
Felipe Leme35b8cf12017-02-10 15:47:29 -08002259static void Vibrate(int duration_ms) {
2260 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002261 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002262 CommandOptions::WithTimeout(10)
2263 .Log("Vibrate: '%s'\n")
2264 .Always()
2265 .Build());
2266 // clang-format on
2267}
2268
Nandana Dutt979388e2018-11-30 16:48:55 +00002269static void MaybeResolveSymlink(std::string* path) {
2270 std::string resolved_path;
2271 if (android::base::Readlink(*path, &resolved_path)) {
2272 *path = resolved_path;
2273 }
2274}
2275
Nandana Dutt4be45d12018-09-26 15:04:23 +01002276/*
2277 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2278 * if we are writing zip files and adds the version file.
2279 */
2280static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002281 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2282
Nandana Dutt4be45d12018-09-26 15:04:23 +01002283 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2284 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002285 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002286 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002287 char date[80];
2288 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2289 ds.name_ = date;
2290 } else {
2291 ds.name_ = "undated";
2292 }
2293
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002294 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002295 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002296 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002297 ds.base_name_ += "-wifi";
2298 }
2299
Paul Chang0d2aad72020-02-13 20:04:03 +08002300 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002301 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002302 }
2303 ds.tmp_path_ = ds.GetPath(".tmp");
2304 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2305
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002306 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002307 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002308 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002309 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002310 "Bugreport dir: [%s] "
2311 "Base name: [%s] "
2312 "Suffix: [%s] "
2313 "Log path: [%s] "
2314 "Temporary path: [%s] "
2315 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002316 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2317 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002318
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002319 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002320 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002321 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2322 create_parent_dirs(ds.path_.c_str());
2323 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2324 if (ds.zip_file == nullptr) {
2325 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2326 } else {
2327 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2328 }
2329 ds.AddTextZipEntry("version.txt", ds.version_);
2330 }
2331}
2332
2333/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002334 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002335 * printing zipped file status, etc.
2336 */
2337static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002338 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002339 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002340 if (!ds.FinishZipFile()) {
2341 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2342 do_text_file = true;
2343 } else {
2344 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002345 }
2346 }
mhasank2d75c442020-06-11 15:05:25 -07002347
2348 std::string final_path = ds.path_;
2349 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002350 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002351 android::os::CopyFileToFile(ds.path_, final_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002352 }
mhasank2d75c442020-06-11 15:05:25 -07002353
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002354 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002355 if (do_text_file) {
2356 dprintf(ds.control_socket_fd_,
2357 "FAIL:could not create zip file, check %s "
2358 "for more details\n",
2359 ds.log_path_.c_str());
2360 } else {
mhasank2d75c442020-06-11 15:05:25 -07002361 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002362 }
2363 }
2364}
2365
Nandana Dutt4be45d12018-09-26 15:04:23 +01002366
Nandana Dutt58d72e22018-11-16 10:30:48 +00002367static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2368 switch (mode) {
2369 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2370 return "BUGREPORT_FULL";
2371 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2372 return "BUGREPORT_INTERACTIVE";
2373 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2374 return "BUGREPORT_REMOTE";
2375 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2376 return "BUGREPORT_WEAR";
2377 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2378 return "BUGREPORT_TELEPHONY";
2379 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2380 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002381 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2382 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002383 }
2384}
2385
Paul Changf59c2b72020-03-10 02:08:55 +08002386static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2387 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002388 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2389 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002390 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002391 switch (mode) {
2392 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002393 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002394 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002395 break;
2396 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002397 // Currently, the dumpstate binder is only used by Shell to update progress.
2398 options->do_start_service = true;
2399 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002400 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002401 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002402 break;
2403 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002404 options->do_vibrate = false;
2405 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002406 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002407 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002408 break;
2409 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002410 options->do_start_service = true;
2411 options->do_progress_updates = true;
2412 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002413 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002414 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002415 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002416 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002417 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002418 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002419 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002420 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002421 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002422 break;
2423 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002424 options->wifi_only = true;
2425 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002426 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002427 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002428 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002429 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2430 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002431 }
2432}
2433
Nandana Dutt58d72e22018-11-16 10:30:48 +00002434static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002435 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002436 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002437 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002438 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002439 "limited_only: %d args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002440 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002441 options.do_screenshot, options.is_remote_mode, options.show_header_only,
mhasankd451a472020-05-26 18:02:39 -07002442 options.do_start_service, options.telephony_only, options.wifi_only,
2443 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2444 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002445}
2446
Nandana Dutt54dbd672019-01-11 12:58:05 +00002447void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2448 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002449 const android::base::unique_fd& screenshot_fd_in,
2450 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002451 // In the new API world, date is always added; output is always a zip file.
2452 // TODO(111441001): remove these options once they are obsolete.
2453 do_add_date = true;
2454 do_zip_file = true;
2455
Nandana Dutt54dbd672019-01-11 12:58:05 +00002456 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2457 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2458 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002459
Paul Changf59c2b72020-03-10 02:08:55 +08002460 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002461}
2462
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002463Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2464 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002465 int c;
mhasankd451a472020-05-26 18:02:39 -07002466 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002467 switch (c) {
2468 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002469 case 'd': do_add_date = true; break;
2470 case 'z': do_zip_file = true; break;
mhasank3a4cfb42020-06-15 18:06:43 -07002471 case 'o': out_dir = optarg; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002472 case 's': use_socket = true; break;
2473 case 'S': use_control_socket = true; break;
2474 case 'v': show_header_only = true; break;
2475 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002476 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002477 case 'P': do_progress_updates = true; break;
2478 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002479 case 'L': limited_only = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002480 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002481 case 'w':
2482 // This was already processed
2483 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002484 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002485 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002486 break;
2487 default:
2488 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002489 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002490 break;
2491 // clang-format on
2492 }
2493 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002494
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002495 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002496 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002497 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002498 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002499 }
2500 }
2501
2502 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2503 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002504
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002505 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002506}
2507
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002508bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002509 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002510 return false;
2511 }
2512
Abhijeet Kaure370d682019-10-01 16:49:30 +01002513 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002514 return false;
2515 }
2516
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002517 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002518 return false;
2519 }
2520
Abhijeet Kaure370d682019-10-01 16:49:30 +01002521 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002522 return false;
2523 }
2524 return true;
2525}
2526
Nandana Dutt197661d2018-11-16 16:40:21 +00002527void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2528 options_ = std::move(options);
2529}
2530
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002531void Dumpstate::Initialize() {
2532 /* gets the sequential id */
2533 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2534 id_ = ++last_id;
2535 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2536}
2537
Nandana Duttd2f5f082019-01-18 17:13:52 +00002538Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2539 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002540 if (listener_ != nullptr) {
2541 switch (status) {
2542 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002543 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002544 break;
2545 case Dumpstate::RunStatus::HELP:
2546 break;
2547 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002548 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002549 break;
2550 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002551 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2552 break;
2553 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2554 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2555 break;
2556 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2557 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002558 break;
2559 }
2560 }
2561 return status;
2562}
2563
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002564void Dumpstate::Cancel() {
2565 CleanupTmpFiles();
2566 android::os::UnlinkAndLogOnError(log_path_);
2567 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2568 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2569 kDumpstateBoardFiles[i]);
2570 }
2571 tombstone_data_.clear();
2572 anr_data_.clear();
2573}
2574
Nandana Dutt979388e2018-11-30 16:48:55 +00002575/*
2576 * Dumps relevant information to a bugreport based on the given options.
2577 *
2578 * The bugreport can be dumped to a file or streamed to a socket.
2579 *
2580 * How dumping to file works:
2581 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2582 * stderr is redirected a log file.
2583 *
2584 * The temporary bugreport is then populated via printfs, dumping contents of files and
2585 * output of commands to stdout.
2586 *
2587 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2588 * text file.
2589 *
2590 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2591 * gets added to the archive.
2592 *
mhasank2d75c442020-06-11 15:05:25 -07002593 * Bugreports are first generated in a local directory and later copied to the caller's fd
2594 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002595 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002596Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2597 const std::string& calling_package) {
Rhed Jao1c855122020-07-16 17:37:39 +08002598 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002599 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002600 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002601 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002602 return RunStatus::INVALID_INPUT;
2603 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002604 /* set as high priority, and protect from OOM killer */
2605 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002606
Felipe Lemed071c682016-10-20 16:48:00 -07002607 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002608 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002609 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002610 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002611 } else {
2612 /* fallback to kernels <= 2.6.35 */
2613 oom_adj = fopen("/proc/self/oom_adj", "we");
2614 if (oom_adj) {
2615 fputs("-17", oom_adj);
2616 fclose(oom_adj);
2617 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002618 }
2619
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002620 if (version_ == VERSION_DEFAULT) {
2621 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002622 }
2623
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002624 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002625 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002626 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002627 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002628 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002629 }
2630
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002631 if (options_->show_header_only) {
2632 PrintHeader();
2633 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002634 }
2635
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002636 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2637 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002638
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002639 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002640 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002641
2642 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002643 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002644 is_redirecting
2645 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2646 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002647 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002648
Sahana Raof35ed432019-07-12 10:47:52 +01002649 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2650 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2651 } else {
2652 // Wake lock will be released automatically on process death
2653 MYLOGD("Wake lock acquired.\n");
2654 }
2655
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002656 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002657
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002658 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002659 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002660 MYLOGI("Starting 'dumpstate' service\n");
2661 android::status_t ret;
2662 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2663 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2664 }
2665 }
2666
Felipe Lemef0292972016-11-22 13:57:05 -08002667 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002668 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2669 }
2670
Nandana Dutt235c6672019-11-14 15:22:32 +00002671 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2672 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002673
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002674 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002675
Christopher Ferrised9354f2014-10-01 17:35:01 -07002676 // If we are going to use a socket, do it as early as possible
2677 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002678 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002679 if (!redirect_to_socket(stdout, "dumpstate")) {
2680 return ERROR;
2681 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002682 }
2683
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002684 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002685 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002686 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002687 if (control_socket_fd_ == -1) {
2688 return ERROR;
2689 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002690 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002691 }
2692
Felipe Leme71bbfc52015-11-23 14:14:51 -08002693 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002694 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002695
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002696 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002697 // clang-format off
2698 std::vector<std::string> am_args = {
2699 "--receiver-permission", "android.permission.DUMP",
2700 };
2701 // clang-format on
2702 // Send STARTED broadcast for apps that listen to bugreport generation events
2703 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002704 if (options_->use_control_socket) {
2705 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002706 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002707 }
2708 }
2709
Nick Kralevichf3599b32016-01-25 15:05:16 -08002710 /* read /proc/cmdline before dropping root */
2711 FILE *cmdline = fopen("/proc/cmdline", "re");
2712 if (cmdline) {
2713 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2714 fclose(cmdline);
2715 }
2716
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002717 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002718 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002719 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002720
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002721 if (options_->do_zip_file && zip_file != nullptr) {
2722 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2723 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002724 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002725 }
2726 }
2727
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002728 int dup_stdout_fd;
2729 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002730 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002731 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002732 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002733 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2734 return ERROR;
2735 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002736 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2737 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2738 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002739 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002740
2741 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2742 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002743 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002744 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002745 /* TODO: rather than generating a text file now and zipping it later,
2746 it would be more efficient to redirect stdout to the zip entry
2747 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002748 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2749 return ERROR;
2750 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002751 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002752 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002753 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002754 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002755 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002756
2757 // Don't buffer stdout
2758 setvbuf(stdout, nullptr, _IONBF, 0);
2759
Rhed Jao1c855122020-07-16 17:37:39 +08002760 // Enable the parallel run if the client requests to output to a file.
2761 EnableParallelRunIfNeeded();
2762 // Using scope guard to make sure the dump pool can be shut down correctly.
2763 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2764 ShutdownDumpPool();
2765 });
2766
Felipe Leme608385d2016-02-01 10:35:38 -08002767 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2768 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002769 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002770 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002771
mhasankd451a472020-05-26 18:02:39 -07002772 // TODO(b/158737089) reduce code repetition in if branches
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002773 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002774 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002775 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002776 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002777 DumpstateTelephonyOnly(calling_package);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002778 DumpstateBoard();
2779 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002780 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002781 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002782 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002783 DumpstateWifiOnly();
mhasankd451a472020-05-26 18:02:39 -07002784 } else if (options_->limited_only) {
2785 MaybeTakeEarlyScreenshot();
2786 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
2787 MaybeCheckUserConsent(calling_uid, calling_package);
2788 DumpstateLimitedOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002789 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002790 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002791 RunDumpsysCritical();
2792
Paul Chang0d2aad72020-02-13 20:04:03 +08002793 // Take screenshot and get consent only after critical dumpsys has finished.
2794 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002795 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002796 MaybeCheckUserConsent(calling_uid, calling_package);
2797
Nandana Dutt4be45d12018-09-26 15:04:23 +01002798 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002799 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002800 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002801 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002802 HandleUserConsentDenied();
2803 }
2804 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002805 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002806 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002807
Felipe Leme55b42a62015-11-10 17:39:08 -08002808 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002809 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002810 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002811 }
2812
Abhijeet Kaure370d682019-10-01 16:49:30 +01002813 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002814 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002815 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002816 }
2817
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002818 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002819 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002820 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002821 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002822 if (status != Dumpstate::RunStatus::OK &&
2823 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2824 // Do an early return if there were errors. We make an exception for consent
2825 // timing out because it's possible the user got distracted. In this case the
2826 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002827 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002828 return status;
2829 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002830 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2831 MYLOGI(
2832 "Did not receive user consent yet."
2833 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002834 const String16 incidentcompanion("incidentcompanion");
2835 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2836 if (ics != nullptr) {
2837 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2838 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2839 consent_callback_.get());
2840 } else {
2841 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2842 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002843 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002844 }
2845
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002846 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002847 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002848 for (int i = 0; i < 3; i++) {
2849 Vibrate(75);
2850 usleep((75 + 50) * 1000);
2851 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002852 }
2853
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2855 progress_->GetInitialMax());
2856 progress_->Save();
2857 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002858
Felipe Leme107a05f2016-03-08 15:11:15 -08002859 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002860 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002861 }
2862
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002863 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002864 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002865 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002866 }
2867
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002868 tombstone_data_.clear();
2869 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002870
Nandana Duttd2f5f082019-01-18 17:13:52 +00002871 return (consent_callback_ != nullptr &&
2872 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2873 ? USER_CONSENT_TIMED_OUT
2874 : RunStatus::OK;
2875}
2876
Paul Chang0d2aad72020-02-13 20:04:03 +08002877void Dumpstate::MaybeTakeEarlyScreenshot() {
2878 if (!options_->do_screenshot || !do_early_screenshot_) {
2879 return;
2880 }
2881
2882 TakeScreenshot();
2883}
2884
Paul Changc490e662020-04-11 18:14:09 +08002885void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
2886 const std::string& calling_package) {
2887 if (calling_uid == AID_SHELL || !CalledByApi()) {
2888 return;
2889 }
2890 if (listener_ != nullptr) {
2891 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2892 // handling if required.
2893 android::String16 package(calling_package.c_str());
2894 listener_->onUiIntensiveBugreportDumpsFinished(package);
2895 }
2896}
2897
Jichao Lie89d9c12019-11-21 19:02:51 -08002898void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2899 if (calling_uid == AID_SHELL || !CalledByApi()) {
2900 // No need to get consent for shell triggered dumpstates, or not through
2901 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002902 return;
2903 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002904 consent_callback_ = new ConsentCallback();
2905 const String16 incidentcompanion("incidentcompanion");
2906 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002907 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002908 if (ics != nullptr) {
2909 MYLOGD("Checking user consent via incidentcompanion service\n");
2910 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002911 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002912 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002913 } else {
2914 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2915 }
2916}
2917
Nandana Dutt5c390032019-03-12 10:52:56 +00002918bool Dumpstate::IsUserConsentDenied() const {
2919 return ds.consent_callback_ != nullptr &&
2920 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2921}
2922
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002923bool Dumpstate::CalledByApi() const {
2924 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2925}
2926
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002927void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002928 android::os::UnlinkAndLogOnError(tmp_path_);
2929 android::os::UnlinkAndLogOnError(screenshot_path_);
2930 android::os::UnlinkAndLogOnError(path_);
2931}
2932
Rhed Jao1c855122020-07-16 17:37:39 +08002933void Dumpstate::EnableParallelRunIfNeeded() {
2934 // The thread pool needs to create temporary files to receive dump results.
2935 // That's why we only enable it when the bugreport client chooses to output
2936 // to a file.
2937 if (!PropertiesHelper::IsParallelRun() || !options_->OutputToFile()) {
2938 return;
2939 }
2940 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
2941}
2942
2943void Dumpstate::ShutdownDumpPool() {
2944 if (dump_pool_) {
2945 dump_pool_->shutdown();
2946 dump_pool_ = nullptr;
2947 }
2948}
2949
Nandana Duttd2f5f082019-01-18 17:13:52 +00002950Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2951 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002952 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00002953 return USER_CONSENT_DENIED;
2954}
2955
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002956Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002957 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002958 // user consent (unless the caller is Shell).
2959 UserConsentResult consent_result;
2960 if (calling_uid == AID_SHELL) {
2961 consent_result = UserConsentResult::APPROVED;
2962 } else {
2963 consent_result = consent_callback_->getResult();
2964 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002965 if (consent_result == UserConsentResult::UNAVAILABLE) {
2966 // User has not responded yet.
2967 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08002968 // Telephony is a fast report type, particularly on user builds where information may be
2969 // more aggressively limited. To give the user time to read the consent dialog, increase the
2970 // timeout.
2971 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
2972 : USER_CONSENT_TIMEOUT_MS;
2973 if (elapsed_ms < timeout_ms) {
2974 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00002975 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2976 sleep(delay_seconds);
2977 }
2978 consent_result = consent_callback_->getResult();
2979 }
2980 if (consent_result == UserConsentResult::DENIED) {
2981 // User has explicitly denied sharing with the app. To be safe delete the
2982 // internal bugreport & tmp files.
2983 return HandleUserConsentDenied();
2984 }
2985 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002986 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2987 if (copy_succeeded) {
2988 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01002989 if (options_->do_screenshot &&
2990 options_->screenshot_fd.get() != -1 &&
2991 !options_->is_screenshot_copied) {
2992 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2993 options_->screenshot_fd.get());
2994 options_->is_screenshot_copied = copy_succeeded;
2995 if (copy_succeeded) {
2996 android::os::UnlinkAndLogOnError(screenshot_path_);
2997 }
2998 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002999 }
3000 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
3001 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3002 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3003 // Since we do not have user consent to share the bugreport it does not get
3004 // copied over to the calling app but remains in the internal directory from
3005 // where the user can manually pull it.
3006 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3007 }
3008 // Unknown result; must be a programming error.
3009 MYLOGE("Unknown user consent result:%d\n", consent_result);
3010 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003011}
3012
Nandana Duttf02564e2019-02-15 15:24:24 +00003013Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003014 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3015 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3016 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003017 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003018 // When directly running dumpstate binary, the output is not expected to be written
3019 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003020 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003021
3022 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003023 // an app; they are irrelevant here because bugreport is triggered via command line.
3024 // Update Last ID before calling Run().
3025 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003026 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003027 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003028 return status;
3029}
3030
3031/* Main entry point for dumpstate binary. */
3032int run_main(int argc, char* argv[]) {
3033 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003034
3035 switch (status) {
3036 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003037 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003038 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003039 ShowUsage();
3040 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003041 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003042 fprintf(stderr, "Invalid combination of args\n");
3043 ShowUsage();
3044 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003045 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003046 FALLTHROUGH_INTENDED;
3047 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3048 FALLTHROUGH_INTENDED;
3049 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003050 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003051 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003052}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003053
3054// TODO(111441001): Default DumpOptions to sensible values.
3055Dumpstate::Dumpstate(const std::string& version)
3056 : pid_(getpid()),
3057 options_(new Dumpstate::DumpOptions()),
Nandana Duttf02cd782019-06-14 14:25:13 +01003058 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003059 version_(version),
3060 now_(time(nullptr)) {
3061}
3062
3063Dumpstate& Dumpstate::GetInstance() {
3064 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3065 return singleton_;
3066}
3067
Rhed Jao1c855122020-07-16 17:37:39 +08003068DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3069 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3070 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003071 if (!title_.empty()) {
3072 started_ = Nanotime();
3073 }
3074}
3075
3076DurationReporter::~DurationReporter() {
3077 if (!title_.empty()) {
3078 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003079 if (elapsed >= .5f || verbose_) {
3080 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003081 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003082 if (!logcat_only_) {
3083 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao1c855122020-07-16 17:37:39 +08003084 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3085 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003086 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003087 }
3088}
3089
3090const int32_t Progress::kDefaultMax = 5000;
3091
3092Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3093}
3094
3095Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3096 : Progress(initial_max, growth_factor, "") {
3097 progress_ = progress;
3098}
3099
3100Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3101 : initial_max_(initial_max),
3102 progress_(0),
3103 max_(initial_max),
3104 growth_factor_(growth_factor),
3105 n_runs_(0),
3106 average_max_(0),
3107 path_(path) {
3108 if (!path_.empty()) {
3109 Load();
3110 }
3111}
3112
3113void Progress::Load() {
3114 MYLOGD("Loading stats from %s\n", path_.c_str());
3115 std::string content;
3116 if (!android::base::ReadFileToString(path_, &content)) {
3117 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3118 return;
3119 }
3120 if (content.empty()) {
3121 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3122 return;
3123 }
3124 std::vector<std::string> lines = android::base::Split(content, "\n");
3125
3126 if (lines.size() < 1) {
3127 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3128 (int)lines.size(), max_);
3129 return;
3130 }
3131 char* ptr;
3132 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3133 average_max_ = strtol(ptr, nullptr, 10);
3134 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3135 average_max_ > STATS_MAX_AVERAGE) {
3136 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3137 initial_max_ = Progress::kDefaultMax;
3138 } else {
3139 initial_max_ = average_max_;
3140 }
3141 max_ = initial_max_;
3142
3143 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3144}
3145
3146void Progress::Save() {
3147 int32_t total = n_runs_ * average_max_ + progress_;
3148 int32_t runs = n_runs_ + 1;
3149 int32_t average = floor(((float)total) / runs);
3150 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3151 path_.c_str());
3152 if (path_.empty()) {
3153 return;
3154 }
3155
3156 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3157 if (!android::base::WriteStringToFile(content, path_)) {
3158 MYLOGE("Could not save stats on %s\n", path_.c_str());
3159 }
3160}
3161
3162int32_t Progress::Get() const {
3163 return progress_;
3164}
3165
3166bool Progress::Inc(int32_t delta_sec) {
3167 bool changed = false;
3168 if (delta_sec >= 0) {
3169 progress_ += delta_sec;
3170 if (progress_ > max_) {
3171 int32_t old_max = max_;
3172 max_ = floor((float)progress_ * growth_factor_);
3173 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3174 changed = true;
3175 }
3176 }
3177 return changed;
3178}
3179
3180int32_t Progress::GetMax() const {
3181 return max_;
3182}
3183
3184int32_t Progress::GetInitialMax() const {
3185 return initial_max_;
3186}
3187
3188void Progress::Dump(int fd, const std::string& prefix) const {
3189 const char* pr = prefix.c_str();
3190 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3191 dprintf(fd, "%smax: %d\n", pr, max_);
3192 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3193 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3194 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3195 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3196 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3197}
3198
3199bool Dumpstate::IsZipping() const {
3200 return zip_writer_ != nullptr;
3201}
3202
3203std::string Dumpstate::GetPath(const std::string& suffix) const {
3204 return GetPath(bugreport_internal_dir_, suffix);
3205}
3206
3207std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3208 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3209 name_.c_str(), suffix.c_str());
3210}
3211
3212void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3213 progress_ = std::move(progress);
3214}
3215
3216void for_each_userid(void (*func)(int), const char *header) {
3217 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3218 "for_each_userid(%s)", header);
3219 DurationReporter duration_reporter(title);
3220 if (PropertiesHelper::IsDryRun()) return;
3221
3222 DIR *d;
3223 struct dirent *de;
3224
3225 if (header) printf("\n------ %s ------\n", header);
3226 func(0);
3227
3228 if (!(d = opendir("/data/system/users"))) {
3229 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3230 return;
3231 }
3232
3233 while ((de = readdir(d))) {
3234 int userid;
3235 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3236 continue;
3237 }
3238 func(userid);
3239 }
3240
3241 closedir(d);
3242}
3243
3244static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3245 DIR *d;
3246 struct dirent *de;
3247
3248 if (!(d = opendir("/proc"))) {
3249 printf("Failed to open /proc (%s)\n", strerror(errno));
3250 return;
3251 }
3252
3253 if (header) printf("\n------ %s ------\n", header);
3254 while ((de = readdir(d))) {
3255 if (ds.IsUserConsentDenied()) {
3256 MYLOGE(
3257 "Returning early because user denied consent to share bugreport with calling app.");
3258 closedir(d);
3259 return;
3260 }
3261 int pid;
3262 int fd;
3263 char cmdpath[255];
3264 char cmdline[255];
3265
3266 if (!(pid = atoi(de->d_name))) {
3267 continue;
3268 }
3269
3270 memset(cmdline, 0, sizeof(cmdline));
3271
3272 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3273 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3274 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3275 close(fd);
3276 if (cmdline[0]) {
3277 helper(pid, cmdline, arg);
3278 continue;
3279 }
3280 }
3281
3282 // if no cmdline, a kernel thread has comm
3283 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3284 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3285 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3286 close(fd);
3287 if (cmdline[1]) {
3288 cmdline[0] = '[';
3289 size_t len = strcspn(cmdline, "\f\b\r\n");
3290 cmdline[len] = ']';
3291 cmdline[len+1] = '\0';
3292 }
3293 }
3294 if (!cmdline[0]) {
3295 strcpy(cmdline, "N/A");
3296 }
3297 helper(pid, cmdline, arg);
3298 }
3299
3300 closedir(d);
3301}
3302
3303static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3304 for_each_pid_func *func = (for_each_pid_func*) arg;
3305 func(pid, cmdline);
3306}
3307
3308void for_each_pid(for_each_pid_func func, const char *header) {
3309 std::string title = header == nullptr ? "for_each_pid"
3310 : android::base::StringPrintf("for_each_pid(%s)", header);
3311 DurationReporter duration_reporter(title);
3312 if (PropertiesHelper::IsDryRun()) return;
3313
3314 __for_each_pid(for_each_pid_helper, header, (void *) func);
3315}
3316
3317static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3318 DIR *d;
3319 struct dirent *de;
3320 char taskpath[255];
3321 for_each_tid_func *func = (for_each_tid_func *) arg;
3322
3323 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3324
3325 if (!(d = opendir(taskpath))) {
3326 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3327 return;
3328 }
3329
3330 func(pid, pid, cmdline);
3331
3332 while ((de = readdir(d))) {
3333 if (ds.IsUserConsentDenied()) {
3334 MYLOGE(
3335 "Returning early because user denied consent to share bugreport with calling app.");
3336 closedir(d);
3337 return;
3338 }
3339 int tid;
3340 int fd;
3341 char commpath[255];
3342 char comm[255];
3343
3344 if (!(tid = atoi(de->d_name))) {
3345 continue;
3346 }
3347
3348 if (tid == pid)
3349 continue;
3350
3351 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3352 memset(comm, 0, sizeof(comm));
3353 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3354 strcpy(comm, "N/A");
3355 } else {
3356 char *c;
3357 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3358 close(fd);
3359
3360 c = strrchr(comm, '\n');
3361 if (c) {
3362 *c = '\0';
3363 }
3364 }
3365 func(pid, tid, comm);
3366 }
3367
3368 closedir(d);
3369}
3370
3371void for_each_tid(for_each_tid_func func, const char *header) {
3372 std::string title = header == nullptr ? "for_each_tid"
3373 : android::base::StringPrintf("for_each_tid(%s)", header);
3374 DurationReporter duration_reporter(title);
3375
3376 if (PropertiesHelper::IsDryRun()) return;
3377
3378 __for_each_pid(for_each_tid_helper, header, (void *) func);
3379}
3380
3381void show_wchan(int pid, int tid, const char *name) {
3382 if (PropertiesHelper::IsDryRun()) return;
3383
3384 char path[255];
3385 char buffer[255];
3386 int fd, ret, save_errno;
3387 char name_buffer[255];
3388
3389 memset(buffer, 0, sizeof(buffer));
3390
3391 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3392 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3393 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3394 return;
3395 }
3396
3397 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3398 save_errno = errno;
3399 close(fd);
3400
3401 if (ret < 0) {
3402 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3403 return;
3404 }
3405
3406 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3407 pid == tid ? 0 : 3, "", name);
3408
3409 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3410
3411 return;
3412}
3413
3414// print time in centiseconds
3415static void snprcent(char *buffer, size_t len, size_t spc,
3416 unsigned long long time) {
3417 static long hz; // cache discovered hz
3418
3419 if (hz <= 0) {
3420 hz = sysconf(_SC_CLK_TCK);
3421 if (hz <= 0) {
3422 hz = 1000;
3423 }
3424 }
3425
3426 // convert to centiseconds
3427 time = (time * 100 + (hz / 2)) / hz;
3428
3429 char str[16];
3430
3431 snprintf(str, sizeof(str), " %llu.%02u",
3432 time / 100, (unsigned)(time % 100));
3433 size_t offset = strlen(buffer);
3434 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3435 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3436}
3437
3438// print permille as a percent
3439static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3440 char str[16];
3441
3442 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3443 size_t offset = strlen(buffer);
3444 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3445 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3446}
3447
3448void show_showtime(int pid, const char *name) {
3449 if (PropertiesHelper::IsDryRun()) return;
3450
3451 char path[255];
3452 char buffer[1023];
3453 int fd, ret, save_errno;
3454
3455 memset(buffer, 0, sizeof(buffer));
3456
3457 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3458 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3459 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3460 return;
3461 }
3462
3463 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3464 save_errno = errno;
3465 close(fd);
3466
3467 if (ret < 0) {
3468 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3469 return;
3470 }
3471
3472 // field 14 is utime
3473 // field 15 is stime
3474 // field 42 is iotime
3475 unsigned long long utime = 0, stime = 0, iotime = 0;
3476 if (sscanf(buffer,
3477 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3478 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3479 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3480 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3481 &utime, &stime, &iotime) != 3) {
3482 return;
3483 }
3484
3485 unsigned long long total = utime + stime;
3486 if (!total) {
3487 return;
3488 }
3489
3490 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3491 if (permille > 1000) {
3492 permille = 1000;
3493 }
3494
3495 // try to beautify and stabilize columns at <80 characters
3496 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3497 if ((name[0] != '[') || utime) {
3498 snprcent(buffer, sizeof(buffer), 57, utime);
3499 }
3500 snprcent(buffer, sizeof(buffer), 65, stime);
3501 if ((name[0] != '[') || iotime) {
3502 snprcent(buffer, sizeof(buffer), 73, iotime);
3503 }
3504 if (iotime) {
3505 snprdec(buffer, sizeof(buffer), 79, permille);
3506 }
3507 puts(buffer); // adds a trailing newline
3508
3509 return;
3510}
3511
3512void do_dmesg() {
3513 const char *title = "KERNEL LOG (dmesg)";
3514 DurationReporter duration_reporter(title);
3515 printf("------ %s ------\n", title);
3516
3517 if (PropertiesHelper::IsDryRun()) return;
3518
3519 /* Get size of kernel buffer */
3520 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3521 if (size <= 0) {
3522 printf("Unexpected klogctl return value: %d\n\n", size);
3523 return;
3524 }
3525 char *buf = (char *) malloc(size + 1);
3526 if (buf == nullptr) {
3527 printf("memory allocation failed\n\n");
3528 return;
3529 }
3530 int retval = klogctl(KLOG_READ_ALL, buf, size);
3531 if (retval < 0) {
3532 printf("klogctl failure\n\n");
3533 free(buf);
3534 return;
3535 }
3536 buf[retval] = '\0';
3537 printf("%s\n\n", buf);
3538 free(buf);
3539 return;
3540}
3541
3542void do_showmap(int pid, const char *name) {
3543 char title[255];
3544 char arg[255];
3545
3546 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3547 snprintf(arg, sizeof(arg), "%d", pid);
3548 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3549}
3550
3551int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3552 DurationReporter duration_reporter(title);
3553
3554 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3555
3556 UpdateProgress(WEIGHT_FILE);
3557
3558 return status;
3559}
3560
3561int read_file_as_long(const char *path, long int *output) {
3562 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3563 if (fd < 0) {
3564 int err = errno;
3565 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3566 return -1;
3567 }
3568 char buffer[50];
3569 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3570 if (bytes_read == -1) {
3571 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3572 return -2;
3573 }
3574 if (bytes_read == 0) {
3575 MYLOGE("File %s is empty\n", path);
3576 return -3;
3577 }
3578 *output = atoi(buffer);
3579 return 0;
3580}
3581
3582/* calls skip to gate calling dump_from_fd recursively
3583 * in the specified directory. dump_from_fd defaults to
3584 * dump_file_from_fd above when set to NULL. skip defaults
3585 * to false when set to NULL. dump_from_fd will always be
3586 * called with title NULL.
3587 */
3588int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3589 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3590 DurationReporter duration_reporter(title);
3591 DIR *dirp;
3592 struct dirent *d;
3593 char *newpath = nullptr;
3594 const char *slash = "/";
3595 int retval = 0;
3596
3597 if (!title.empty()) {
3598 printf("------ %s (%s) ------\n", title.c_str(), dir);
3599 }
3600 if (PropertiesHelper::IsDryRun()) return 0;
3601
3602 if (dir[strlen(dir) - 1] == '/') {
3603 ++slash;
3604 }
3605 dirp = opendir(dir);
3606 if (dirp == nullptr) {
3607 retval = -errno;
3608 MYLOGE("%s: %s\n", dir, strerror(errno));
3609 return retval;
3610 }
3611
3612 if (!dump_from_fd) {
3613 dump_from_fd = dump_file_from_fd;
3614 }
3615 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3616 if ((d->d_name[0] == '.')
3617 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3618 || (d->d_name[1] == '\0'))) {
3619 continue;
3620 }
3621 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3622 (d->d_type == DT_DIR) ? "/" : "");
3623 if (!newpath) {
3624 retval = -errno;
3625 continue;
3626 }
3627 if (skip && (*skip)(newpath)) {
3628 continue;
3629 }
3630 if (d->d_type == DT_DIR) {
3631 int ret = dump_files("", newpath, skip, dump_from_fd);
3632 if (ret < 0) {
3633 retval = ret;
3634 }
3635 continue;
3636 }
3637 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3638 if (fd.get() < 0) {
3639 retval = -1;
3640 printf("*** %s: %s\n", newpath, strerror(errno));
3641 continue;
3642 }
3643 (*dump_from_fd)(nullptr, newpath, fd.get());
3644 }
3645 closedir(dirp);
3646 if (!title.empty()) {
3647 printf("\n");
3648 }
3649 return retval;
3650}
3651
3652/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3653 * it's possible to avoid issues where opening the file itself can get
3654 * stuck.
3655 */
3656int dump_file_from_fd(const char *title, const char *path, int fd) {
3657 if (PropertiesHelper::IsDryRun()) return 0;
3658
3659 int flags = fcntl(fd, F_GETFL);
3660 if (flags == -1) {
3661 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3662 return -1;
3663 } else if (!(flags & O_NONBLOCK)) {
3664 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3665 return -1;
3666 }
3667 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3668}
3669
3670int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +01003671 const CommandOptions& options, bool verbose_duration) {
3672 DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003673
3674 int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
3675
3676 /* TODO: for now we're simplifying the progress calculation by using the
3677 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3678 * where its weight should be much higher proportionally to its timeout.
3679 * Ideally, it should use a options.EstimatedDuration() instead...*/
3680 UpdateProgress(options.Timeout());
3681
3682 return status;
3683}
3684
3685void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3686 const CommandOptions& options, long dumpsysTimeoutMs) {
3687 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3688 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3689 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3690 RunCommand(title, dumpsys, options);
3691}
3692
3693int open_socket(const char *service) {
3694 int s = android_get_control_socket(service);
3695 if (s < 0) {
3696 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3697 return -1;
3698 }
3699 fcntl(s, F_SETFD, FD_CLOEXEC);
3700
3701 // Set backlog to 0 to make sure that queue size will be minimum.
3702 // In Linux, because the minimum queue will be 1, connect() will be blocked
3703 // if the other clients already called connect() and the connection request was not accepted.
3704 if (listen(s, 0) < 0) {
3705 MYLOGE("listen(control socket): %s\n", strerror(errno));
3706 return -1;
3707 }
3708
3709 struct sockaddr addr;
3710 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003711 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003712
3713 // Close socket just after accept(), to make sure that connect() by client will get error
3714 // when the socket is used by the other services.
3715 // There is still a race condition possibility between accept and close, but there is no way
3716 // to close-on-accept atomically.
3717 // See detail; b/123306389#comment25
3718 close(s);
3719
3720 if (fd < 0) {
3721 MYLOGE("accept(control socket): %s\n", strerror(errno));
3722 return -1;
3723 }
3724
3725 return fd;
3726}
3727
3728/* redirect output to a service control socket */
3729bool redirect_to_socket(FILE* redirect, const char* service) {
3730 int fd = open_socket(service);
3731 if (fd == -1) {
3732 return false;
3733 }
3734 fflush(redirect);
3735 // TODO: handle dup2 failure
3736 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3737 close(fd);
3738 return true;
3739}
3740
3741// TODO: should call is_valid_output_file and/or be merged into it.
3742void create_parent_dirs(const char *path) {
3743 char *chp = const_cast<char *> (path);
3744
3745 /* skip initial slash */
3746 if (chp[0] == '/')
3747 chp++;
3748
3749 /* create leading directories, if necessary */
3750 struct stat dir_stat;
3751 while (chp && chp[0]) {
3752 chp = strchr(chp, '/');
3753 if (chp) {
3754 *chp = 0;
3755 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3756 MYLOGI("Creating directory %s\n", path);
3757 if (mkdir(path, 0770)) { /* drwxrwx--- */
3758 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3759 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3760 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3761 }
3762 }
3763 *chp++ = '/';
3764 }
3765 }
3766}
3767
3768bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3769 create_parent_dirs(path);
3770
3771 int fd = TEMP_FAILURE_RETRY(open(path,
3772 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3773 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3774 if (fd < 0) {
3775 MYLOGE("%s: %s\n", path, strerror(errno));
3776 return false;
3777 }
3778
3779 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3780 close(fd);
3781 return true;
3782}
3783
3784bool redirect_to_file(FILE* redirect, char* path) {
3785 return _redirect_to_file(redirect, path, O_TRUNC);
3786}
3787
3788bool redirect_to_existing_file(FILE* redirect, char* path) {
3789 return _redirect_to_file(redirect, path, O_APPEND);
3790}
3791
3792void dump_route_tables() {
3793 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3794 if (PropertiesHelper::IsDryRun()) return;
3795 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3796 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3797 FILE* fp = fopen(RT_TABLES_PATH, "re");
3798 if (!fp) {
3799 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3800 return;
3801 }
3802 char table[16];
3803 // Each line has an integer (the table number), a space, and a string (the table name). We only
3804 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3805 // Add a fixed max limit so this doesn't go awry.
3806 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3807 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3808 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3809 }
3810 fclose(fp);
3811}
3812
3813// TODO: make this function thread safe if sections are generated in parallel.
3814void Dumpstate::UpdateProgress(int32_t delta_sec) {
3815 if (progress_ == nullptr) {
3816 MYLOGE("UpdateProgress: progress_ not set\n");
3817 return;
3818 }
3819
3820 // Always update progess so stats can be tuned...
Nandana Duttf02cd782019-06-14 14:25:13 +01003821 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003822
3823 // ...but only notifiy listeners when necessary.
3824 if (!options_->do_progress_updates) return;
3825
3826 int progress = progress_->Get();
3827 int max = progress_->GetMax();
Nandana Duttf02cd782019-06-14 14:25:13 +01003828 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003829
Nandana Duttf02cd782019-06-14 14:25:13 +01003830 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003831 return;
3832 }
Nandana Duttf02cd782019-06-14 14:25:13 +01003833 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003834
3835 if (control_socket_fd_ >= 0) {
3836 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3837 fsync(control_socket_fd_);
3838 }
3839
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003840 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003841 if (percent % 10 == 0) {
3842 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003843 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003844 } else {
3845 // stderr is ignored on normal invocations, but useful when calling
3846 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003847 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003848 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003849
3850 listener_->onProgress(percent);
3851 }
3852}
3853
3854void Dumpstate::TakeScreenshot(const std::string& path) {
3855 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3856 int status =
3857 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3858 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3859 if (status == 0) {
3860 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3861 } else {
3862 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3863 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003864 if (listener_ != nullptr) {
3865 // Show a visual indication to indicate screenshot is taken via
3866 // IDumpstateListener.onScreenshotTaken()
3867 listener_->onScreenshotTaken(status == 0);
3868 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003869}
3870
3871bool is_dir(const char* pathname) {
3872 struct stat info;
3873 if (stat(pathname, &info) == -1) {
3874 return false;
3875 }
3876 return S_ISDIR(info.st_mode);
3877}
3878
3879time_t get_mtime(int fd, time_t default_mtime) {
3880 struct stat info;
3881 if (fstat(fd, &info) == -1) {
3882 return default_mtime;
3883 }
3884 return info.st_mtime;
3885}