blob: 7d195b4fa1329de60bc04ce20f08d9721f72725c [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010022#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070024#include <limits.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010025#include <math.h>
26#include <poll.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070027#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070028#include <stdio.h>
29#include <stdlib.h>
30#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080031#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070032#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070033#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/time.h>
36#include <sys/wait.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010037#include <signal.h>
38#include <stdarg.h>
39#include <string.h>
40#include <sys/capability.h>
41#include <sys/inotify.h>
42#include <sys/klog.h>
43#include <time.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070045
46#include <chrono>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070047#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000048#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070049#include <functional>
50#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010051#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070052#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010053#include <regex>
54#include <set>
55#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070056#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010057#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070058
Felipe Leme96c2bbb2016-09-26 09:21:21 -070059#include <android-base/file.h>
60#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070061#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080062#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070063#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070064#include <android-base/unique_fd.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010065#include <android/content/pm/IPackageManagerNative.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080066#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080067#include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
68#include <android/hardware/dumpstate/1.1/types.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080069#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000070#include <android/os/IIncidentCompanion.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010071#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080072#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070073#include <cutils/properties.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010074#include <cutils/sockets.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000075#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080076#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000077#include <dumputils/dump_utils.h>
Sahana Raof35ed432019-07-12 10:47:52 +010078#include <hardware_legacy/power.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080079#include <hidl/ServiceManagement.h>
Abhijeet Kaurcf234e82019-07-01 14:53:55 +010080#include <log/log.h>
Tom Cherryf4472f32020-08-05 09:31:17 -070081#include <log/log_read.h>
Felipe Leme75876a22016-10-27 16:31:27 -070082#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070083#include <private/android_filesystem_config.h>
84#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080085#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070086#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080087#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070088#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070089#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080090
Hunter Knepshield8540faf2020-02-04 19:47:20 -080091using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
92using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
93using ::android::hardware::dumpstate::V1_1::DumpstateMode;
94using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
95using ::android::hardware::dumpstate::V1_1::toString;
Vishnu Naire97d6122018-01-18 13:58:56 -080096using ::std::literals::chrono_literals::operator""ms;
97using ::std::literals::chrono_literals::operator""s;
Rhed Jao5377d792020-07-16 17:37:39 +080098using ::std::placeholders::_1;
Steven Morelandcb7ef822016-11-29 13:20:37 -080099
Felipe Leme47e9be22016-12-21 15:37:07 -0800100// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -0800101using android::defaultServiceManager;
102using android::Dumpsys;
103using android::INVALID_OPERATION;
104using android::IServiceManager;
105using android::OK;
106using android::sp;
107using android::status_t;
108using android::String16;
109using android::String8;
110using android::TIMED_OUT;
111using android::UNKNOWN_ERROR;
112using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000113using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000114using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800115using android::os::dumpstate::CommandOptions;
116using android::os::dumpstate::DumpFileToFd;
Rhed Jao5377d792020-07-16 17:37:39 +0800117using android::os::dumpstate::DumpPool;
Vishnu Naire97d6122018-01-18 13:58:56 -0800118using android::os::dumpstate::PropertiesHelper;
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 Juravlef84d3692020-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 Jao5377d792020-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 Jao5377d792020-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 Jao5377d792020-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"},
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001332 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1333 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);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001531
Paul Chang0d2aad72020-02-13 20:04:03 +08001532 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001533 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001534 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001535 }
1536
Felipe Lemee184f662016-10-27 10:04:47 -07001537 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001538
Narayan Kamath8f788292017-05-25 13:20:39 +01001539 // NOTE: tombstones are always added as separate entries in the zip archive
1540 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001541 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001542 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001543 if (!tombstones_dumped) {
1544 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001545 }
1546
Jayachandran Ca94c7172017-06-10 15:08:12 -07001547 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001548
Chenbo Feng276a3b62018-08-07 11:44:49 -07001549 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1550
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001551 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001552
Jayachandran Ca94c7172017-06-10 15:08:12 -07001553 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001554
1555 dump_route_tables();
1556
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001557 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1558 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1559 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001560
Nandana Dutt5c390032019-03-12 10:52:56 +00001561 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001562
Elliott Hughes23ccc622017-02-28 10:14:22 -08001563 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001564
Jin Qianf334d662017-10-10 14:41:37 -07001565 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001566
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001567 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001568
Colin Crossf45fa6b2012-03-26 12:38:26 -07001569 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001570 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1571 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1572
1573 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1574 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1575 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1576 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1577 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001578
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001579 /* Add window and surface trace files. */
1580 if (!PropertiesHelper::IsUserBuild()) {
1581 ds.AddDir(WMTRACE_DATA_DIR, false);
1582 }
1583
Yifan Hongd90cc652020-02-08 16:52:02 -08001584 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1585
Nandana Dutt5c390032019-03-12 10:52:56 +00001586 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001587
Steven Moreland7440ddb2016-12-15 16:13:39 -08001588 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001589 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1590 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001591 // su does not exist on user builds, so try running without it.
1592 // This way any implementations of vril-dump that do not require
1593 // root can run on user builds.
1594 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001595 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001596 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001597 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001598 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001599 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001600 }
1601
Felipe Lemed8b94e52016-12-08 10:21:44 -08001602 printf("========================================================\n");
1603 printf("== Android Framework Services\n");
1604 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001605
Nandana Dutt5c390032019-03-12 10:52:56 +00001606 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001607
Felipe Lemed8b94e52016-12-08 10:21:44 -08001608 printf("========================================================\n");
1609 printf("== Checkins\n");
1610 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001611
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001612 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001613
1614 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1615
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001616 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1617 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1618 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1619 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001620
Felipe Lemed8b94e52016-12-08 10:21:44 -08001621 printf("========================================================\n");
1622 printf("== Running Application Activities\n");
1623 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001624
Makoto Onuki60780982018-04-16 15:34:00 -07001625 // The following dumpsys internally collects output from running apps, so it can take a long
1626 // time. So let's extend the timeout.
1627
1628 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1629
1630 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001631
Felipe Lemed8b94e52016-12-08 10:21:44 -08001632 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001633 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001634 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001635
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001636 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001637 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001638
Felipe Lemed8b94e52016-12-08 10:21:44 -08001639 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001640 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001641 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001642
Makoto Onuki60780982018-04-16 15:34:00 -07001643 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1644 DUMPSYS_COMPONENTS_OPTIONS);
1645
1646 printf("========================================================\n");
1647 printf("== Running Application Providers (platform)\n");
1648 printf("========================================================\n");
1649
1650 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1651 DUMPSYS_COMPONENTS_OPTIONS);
1652
1653 printf("========================================================\n");
1654 printf("== Running Application Providers (non-platform)\n");
1655 printf("========================================================\n");
1656
1657 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1658 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001659
Adrian Roos8b397ab2017-04-04 16:35:44 -07001660 printf("========================================================\n");
1661 printf("== Dropbox crashes\n");
1662 printf("========================================================\n");
1663
1664 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1665 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1666
Felipe Lemed8b94e52016-12-08 10:21:44 -08001667 printf("========================================================\n");
1668 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1669 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1670 printf("========================================================\n");
1671 printf("== dumpstate: done (id %d)\n", ds.id_);
1672 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001673
1674 printf("========================================================\n");
1675 printf("== Obtaining statsd metadata\n");
1676 printf("========================================================\n");
1677 // This differs from the usual dumpsys stats, which is the stats report data.
1678 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001679
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001680 // Add linker configuration directory
1681 ds.AddDir(LINKERCONFIG_DIR, true);
1682
Mike Ma5c267872019-08-21 11:31:34 -07001683 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
1684
Nandana Dutt5c390032019-03-12 10:52:56 +00001685 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001686}
1687
Nandana Dutt5c390032019-03-12 10:52:56 +00001688/*
1689 * Dumps state for the default case; drops root after it's no longer necessary.
1690 *
1691 * Returns RunStatus::OK if everything went fine.
1692 * Returns RunStatus::ERROR if there was an error.
1693 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1694 * with the caller.
1695 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001696Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001697 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1698 // buffer.
1699 DoLogcat();
1700 // Capture timestamp after first logcat to use in next logcat
1701 time_t logcat_ts = time(nullptr);
1702
Nandana Dutt4be45d12018-09-26 15:04:23 +01001703 /* collect stack traces from Dalvik and native processes (needs root) */
Rhed Jao5377d792020-07-16 17:37:39 +08001704 if (dump_pool_) {
1705 RETURN_IF_USER_DENIED_CONSENT();
1706 // One thread is enough since we only need to enqueue DumpTraces here.
1707 dump_pool_->start(/* thread_counts = */1);
1708
1709 // DumpTraces takes long time, post it to the another thread in the
1710 // pool, if pool is available
1711 dump_pool_->enqueueTask(DUMP_TRACES_TASK, &Dumpstate::DumpTraces, &ds, &dump_traces_path);
1712 } else {
1713 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK_AND_LOG(DUMP_TRACES_TASK, ds.DumpTraces,
1714 &dump_traces_path);
1715 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001716
1717 /* Run some operations that require root. */
1718 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1719 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1720
1721 ds.AddDir(RECOVERY_DIR, true);
1722 ds.AddDir(RECOVERY_DATA_DIR, true);
1723 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1724 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1725 if (!PropertiesHelper::IsUserBuild()) {
1726 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1727 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001728 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001729 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001730 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001731 add_mountinfo();
1732 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001733 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001734 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001735
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001736 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001737 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1738
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001739 // Dump IPsec stats. No keys are exposed here.
1740 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1741
Nandana Dutt4be45d12018-09-26 15:04:23 +01001742 // Run ss as root so we can see socket marks.
1743 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1744
1745 // Run iotop as root to show top 100 IO threads
1746 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1747
Erick Reyese68df822019-02-11 14:46:36 -08001748 // Gather shared memory buffer info if the product implements it
1749 struct stat st;
1750 if (!stat("/product/bin/dmabuf_dump", &st)) {
1751 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1752 }
1753
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001754 DumpFile("PSI cpu", "/proc/pressure/cpu");
1755 DumpFile("PSI memory", "/proc/pressure/memory");
1756 DumpFile("PSI io", "/proc/pressure/io");
1757
Rhed Jao5377d792020-07-16 17:37:39 +08001758 if (dump_pool_) {
1759 RETURN_IF_USER_DENIED_CONSENT();
1760 dump_pool_->waitForTask(DUMP_TRACES_TASK);
1761
1762 // Current running thread in the pool is the root user also. Shutdown
1763 // the pool and restart later to ensure all threads in the pool could
1764 // drop the root user.
1765 dump_pool_->shutdown();
1766 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01001767 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001768 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001769 }
1770
Nandana Dutt5c390032019-03-12 10:52:56 +00001771 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001772 Dumpstate::RunStatus status = dumpstate();
1773 // Capture logcat since the last time we did it.
1774 DoSystemLogcat(logcat_ts);
1775 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001776}
1777
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001778// This method collects common dumpsys for telephony and wifi. Typically, wifi
1779// reports are fine to include all information, but telephony reports on user
1780// builds need to strip some content (see DumpstateTelephonyOnly).
1781static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001782 DumpIpTablesAsRoot();
1783
Jayachandran Cb4389d92019-07-08 09:46:05 -07001784 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1785
Jayachandran Ca94c7172017-06-10 15:08:12 -07001786 if (!DropRootUser()) {
1787 return;
1788 }
1789
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001790 // We need to be picky about some stuff for telephony reports on user builds.
1791 if (!include_sensitive_info) {
1792 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1793 DoRadioLogcat();
1794 } else {
1795 // Contains various system properties and process startup info.
1796 do_dmesg();
1797 // Logs other than the radio buffer may contain package/component names and potential PII.
1798 DoLogcat();
1799 // Too broad for connectivity problems.
1800 DoKmsg();
1801 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
1802 DumpHals();
1803 }
1804
Jayachandran Ca94c7172017-06-10 15:08:12 -07001805 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001806 DumpIpAddrAndRules();
1807 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001808 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1809 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001810}
1811
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001812// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1813// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1814// for what can be included on user builds: all reported information MUST directly relate to
1815// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1816// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1817// names are not), and MUST NOT contain logs of user application traffic.
1818// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001819static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001820 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001821
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001822 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001823
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001824 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001825
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001826 DumpstateRadioCommon(include_sensitive_info);
1827
1828 if (include_sensitive_info) {
1829 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1830 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1831 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1832 // way.
1833 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1834 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001835
1836 printf("========================================================\n");
1837 printf("== Android Framework Services\n");
1838 printf("========================================================\n");
1839
Vishnu Nair652cc802017-11-30 15:18:30 -08001840 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1841 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001842 if (include_sensitive_info) {
1843 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1844 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1845 SEC_TO_MSEC(10));
1846 } else {
1847 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1848 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1849 // give a higher timeout as well.
1850 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1851 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1852 }
1853 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001854 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1855 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001856 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001857 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1858 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001859 if (include_sensitive_info) {
1860 // Contains raw IP addresses, omit from reports on user builds.
1861 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1862 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1863 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1864 SEC_TO_MSEC(10));
1865 // Contains package/component names, omit from reports on user builds.
1866 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1867 SEC_TO_MSEC(10));
1868 // Contains package names, but should be relatively simple to remove them (also contains
1869 // UIDs already), omit from reports on user builds.
1870 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1871 SEC_TO_MSEC(10));
1872 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001873
1874 printf("========================================================\n");
1875 printf("== Running Application Services\n");
1876 printf("========================================================\n");
1877
1878 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1879
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001880 if (include_sensitive_info) {
1881 printf("========================================================\n");
1882 printf("== Running Application Services (non-platform)\n");
1883 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001884
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001885 // Contains package/component names and potential PII, omit from reports on user builds.
1886 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1887 // carrier_config dumpsys instead.
1888 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1889 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001890
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001891 printf("========================================================\n");
1892 printf("== Checkins\n");
1893 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001894
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001895 // Contains package/component names, omit from reports on user builds.
1896 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1897 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001898
1899 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001900 printf("== dumpstate: done (id %d)\n", ds.id_);
1901 printf("========================================================\n");
1902}
1903
mukesh agrawal253dad42018-01-23 21:59:59 -08001904// This method collects dumpsys for wifi debugging only
1905static void DumpstateWifiOnly() {
1906 DurationReporter duration_reporter("DUMPSTATE");
1907
1908 DumpstateRadioCommon();
1909
1910 printf("========================================================\n");
1911 printf("== Android Framework Services\n");
1912 printf("========================================================\n");
1913
1914 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1915 SEC_TO_MSEC(10));
1916 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1917 SEC_TO_MSEC(10));
1918
1919 printf("========================================================\n");
1920 printf("== dumpstate: done (id %d)\n", ds.id_);
1921 printf("========================================================\n");
1922}
1923
Nandana Duttcf419a72019-03-14 10:40:17 +00001924Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001925 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1926 const size_t buf_size = temp_file_pattern.length() + 1;
1927 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1928 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1929
1930 // Create a new, empty file to receive all trace dumps.
1931 //
1932 // TODO: This can be simplified once we remove support for the old style
1933 // dumps. We can have a file descriptor passed in to dump_traces instead
1934 // of creating a file, closing it and then reopening it again.
1935 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1936 if (fd < 0) {
1937 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001938 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001939 }
1940
1941 // Nobody should have access to this temporary file except dumpstate, but we
1942 // temporarily grant 'read' to 'others' here because this file is created
1943 // when tombstoned is still running as root, but dumped after dropping. This
1944 // can go away once support for old style dumping has.
1945 const int chmod_ret = fchmod(fd, 0666);
1946 if (chmod_ret < 0) {
1947 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001948 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001949 }
1950
1951 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1952 if (proc.get() == nullptr) {
1953 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001954 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001955 }
1956
1957 // Number of times process dumping has timed out. If we encounter too many
1958 // failures, we'll give up.
1959 int timeout_failures = 0;
1960 bool dalvik_found = false;
1961
1962 const std::set<int> hal_pids = get_interesting_hal_pids();
1963
1964 struct dirent* d;
1965 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001966 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001967 int pid = atoi(d->d_name);
1968 if (pid <= 0) {
1969 continue;
1970 }
1971
1972 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1973 std::string exe;
1974 if (!android::base::Readlink(link_name, &exe)) {
1975 continue;
1976 }
1977
1978 bool is_java_process;
1979 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1980 // Don't bother dumping backtraces for the zygote.
1981 if (IsZygote(pid)) {
1982 continue;
1983 }
1984
1985 dalvik_found = true;
1986 is_java_process = true;
1987 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1988 is_java_process = false;
1989 } else {
1990 // Probably a native process we don't care about, continue.
1991 continue;
1992 }
1993
1994 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1995 if (timeout_failures == 3) {
1996 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1997 break;
1998 }
1999
2000 const uint64_t start = Nanotime();
2001 const int ret = dump_backtrace_to_file_timeout(
2002 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
2003 is_java_process ? 5 : 20, fd);
2004
2005 if (ret == -1) {
2006 // For consistency, the header and footer to this message match those
2007 // dumped by debuggerd in the success case.
2008 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
2009 dprintf(fd, "Dump failed, likely due to a timeout.\n");
2010 dprintf(fd, "---- end %d ----", pid);
2011 timeout_failures++;
2012 continue;
2013 }
2014
2015 // We've successfully dumped stack traces, reset the failure count
2016 // and write a summary of the elapsed time to the file and continue with the
2017 // next process.
2018 timeout_failures = 0;
2019
2020 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
2021 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
2022 }
2023
2024 if (!dalvik_found) {
2025 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
2026 }
2027
Nandana Duttcf419a72019-03-14 10:40:17 +00002028 *path = file_name_buf.release();
2029 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00002030}
2031
Felipe Leme6f674ae2016-11-18 17:10:33 -08002032void Dumpstate::DumpstateBoard() {
2033 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08002034 printf("========================================================\n");
2035 printf("== Board\n");
2036 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002037
Felipe Leme6f674ae2016-11-18 17:10:33 -08002038 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08002039 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08002040 return;
2041 }
2042
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002043 std::vector<std::string> paths;
2044 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07002045 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002046 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
2047 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002048 remover.emplace_back(android::base::make_scope_guard(
2049 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002050 }
Jie Song9fbfad02017-06-20 16:29:42 -07002051
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002052 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
2053 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07002054 MYLOGE("No IDumpstateDevice implementation\n");
2055 return;
2056 }
2057
2058 using ScopedNativeHandle =
2059 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
2060 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
2061 [](native_handle_t* handle) {
2062 native_handle_close(handle);
2063 native_handle_delete(handle);
2064 });
2065 if (handle == nullptr) {
2066 MYLOGE("Could not create native_handle\n");
2067 return;
2068 }
2069
Nandana Dutt5c390032019-03-12 10:52:56 +00002070 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002071 for (size_t i = 0; i < paths.size(); i++) {
2072 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2073
2074 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2075 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2076 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2077 if (fd < 0) {
2078 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2079 return;
2080 }
2081 handle.get()->data[i] = fd.release();
2082 }
2083
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002084 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2085 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2086 // will kill the HAL and grab whatever it dumped in time.
2087 constexpr size_t timeout_sec = 30;
2088 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2089 // implement just 1.0.
2090 const char* descriptor_to_kill;
2091 using DumpstateBoardTask = std::packaged_task<bool()>;
2092 DumpstateBoardTask dumpstate_board_task;
2093 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2094 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2095 if (dumpstate_device_1_1 != nullptr) {
2096 MYLOGI("Using IDumpstateDevice v1.1");
2097 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2098 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2099 ::android::hardware::Return<DumpstateStatus> status =
2100 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2101 SEC_TO_MSEC(timeout_sec));
2102 if (!status.isOk()) {
2103 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2104 return false;
2105 } else if (status != DumpstateStatus::OK) {
2106 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2107 return false;
2108 }
2109 return true;
2110 });
2111 } else {
2112 MYLOGI("Using IDumpstateDevice v1.0");
2113 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2114 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2115 ::android::hardware::Return<void> status =
2116 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002117 if (!status.isOk()) {
2118 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002119 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002120 }
Wei Wang587eac92018-04-05 12:17:20 -07002121 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002122 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002123 }
2124 auto result = dumpstate_board_task.get_future();
2125 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002126
Wei Wang587eac92018-04-05 12:17:20 -07002127 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2128 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002129 if (!android::base::SetProperty(
2130 "ctl.interface_restart",
2131 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002132 MYLOGE("Couldn't restart dumpstate HAL\n");
2133 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002134 }
Wei Wang587eac92018-04-05 12:17:20 -07002135 // Wait some time for init to kill dumpstate vendor HAL
2136 constexpr size_t killing_timeout_sec = 10;
2137 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2138 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2139 "there might be racing in content\n", killing_timeout_sec);
2140 }
2141
2142 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2143 for (size_t i = 0; i < paths.size(); i++) {
2144 struct stat s;
2145 if (fstat(handle.get()->data[i], &s) == -1) {
2146 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2147 strerror(errno));
2148 file_sizes[i] = -1;
2149 continue;
2150 }
2151 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002152 }
2153
2154 for (size_t i = 0; i < paths.size(); i++) {
2155 if (file_sizes[i] == -1) {
2156 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002157 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002158 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002159 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002160 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002161 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002162 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002163 printf("*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002164 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002165}
2166
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002167static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002168 fprintf(stderr,
mhasank2d75c442020-06-11 15:05:25 -07002169 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o directory] [-d] [-p] "
mhasankd451a472020-05-26 18:02:39 -07002170 "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002171 " -h: display this help message\n"
2172 " -b: play sound file instead of vibrate, at beginning of job\n"
2173 " -e: play sound file instead of vibrate, at end of job\n"
mhasank2d75c442020-06-11 15:05:25 -07002174 " -o: write to custom directory (only in limited mode)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002175 " -d: append date to filename\n"
2176 " -p: capture screenshot to filename.png\n"
2177 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002178 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002179 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002180 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002181 " -P: send broadcast when started and do progress updates\n"
2182 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002183 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002184 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002185 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002186}
2187
Wei Liuf87959e2016-08-26 14:51:42 -07002188static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002189 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002190}
2191
Felipe Leme1d486fe2016-10-14 18:06:47 -07002192bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002193 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002194 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002195 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002196 // Final timestamp
2197 char date[80];
2198 time_t the_real_now_please_stand_up = time(nullptr);
2199 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002200 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002201 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002202
Felipe Leme9a523ae2016-10-20 15:10:33 -07002203 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002204 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002205 return false;
2206 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002207 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002208 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002209 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002210 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002211
Felipe Leme0f3fb202016-06-10 17:10:53 -07002212 // Add log file (which contains stderr output) to zip...
2213 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002214 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002215 MYLOGE("Failed to add dumpstate log to .zip file\n");
2216 return false;
2217 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002218 // TODO: Should truncate the existing file.
2219 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002220 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2221 return false;
2222 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002223 fprintf(stderr, "\n");
2224
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002225 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002226 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002227 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002228 return false;
2229 }
2230
Felipe Leme1d486fe2016-10-14 18:06:47 -07002231 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2232 ds.zip_file.reset(nullptr);
2233
Felipe Lemee9d2c542016-11-15 11:48:26 -08002234 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002235 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002236
Felipe Leme1e9edc62015-12-21 16:02:13 -08002237 return true;
2238}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002239
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002240static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2241 // clang-format off
2242 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2243 "--receiver-foreground", "--receiver-include-background", "-a", action};
2244 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002245
2246 am.insert(am.end(), args.begin(), args.end());
2247
Felipe Leme8d2410e2017-02-08 09:46:08 -08002248 RunCommand("", am,
2249 CommandOptions::WithTimeout(20)
2250 .Log("Sending broadcast: '%s'\n")
2251 .Always()
2252 .DropRoot()
2253 .RedirectStderr()
2254 .Build());
2255}
2256
Felipe Leme35b8cf12017-02-10 15:47:29 -08002257static void Vibrate(int duration_ms) {
2258 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002259 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002260 CommandOptions::WithTimeout(10)
2261 .Log("Vibrate: '%s'\n")
2262 .Always()
2263 .Build());
2264 // clang-format on
2265}
2266
Nandana Dutt979388e2018-11-30 16:48:55 +00002267static void MaybeResolveSymlink(std::string* path) {
2268 std::string resolved_path;
2269 if (android::base::Readlink(*path, &resolved_path)) {
2270 *path = resolved_path;
2271 }
2272}
2273
Nandana Dutt4be45d12018-09-26 15:04:23 +01002274/*
2275 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2276 * if we are writing zip files and adds the version file.
2277 */
2278static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002279 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2280
Nandana Dutt4be45d12018-09-26 15:04:23 +01002281 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2282 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002283 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002284 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002285 char date[80];
2286 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2287 ds.name_ = date;
2288 } else {
2289 ds.name_ = "undated";
2290 }
2291
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002292 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002293 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002294 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002295 ds.base_name_ += "-wifi";
2296 }
2297
Paul Chang0d2aad72020-02-13 20:04:03 +08002298 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002299 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002300 }
2301 ds.tmp_path_ = ds.GetPath(".tmp");
2302 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2303
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002304 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002305 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002306 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002307 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002308 "Bugreport dir: [%s] "
2309 "Base name: [%s] "
2310 "Suffix: [%s] "
2311 "Log path: [%s] "
2312 "Temporary path: [%s] "
2313 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002314 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2315 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002316
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002317 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002318 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002319 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2320 create_parent_dirs(ds.path_.c_str());
2321 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2322 if (ds.zip_file == nullptr) {
2323 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2324 } else {
2325 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2326 }
2327 ds.AddTextZipEntry("version.txt", ds.version_);
2328 }
2329}
2330
2331/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002332 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002333 * printing zipped file status, etc.
2334 */
2335static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002336 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002337 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002338 if (!ds.FinishZipFile()) {
2339 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2340 do_text_file = true;
2341 } else {
2342 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002343 }
2344 }
mhasank2d75c442020-06-11 15:05:25 -07002345
2346 std::string final_path = ds.path_;
2347 if (ds.options_->OutputToCustomFile()) {
mhasank3a4cfb42020-06-15 18:06:43 -07002348 final_path = ds.GetPath(ds.options_->out_dir, ".zip");
mhasank2d75c442020-06-11 15:05:25 -07002349 android::os::CopyFileToFile(ds.path_, final_path);
2350 }
2351
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002352 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002353 if (do_text_file) {
2354 dprintf(ds.control_socket_fd_,
2355 "FAIL:could not create zip file, check %s "
2356 "for more details\n",
2357 ds.log_path_.c_str());
2358 } else {
mhasank2d75c442020-06-11 15:05:25 -07002359 dprintf(ds.control_socket_fd_, "OK:%s\n", final_path.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002360 }
2361 }
2362}
2363
Nandana Dutt4be45d12018-09-26 15:04:23 +01002364
Nandana Dutt58d72e22018-11-16 10:30:48 +00002365static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2366 switch (mode) {
2367 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2368 return "BUGREPORT_FULL";
2369 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2370 return "BUGREPORT_INTERACTIVE";
2371 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2372 return "BUGREPORT_REMOTE";
2373 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2374 return "BUGREPORT_WEAR";
2375 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2376 return "BUGREPORT_TELEPHONY";
2377 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2378 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002379 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2380 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002381 }
2382}
2383
Paul Changf59c2b72020-03-10 02:08:55 +08002384static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2385 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002386 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2387 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002388 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002389 switch (mode) {
2390 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002391 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002392 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002393 break;
2394 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002395 // Currently, the dumpstate binder is only used by Shell to update progress.
2396 options->do_start_service = true;
2397 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002398 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002399 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002400 break;
2401 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002402 options->do_vibrate = false;
2403 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002404 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002405 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002406 break;
2407 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002408 options->do_start_service = true;
2409 options->do_progress_updates = true;
2410 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002411 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002412 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002413 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002414 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002415 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002416 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002417 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002418 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002419 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002420 break;
2421 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002422 options->wifi_only = true;
2423 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002424 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002425 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002426 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002427 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2428 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002429 }
2430}
2431
Nandana Dutt58d72e22018-11-16 10:30:48 +00002432static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002433 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002434 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002435 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002436 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002437 "limited_only: %d args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002438 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002439 options.do_screenshot, options.is_remote_mode, options.show_header_only,
mhasankd451a472020-05-26 18:02:39 -07002440 options.do_start_service, options.telephony_only, options.wifi_only,
2441 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2442 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002443}
2444
Nandana Dutt54dbd672019-01-11 12:58:05 +00002445void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2446 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002447 const android::base::unique_fd& screenshot_fd_in,
2448 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002449 // In the new API world, date is always added; output is always a zip file.
2450 // TODO(111441001): remove these options once they are obsolete.
2451 do_add_date = true;
2452 do_zip_file = true;
2453
Nandana Dutt54dbd672019-01-11 12:58:05 +00002454 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2455 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2456 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002457
Paul Changf59c2b72020-03-10 02:08:55 +08002458 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002459}
2460
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002461Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2462 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002463 int c;
mhasankd451a472020-05-26 18:02:39 -07002464 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002465 switch (c) {
2466 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002467 case 'd': do_add_date = true; break;
2468 case 'z': do_zip_file = true; break;
mhasank3a4cfb42020-06-15 18:06:43 -07002469 case 'o': out_dir = optarg; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002470 case 's': use_socket = true; break;
2471 case 'S': use_control_socket = true; break;
2472 case 'v': show_header_only = true; break;
2473 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002474 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002475 case 'P': do_progress_updates = true; break;
2476 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002477 case 'L': limited_only = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002478 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002479 case 'w':
2480 // This was already processed
2481 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002482 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002483 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002484 break;
2485 default:
2486 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002487 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002488 break;
2489 // clang-format on
2490 }
2491 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002492
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002493 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002494 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002495 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002496 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002497 }
2498 }
2499
2500 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2501 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002502
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002503 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002504}
2505
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002506bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002507 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002508 return false;
2509 }
2510
Abhijeet Kaure370d682019-10-01 16:49:30 +01002511 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002512 return false;
2513 }
2514
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002515 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002516 return false;
2517 }
2518
Abhijeet Kaure370d682019-10-01 16:49:30 +01002519 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002520 return false;
2521 }
2522 return true;
2523}
2524
Nandana Dutt197661d2018-11-16 16:40:21 +00002525void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2526 options_ = std::move(options);
2527}
2528
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002529void Dumpstate::Initialize() {
2530 /* gets the sequential id */
2531 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2532 id_ = ++last_id;
2533 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2534}
2535
Nandana Duttd2f5f082019-01-18 17:13:52 +00002536Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2537 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002538 if (listener_ != nullptr) {
2539 switch (status) {
2540 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002541 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002542 break;
2543 case Dumpstate::RunStatus::HELP:
2544 break;
2545 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002546 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002547 break;
2548 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002549 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2550 break;
2551 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2552 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2553 break;
2554 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2555 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002556 break;
2557 }
2558 }
2559 return status;
2560}
2561
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002562void Dumpstate::Cancel() {
2563 CleanupTmpFiles();
2564 android::os::UnlinkAndLogOnError(log_path_);
2565 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2566 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2567 kDumpstateBoardFiles[i]);
2568 }
2569 tombstone_data_.clear();
2570 anr_data_.clear();
2571}
2572
Nandana Dutt979388e2018-11-30 16:48:55 +00002573/*
2574 * Dumps relevant information to a bugreport based on the given options.
2575 *
2576 * The bugreport can be dumped to a file or streamed to a socket.
2577 *
2578 * How dumping to file works:
2579 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2580 * stderr is redirected a log file.
2581 *
2582 * The temporary bugreport is then populated via printfs, dumping contents of files and
2583 * output of commands to stdout.
2584 *
2585 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2586 * text file.
2587 *
2588 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2589 * gets added to the archive.
2590 *
mhasank2d75c442020-06-11 15:05:25 -07002591 * Bugreports are first generated in a local directory and later copied to the caller's fd
2592 * or directory if supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002593 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002594Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2595 const std::string& calling_package) {
Rhed Jao5377d792020-07-16 17:37:39 +08002596 DurationReporter duration_reporter("RUN INTERNAL", /* logcat_only = */true);
Nandana Dutt979388e2018-11-30 16:48:55 +00002597 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002598 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002599 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002600 return RunStatus::INVALID_INPUT;
2601 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002602 /* set as high priority, and protect from OOM killer */
2603 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002604
Felipe Lemed071c682016-10-20 16:48:00 -07002605 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002606 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002607 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002608 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002609 } else {
2610 /* fallback to kernels <= 2.6.35 */
2611 oom_adj = fopen("/proc/self/oom_adj", "we");
2612 if (oom_adj) {
2613 fputs("-17", oom_adj);
2614 fclose(oom_adj);
2615 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002616 }
2617
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002618 if (version_ == VERSION_DEFAULT) {
2619 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002620 }
2621
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002622 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002623 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002624 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002625 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002626 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002627 }
2628
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002629 if (options_->show_header_only) {
2630 PrintHeader();
2631 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002632 }
2633
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002634 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2635 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002636
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002637 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002638 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002639
2640 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002641 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002642 is_redirecting
2643 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2644 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002645 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002646
Sahana Raof35ed432019-07-12 10:47:52 +01002647 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2648 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2649 } else {
2650 // Wake lock will be released automatically on process death
2651 MYLOGD("Wake lock acquired.\n");
2652 }
2653
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002654 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002655
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002656 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002657 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002658 MYLOGI("Starting 'dumpstate' service\n");
2659 android::status_t ret;
2660 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2661 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2662 }
2663 }
2664
Felipe Lemef0292972016-11-22 13:57:05 -08002665 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002666 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2667 }
2668
Nandana Dutt235c6672019-11-14 15:22:32 +00002669 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2670 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002671
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002672 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002673
Christopher Ferrised9354f2014-10-01 17:35:01 -07002674 // If we are going to use a socket, do it as early as possible
2675 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002676 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002677 if (!redirect_to_socket(stdout, "dumpstate")) {
2678 return ERROR;
2679 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002680 }
2681
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002682 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002683 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002684 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002685 if (control_socket_fd_ == -1) {
2686 return ERROR;
2687 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002688 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002689 }
2690
Felipe Leme71bbfc52015-11-23 14:14:51 -08002691 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002692 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002693
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002694 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002695 // clang-format off
2696 std::vector<std::string> am_args = {
2697 "--receiver-permission", "android.permission.DUMP",
2698 };
2699 // clang-format on
2700 // Send STARTED broadcast for apps that listen to bugreport generation events
2701 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002702 if (options_->use_control_socket) {
2703 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002704 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002705 }
2706 }
2707
Nick Kralevichf3599b32016-01-25 15:05:16 -08002708 /* read /proc/cmdline before dropping root */
2709 FILE *cmdline = fopen("/proc/cmdline", "re");
2710 if (cmdline) {
2711 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2712 fclose(cmdline);
2713 }
2714
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002715 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002716 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002717 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002718
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002719 if (options_->do_zip_file && zip_file != nullptr) {
2720 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2721 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002722 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002723 }
2724 }
2725
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002726 int dup_stdout_fd;
2727 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002728 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002729 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002730 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002731 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2732 return ERROR;
2733 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002734 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2735 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2736 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002737 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002738
2739 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2740 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002741 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002742 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002743 /* TODO: rather than generating a text file now and zipping it later,
2744 it would be more efficient to redirect stdout to the zip entry
2745 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002746 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2747 return ERROR;
2748 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002749 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002750 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002751 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002752 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002753 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002754
2755 // Don't buffer stdout
2756 setvbuf(stdout, nullptr, _IONBF, 0);
2757
Rhed Jao5377d792020-07-16 17:37:39 +08002758 // Enable the parallel run if the client requests to output to a file.
2759 EnableParallelRunIfNeeded();
2760 // Using scope guard to make sure the dump pool can be shut down correctly.
2761 auto scope_guard_to_shutdown_pool = android::base::make_scope_guard([=]() {
2762 ShutdownDumpPool();
2763 });
2764
Felipe Leme608385d2016-02-01 10:35:38 -08002765 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2766 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002767 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002768 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002769
mhasankd451a472020-05-26 18:02:39 -07002770 // TODO(b/158737089) reduce code repetition in if branches
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002771 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002772 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002773 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002774 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002775 DumpstateTelephonyOnly(calling_package);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002776 DumpstateBoard();
2777 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002778 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002779 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002780 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002781 DumpstateWifiOnly();
mhasankd451a472020-05-26 18:02:39 -07002782 } else if (options_->limited_only) {
2783 MaybeTakeEarlyScreenshot();
2784 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
2785 MaybeCheckUserConsent(calling_uid, calling_package);
2786 DumpstateLimitedOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002787 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002788 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002789 RunDumpsysCritical();
2790
Paul Chang0d2aad72020-02-13 20:04:03 +08002791 // Take screenshot and get consent only after critical dumpsys has finished.
2792 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002793 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002794 MaybeCheckUserConsent(calling_uid, calling_package);
2795
Nandana Dutt4be45d12018-09-26 15:04:23 +01002796 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002797 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002798 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002799 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002800 HandleUserConsentDenied();
2801 }
2802 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002803 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002804 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002805
Felipe Leme55b42a62015-11-10 17:39:08 -08002806 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002807 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002808 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002809 }
2810
Abhijeet Kaure370d682019-10-01 16:49:30 +01002811 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002812 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002813 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002814 }
2815
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002816 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002817 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002818 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002819 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002820 if (status != Dumpstate::RunStatus::OK &&
2821 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2822 // Do an early return if there were errors. We make an exception for consent
2823 // timing out because it's possible the user got distracted. In this case the
2824 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002825 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002826 return status;
2827 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002828 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2829 MYLOGI(
2830 "Did not receive user consent yet."
2831 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002832 const String16 incidentcompanion("incidentcompanion");
2833 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2834 if (ics != nullptr) {
2835 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2836 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2837 consent_callback_.get());
2838 } else {
2839 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2840 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002841 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002842 }
2843
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002844 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002845 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002846 for (int i = 0; i < 3; i++) {
2847 Vibrate(75);
2848 usleep((75 + 50) * 1000);
2849 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002850 }
2851
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002852 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2853 progress_->GetInitialMax());
2854 progress_->Save();
2855 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002856
Felipe Leme107a05f2016-03-08 15:11:15 -08002857 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002858 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002859 }
2860
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002861 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002862 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002863 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002864 }
2865
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002866 tombstone_data_.clear();
2867 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002868
Nandana Duttd2f5f082019-01-18 17:13:52 +00002869 return (consent_callback_ != nullptr &&
2870 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2871 ? USER_CONSENT_TIMED_OUT
2872 : RunStatus::OK;
2873}
2874
Paul Chang0d2aad72020-02-13 20:04:03 +08002875void Dumpstate::MaybeTakeEarlyScreenshot() {
2876 if (!options_->do_screenshot || !do_early_screenshot_) {
2877 return;
2878 }
2879
2880 TakeScreenshot();
2881}
2882
Paul Changc490e662020-04-11 18:14:09 +08002883void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
2884 const std::string& calling_package) {
2885 if (calling_uid == AID_SHELL || !CalledByApi()) {
2886 return;
2887 }
2888 if (listener_ != nullptr) {
2889 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2890 // handling if required.
2891 android::String16 package(calling_package.c_str());
2892 listener_->onUiIntensiveBugreportDumpsFinished(package);
2893 }
2894}
2895
Jichao Lie89d9c12019-11-21 19:02:51 -08002896void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2897 if (calling_uid == AID_SHELL || !CalledByApi()) {
2898 // No need to get consent for shell triggered dumpstates, or not through
2899 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002900 return;
2901 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002902 consent_callback_ = new ConsentCallback();
2903 const String16 incidentcompanion("incidentcompanion");
2904 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002905 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002906 if (ics != nullptr) {
2907 MYLOGD("Checking user consent via incidentcompanion service\n");
2908 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002909 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002910 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002911 } else {
2912 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2913 }
2914}
2915
Nandana Dutt5c390032019-03-12 10:52:56 +00002916bool Dumpstate::IsUserConsentDenied() const {
2917 return ds.consent_callback_ != nullptr &&
2918 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2919}
2920
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002921bool Dumpstate::CalledByApi() const {
2922 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2923}
2924
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002925void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002926 android::os::UnlinkAndLogOnError(tmp_path_);
2927 android::os::UnlinkAndLogOnError(screenshot_path_);
2928 android::os::UnlinkAndLogOnError(path_);
2929}
2930
Rhed Jao5377d792020-07-16 17:37:39 +08002931void Dumpstate::EnableParallelRunIfNeeded() {
2932 // The thread pool needs to create temporary files to receive dump results.
2933 // That's why we only enable it when the bugreport client chooses to output
2934 // to a file.
2935 if (!PropertiesHelper::IsParallelRun() || !options_->OutputToFile()) {
2936 return;
2937 }
2938 dump_pool_ = std::make_unique<DumpPool>(bugreport_internal_dir_);
2939}
2940
2941void Dumpstate::ShutdownDumpPool() {
2942 if (dump_pool_) {
2943 dump_pool_->shutdown();
2944 dump_pool_ = nullptr;
2945 }
2946}
2947
Nandana Duttd2f5f082019-01-18 17:13:52 +00002948Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2949 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002950 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00002951 return USER_CONSENT_DENIED;
2952}
2953
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002954Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002955 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002956 // user consent (unless the caller is Shell).
2957 UserConsentResult consent_result;
2958 if (calling_uid == AID_SHELL) {
2959 consent_result = UserConsentResult::APPROVED;
2960 } else {
2961 consent_result = consent_callback_->getResult();
2962 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002963 if (consent_result == UserConsentResult::UNAVAILABLE) {
2964 // User has not responded yet.
2965 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08002966 // Telephony is a fast report type, particularly on user builds where information may be
2967 // more aggressively limited. To give the user time to read the consent dialog, increase the
2968 // timeout.
2969 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
2970 : USER_CONSENT_TIMEOUT_MS;
2971 if (elapsed_ms < timeout_ms) {
2972 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00002973 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2974 sleep(delay_seconds);
2975 }
2976 consent_result = consent_callback_->getResult();
2977 }
2978 if (consent_result == UserConsentResult::DENIED) {
2979 // User has explicitly denied sharing with the app. To be safe delete the
2980 // internal bugreport & tmp files.
2981 return HandleUserConsentDenied();
2982 }
2983 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002984 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2985 if (copy_succeeded) {
2986 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01002987 if (options_->do_screenshot &&
2988 options_->screenshot_fd.get() != -1 &&
2989 !options_->is_screenshot_copied) {
2990 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2991 options_->screenshot_fd.get());
2992 options_->is_screenshot_copied = copy_succeeded;
2993 if (copy_succeeded) {
2994 android::os::UnlinkAndLogOnError(screenshot_path_);
2995 }
2996 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002997 }
2998 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2999 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
3000 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
3001 // Since we do not have user consent to share the bugreport it does not get
3002 // copied over to the calling app but remains in the internal directory from
3003 // where the user can manually pull it.
3004 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
3005 }
3006 // Unknown result; must be a programming error.
3007 MYLOGE("Unknown user consent result:%d\n", consent_result);
3008 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003009}
3010
Nandana Duttf02564e2019-02-15 15:24:24 +00003011Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003012 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
3013 Dumpstate::RunStatus status = options->Initialize(argc, argv);
3014 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00003015 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00003016 // When directly running dumpstate binary, the output is not expected to be written
3017 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00003018 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00003019
3020 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00003021 // an app; they are irrelevant here because bugreport is triggered via command line.
3022 // Update Last ID before calling Run().
3023 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00003024 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003025 }
Nandana Duttf02564e2019-02-15 15:24:24 +00003026 return status;
3027}
3028
3029/* Main entry point for dumpstate binary. */
3030int run_main(int argc, char* argv[]) {
3031 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003032
3033 switch (status) {
3034 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003035 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003036 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003037 ShowUsage();
3038 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003039 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003040 fprintf(stderr, "Invalid combination of args\n");
3041 ShowUsage();
3042 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003043 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00003044 FALLTHROUGH_INTENDED;
3045 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
3046 FALLTHROUGH_INTENDED;
3047 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00003048 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01003049 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07003050}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003051
3052// TODO(111441001): Default DumpOptions to sensible values.
3053Dumpstate::Dumpstate(const std::string& version)
3054 : pid_(getpid()),
3055 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01003056 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003057 version_(version),
3058 now_(time(nullptr)) {
3059}
3060
3061Dumpstate& Dumpstate::GetInstance() {
3062 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
3063 return singleton_;
3064}
3065
Rhed Jao5377d792020-07-16 17:37:39 +08003066DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose,
3067 int duration_fd) : title_(title), logcat_only_(logcat_only), verbose_(verbose),
3068 duration_fd_(duration_fd) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003069 if (!title_.empty()) {
3070 started_ = Nanotime();
3071 }
3072}
3073
3074DurationReporter::~DurationReporter() {
3075 if (!title_.empty()) {
3076 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08003077 if (elapsed >= .5f || verbose_) {
3078 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003079 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08003080 if (!logcat_only_) {
3081 // Use "Yoda grammar" to make it easier to grep|sort sections.
Rhed Jao5377d792020-07-16 17:37:39 +08003082 dprintf(duration_fd_, "------ %.3fs was the duration of '%s' ------\n",
3083 elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003084 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003085 }
3086}
3087
3088const int32_t Progress::kDefaultMax = 5000;
3089
3090Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
3091}
3092
3093Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
3094 : Progress(initial_max, growth_factor, "") {
3095 progress_ = progress;
3096}
3097
3098Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
3099 : initial_max_(initial_max),
3100 progress_(0),
3101 max_(initial_max),
3102 growth_factor_(growth_factor),
3103 n_runs_(0),
3104 average_max_(0),
3105 path_(path) {
3106 if (!path_.empty()) {
3107 Load();
3108 }
3109}
3110
3111void Progress::Load() {
3112 MYLOGD("Loading stats from %s\n", path_.c_str());
3113 std::string content;
3114 if (!android::base::ReadFileToString(path_, &content)) {
3115 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3116 return;
3117 }
3118 if (content.empty()) {
3119 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3120 return;
3121 }
3122 std::vector<std::string> lines = android::base::Split(content, "\n");
3123
3124 if (lines.size() < 1) {
3125 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3126 (int)lines.size(), max_);
3127 return;
3128 }
3129 char* ptr;
3130 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3131 average_max_ = strtol(ptr, nullptr, 10);
3132 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3133 average_max_ > STATS_MAX_AVERAGE) {
3134 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3135 initial_max_ = Progress::kDefaultMax;
3136 } else {
3137 initial_max_ = average_max_;
3138 }
3139 max_ = initial_max_;
3140
3141 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3142}
3143
3144void Progress::Save() {
3145 int32_t total = n_runs_ * average_max_ + progress_;
3146 int32_t runs = n_runs_ + 1;
3147 int32_t average = floor(((float)total) / runs);
3148 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3149 path_.c_str());
3150 if (path_.empty()) {
3151 return;
3152 }
3153
3154 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3155 if (!android::base::WriteStringToFile(content, path_)) {
3156 MYLOGE("Could not save stats on %s\n", path_.c_str());
3157 }
3158}
3159
3160int32_t Progress::Get() const {
3161 return progress_;
3162}
3163
3164bool Progress::Inc(int32_t delta_sec) {
3165 bool changed = false;
3166 if (delta_sec >= 0) {
3167 progress_ += delta_sec;
3168 if (progress_ > max_) {
3169 int32_t old_max = max_;
3170 max_ = floor((float)progress_ * growth_factor_);
3171 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3172 changed = true;
3173 }
3174 }
3175 return changed;
3176}
3177
3178int32_t Progress::GetMax() const {
3179 return max_;
3180}
3181
3182int32_t Progress::GetInitialMax() const {
3183 return initial_max_;
3184}
3185
3186void Progress::Dump(int fd, const std::string& prefix) const {
3187 const char* pr = prefix.c_str();
3188 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3189 dprintf(fd, "%smax: %d\n", pr, max_);
3190 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3191 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3192 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3193 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3194 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3195}
3196
3197bool Dumpstate::IsZipping() const {
3198 return zip_writer_ != nullptr;
3199}
3200
3201std::string Dumpstate::GetPath(const std::string& suffix) const {
3202 return GetPath(bugreport_internal_dir_, suffix);
3203}
3204
3205std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3206 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3207 name_.c_str(), suffix.c_str());
3208}
3209
3210void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3211 progress_ = std::move(progress);
3212}
3213
3214void for_each_userid(void (*func)(int), const char *header) {
3215 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3216 "for_each_userid(%s)", header);
3217 DurationReporter duration_reporter(title);
3218 if (PropertiesHelper::IsDryRun()) return;
3219
3220 DIR *d;
3221 struct dirent *de;
3222
3223 if (header) printf("\n------ %s ------\n", header);
3224 func(0);
3225
3226 if (!(d = opendir("/data/system/users"))) {
3227 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3228 return;
3229 }
3230
3231 while ((de = readdir(d))) {
3232 int userid;
3233 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3234 continue;
3235 }
3236 func(userid);
3237 }
3238
3239 closedir(d);
3240}
3241
3242static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3243 DIR *d;
3244 struct dirent *de;
3245
3246 if (!(d = opendir("/proc"))) {
3247 printf("Failed to open /proc (%s)\n", strerror(errno));
3248 return;
3249 }
3250
3251 if (header) printf("\n------ %s ------\n", header);
3252 while ((de = readdir(d))) {
3253 if (ds.IsUserConsentDenied()) {
3254 MYLOGE(
3255 "Returning early because user denied consent to share bugreport with calling app.");
3256 closedir(d);
3257 return;
3258 }
3259 int pid;
3260 int fd;
3261 char cmdpath[255];
3262 char cmdline[255];
3263
3264 if (!(pid = atoi(de->d_name))) {
3265 continue;
3266 }
3267
3268 memset(cmdline, 0, sizeof(cmdline));
3269
3270 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3271 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3272 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3273 close(fd);
3274 if (cmdline[0]) {
3275 helper(pid, cmdline, arg);
3276 continue;
3277 }
3278 }
3279
3280 // if no cmdline, a kernel thread has comm
3281 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3282 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3283 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3284 close(fd);
3285 if (cmdline[1]) {
3286 cmdline[0] = '[';
3287 size_t len = strcspn(cmdline, "\f\b\r\n");
3288 cmdline[len] = ']';
3289 cmdline[len+1] = '\0';
3290 }
3291 }
3292 if (!cmdline[0]) {
3293 strcpy(cmdline, "N/A");
3294 }
3295 helper(pid, cmdline, arg);
3296 }
3297
3298 closedir(d);
3299}
3300
3301static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3302 for_each_pid_func *func = (for_each_pid_func*) arg;
3303 func(pid, cmdline);
3304}
3305
3306void for_each_pid(for_each_pid_func func, const char *header) {
3307 std::string title = header == nullptr ? "for_each_pid"
3308 : android::base::StringPrintf("for_each_pid(%s)", header);
3309 DurationReporter duration_reporter(title);
3310 if (PropertiesHelper::IsDryRun()) return;
3311
3312 __for_each_pid(for_each_pid_helper, header, (void *) func);
3313}
3314
3315static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3316 DIR *d;
3317 struct dirent *de;
3318 char taskpath[255];
3319 for_each_tid_func *func = (for_each_tid_func *) arg;
3320
3321 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3322
3323 if (!(d = opendir(taskpath))) {
3324 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3325 return;
3326 }
3327
3328 func(pid, pid, cmdline);
3329
3330 while ((de = readdir(d))) {
3331 if (ds.IsUserConsentDenied()) {
3332 MYLOGE(
3333 "Returning early because user denied consent to share bugreport with calling app.");
3334 closedir(d);
3335 return;
3336 }
3337 int tid;
3338 int fd;
3339 char commpath[255];
3340 char comm[255];
3341
3342 if (!(tid = atoi(de->d_name))) {
3343 continue;
3344 }
3345
3346 if (tid == pid)
3347 continue;
3348
3349 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3350 memset(comm, 0, sizeof(comm));
3351 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3352 strcpy(comm, "N/A");
3353 } else {
3354 char *c;
3355 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3356 close(fd);
3357
3358 c = strrchr(comm, '\n');
3359 if (c) {
3360 *c = '\0';
3361 }
3362 }
3363 func(pid, tid, comm);
3364 }
3365
3366 closedir(d);
3367}
3368
3369void for_each_tid(for_each_tid_func func, const char *header) {
3370 std::string title = header == nullptr ? "for_each_tid"
3371 : android::base::StringPrintf("for_each_tid(%s)", header);
3372 DurationReporter duration_reporter(title);
3373
3374 if (PropertiesHelper::IsDryRun()) return;
3375
3376 __for_each_pid(for_each_tid_helper, header, (void *) func);
3377}
3378
3379void show_wchan(int pid, int tid, const char *name) {
3380 if (PropertiesHelper::IsDryRun()) return;
3381
3382 char path[255];
3383 char buffer[255];
3384 int fd, ret, save_errno;
3385 char name_buffer[255];
3386
3387 memset(buffer, 0, sizeof(buffer));
3388
3389 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3390 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3391 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3392 return;
3393 }
3394
3395 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3396 save_errno = errno;
3397 close(fd);
3398
3399 if (ret < 0) {
3400 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3401 return;
3402 }
3403
3404 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3405 pid == tid ? 0 : 3, "", name);
3406
3407 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3408
3409 return;
3410}
3411
3412// print time in centiseconds
3413static void snprcent(char *buffer, size_t len, size_t spc,
3414 unsigned long long time) {
3415 static long hz; // cache discovered hz
3416
3417 if (hz <= 0) {
3418 hz = sysconf(_SC_CLK_TCK);
3419 if (hz <= 0) {
3420 hz = 1000;
3421 }
3422 }
3423
3424 // convert to centiseconds
3425 time = (time * 100 + (hz / 2)) / hz;
3426
3427 char str[16];
3428
3429 snprintf(str, sizeof(str), " %llu.%02u",
3430 time / 100, (unsigned)(time % 100));
3431 size_t offset = strlen(buffer);
3432 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3433 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3434}
3435
3436// print permille as a percent
3437static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3438 char str[16];
3439
3440 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3441 size_t offset = strlen(buffer);
3442 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3443 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3444}
3445
3446void show_showtime(int pid, const char *name) {
3447 if (PropertiesHelper::IsDryRun()) return;
3448
3449 char path[255];
3450 char buffer[1023];
3451 int fd, ret, save_errno;
3452
3453 memset(buffer, 0, sizeof(buffer));
3454
3455 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3456 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3457 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3458 return;
3459 }
3460
3461 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3462 save_errno = errno;
3463 close(fd);
3464
3465 if (ret < 0) {
3466 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3467 return;
3468 }
3469
3470 // field 14 is utime
3471 // field 15 is stime
3472 // field 42 is iotime
3473 unsigned long long utime = 0, stime = 0, iotime = 0;
3474 if (sscanf(buffer,
3475 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3476 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3477 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3478 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3479 &utime, &stime, &iotime) != 3) {
3480 return;
3481 }
3482
3483 unsigned long long total = utime + stime;
3484 if (!total) {
3485 return;
3486 }
3487
3488 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3489 if (permille > 1000) {
3490 permille = 1000;
3491 }
3492
3493 // try to beautify and stabilize columns at <80 characters
3494 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3495 if ((name[0] != '[') || utime) {
3496 snprcent(buffer, sizeof(buffer), 57, utime);
3497 }
3498 snprcent(buffer, sizeof(buffer), 65, stime);
3499 if ((name[0] != '[') || iotime) {
3500 snprcent(buffer, sizeof(buffer), 73, iotime);
3501 }
3502 if (iotime) {
3503 snprdec(buffer, sizeof(buffer), 79, permille);
3504 }
3505 puts(buffer); // adds a trailing newline
3506
3507 return;
3508}
3509
3510void do_dmesg() {
3511 const char *title = "KERNEL LOG (dmesg)";
3512 DurationReporter duration_reporter(title);
3513 printf("------ %s ------\n", title);
3514
3515 if (PropertiesHelper::IsDryRun()) return;
3516
3517 /* Get size of kernel buffer */
3518 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3519 if (size <= 0) {
3520 printf("Unexpected klogctl return value: %d\n\n", size);
3521 return;
3522 }
3523 char *buf = (char *) malloc(size + 1);
3524 if (buf == nullptr) {
3525 printf("memory allocation failed\n\n");
3526 return;
3527 }
3528 int retval = klogctl(KLOG_READ_ALL, buf, size);
3529 if (retval < 0) {
3530 printf("klogctl failure\n\n");
3531 free(buf);
3532 return;
3533 }
3534 buf[retval] = '\0';
3535 printf("%s\n\n", buf);
3536 free(buf);
3537 return;
3538}
3539
3540void do_showmap(int pid, const char *name) {
3541 char title[255];
3542 char arg[255];
3543
3544 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3545 snprintf(arg, sizeof(arg), "%d", pid);
3546 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3547}
3548
3549int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3550 DurationReporter duration_reporter(title);
3551
3552 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3553
3554 UpdateProgress(WEIGHT_FILE);
3555
3556 return status;
3557}
3558
3559int read_file_as_long(const char *path, long int *output) {
3560 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3561 if (fd < 0) {
3562 int err = errno;
3563 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3564 return -1;
3565 }
3566 char buffer[50];
3567 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3568 if (bytes_read == -1) {
3569 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3570 return -2;
3571 }
3572 if (bytes_read == 0) {
3573 MYLOGE("File %s is empty\n", path);
3574 return -3;
3575 }
3576 *output = atoi(buffer);
3577 return 0;
3578}
3579
3580/* calls skip to gate calling dump_from_fd recursively
3581 * in the specified directory. dump_from_fd defaults to
3582 * dump_file_from_fd above when set to NULL. skip defaults
3583 * to false when set to NULL. dump_from_fd will always be
3584 * called with title NULL.
3585 */
3586int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3587 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3588 DurationReporter duration_reporter(title);
3589 DIR *dirp;
3590 struct dirent *d;
3591 char *newpath = nullptr;
3592 const char *slash = "/";
3593 int retval = 0;
3594
3595 if (!title.empty()) {
3596 printf("------ %s (%s) ------\n", title.c_str(), dir);
3597 }
3598 if (PropertiesHelper::IsDryRun()) return 0;
3599
3600 if (dir[strlen(dir) - 1] == '/') {
3601 ++slash;
3602 }
3603 dirp = opendir(dir);
3604 if (dirp == nullptr) {
3605 retval = -errno;
3606 MYLOGE("%s: %s\n", dir, strerror(errno));
3607 return retval;
3608 }
3609
3610 if (!dump_from_fd) {
3611 dump_from_fd = dump_file_from_fd;
3612 }
3613 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3614 if ((d->d_name[0] == '.')
3615 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3616 || (d->d_name[1] == '\0'))) {
3617 continue;
3618 }
3619 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3620 (d->d_type == DT_DIR) ? "/" : "");
3621 if (!newpath) {
3622 retval = -errno;
3623 continue;
3624 }
3625 if (skip && (*skip)(newpath)) {
3626 continue;
3627 }
3628 if (d->d_type == DT_DIR) {
3629 int ret = dump_files("", newpath, skip, dump_from_fd);
3630 if (ret < 0) {
3631 retval = ret;
3632 }
3633 continue;
3634 }
3635 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3636 if (fd.get() < 0) {
3637 retval = -1;
3638 printf("*** %s: %s\n", newpath, strerror(errno));
3639 continue;
3640 }
3641 (*dump_from_fd)(nullptr, newpath, fd.get());
3642 }
3643 closedir(dirp);
3644 if (!title.empty()) {
3645 printf("\n");
3646 }
3647 return retval;
3648}
3649
3650/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3651 * it's possible to avoid issues where opening the file itself can get
3652 * stuck.
3653 */
3654int dump_file_from_fd(const char *title, const char *path, int fd) {
3655 if (PropertiesHelper::IsDryRun()) return 0;
3656
3657 int flags = fcntl(fd, F_GETFL);
3658 if (flags == -1) {
3659 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3660 return -1;
3661 } else if (!(flags & O_NONBLOCK)) {
3662 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3663 return -1;
3664 }
3665 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3666}
3667
3668int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +01003669 const CommandOptions& options, bool verbose_duration) {
3670 DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003671
3672 int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
3673
3674 /* TODO: for now we're simplifying the progress calculation by using the
3675 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3676 * where its weight should be much higher proportionally to its timeout.
3677 * Ideally, it should use a options.EstimatedDuration() instead...*/
3678 UpdateProgress(options.Timeout());
3679
3680 return status;
3681}
3682
3683void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3684 const CommandOptions& options, long dumpsysTimeoutMs) {
3685 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3686 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3687 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3688 RunCommand(title, dumpsys, options);
3689}
3690
3691int open_socket(const char *service) {
3692 int s = android_get_control_socket(service);
3693 if (s < 0) {
3694 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3695 return -1;
3696 }
3697 fcntl(s, F_SETFD, FD_CLOEXEC);
3698
3699 // Set backlog to 0 to make sure that queue size will be minimum.
3700 // In Linux, because the minimum queue will be 1, connect() will be blocked
3701 // if the other clients already called connect() and the connection request was not accepted.
3702 if (listen(s, 0) < 0) {
3703 MYLOGE("listen(control socket): %s\n", strerror(errno));
3704 return -1;
3705 }
3706
3707 struct sockaddr addr;
3708 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003709 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003710
3711 // Close socket just after accept(), to make sure that connect() by client will get error
3712 // when the socket is used by the other services.
3713 // There is still a race condition possibility between accept and close, but there is no way
3714 // to close-on-accept atomically.
3715 // See detail; b/123306389#comment25
3716 close(s);
3717
3718 if (fd < 0) {
3719 MYLOGE("accept(control socket): %s\n", strerror(errno));
3720 return -1;
3721 }
3722
3723 return fd;
3724}
3725
3726/* redirect output to a service control socket */
3727bool redirect_to_socket(FILE* redirect, const char* service) {
3728 int fd = open_socket(service);
3729 if (fd == -1) {
3730 return false;
3731 }
3732 fflush(redirect);
3733 // TODO: handle dup2 failure
3734 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3735 close(fd);
3736 return true;
3737}
3738
3739// TODO: should call is_valid_output_file and/or be merged into it.
3740void create_parent_dirs(const char *path) {
3741 char *chp = const_cast<char *> (path);
3742
3743 /* skip initial slash */
3744 if (chp[0] == '/')
3745 chp++;
3746
3747 /* create leading directories, if necessary */
3748 struct stat dir_stat;
3749 while (chp && chp[0]) {
3750 chp = strchr(chp, '/');
3751 if (chp) {
3752 *chp = 0;
3753 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3754 MYLOGI("Creating directory %s\n", path);
3755 if (mkdir(path, 0770)) { /* drwxrwx--- */
3756 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3757 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3758 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3759 }
3760 }
3761 *chp++ = '/';
3762 }
3763 }
3764}
3765
3766bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3767 create_parent_dirs(path);
3768
3769 int fd = TEMP_FAILURE_RETRY(open(path,
3770 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3771 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3772 if (fd < 0) {
3773 MYLOGE("%s: %s\n", path, strerror(errno));
3774 return false;
3775 }
3776
3777 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3778 close(fd);
3779 return true;
3780}
3781
3782bool redirect_to_file(FILE* redirect, char* path) {
3783 return _redirect_to_file(redirect, path, O_TRUNC);
3784}
3785
3786bool redirect_to_existing_file(FILE* redirect, char* path) {
3787 return _redirect_to_file(redirect, path, O_APPEND);
3788}
3789
3790void dump_route_tables() {
3791 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3792 if (PropertiesHelper::IsDryRun()) return;
3793 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3794 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3795 FILE* fp = fopen(RT_TABLES_PATH, "re");
3796 if (!fp) {
3797 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3798 return;
3799 }
3800 char table[16];
3801 // Each line has an integer (the table number), a space, and a string (the table name). We only
3802 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3803 // Add a fixed max limit so this doesn't go awry.
3804 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3805 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3806 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3807 }
3808 fclose(fp);
3809}
3810
3811// TODO: make this function thread safe if sections are generated in parallel.
3812void Dumpstate::UpdateProgress(int32_t delta_sec) {
3813 if (progress_ == nullptr) {
3814 MYLOGE("UpdateProgress: progress_ not set\n");
3815 return;
3816 }
3817
3818 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01003819 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003820
3821 // ...but only notifiy listeners when necessary.
3822 if (!options_->do_progress_updates) return;
3823
3824 int progress = progress_->Get();
3825 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01003826 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003827
Nandana Dutt402a8392019-06-14 14:25:13 +01003828 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003829 return;
3830 }
Nandana Dutt402a8392019-06-14 14:25:13 +01003831 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003832
3833 if (control_socket_fd_ >= 0) {
3834 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3835 fsync(control_socket_fd_);
3836 }
3837
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003838 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003839 if (percent % 10 == 0) {
3840 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003841 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003842 } else {
3843 // stderr is ignored on normal invocations, but useful when calling
3844 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003845 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003846 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003847
3848 listener_->onProgress(percent);
3849 }
3850}
3851
3852void Dumpstate::TakeScreenshot(const std::string& path) {
3853 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3854 int status =
3855 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3856 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3857 if (status == 0) {
3858 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3859 } else {
3860 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3861 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003862 if (listener_ != nullptr) {
3863 // Show a visual indication to indicate screenshot is taken via
3864 // IDumpstateListener.onScreenshotTaken()
3865 listener_->onScreenshotTaken(status == 0);
3866 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003867}
3868
3869bool is_dir(const char* pathname) {
3870 struct stat info;
3871 if (stat(pathname, &info) == -1) {
3872 return false;
3873 }
3874 return S_ISDIR(info.st_mode);
3875}
3876
3877time_t get_mtime(int fd, time_t default_mtime) {
3878 struct stat info;
3879 if (fstat(fd, &info) == -1) {
3880 return default_mtime;
3881 }
3882 return info.st_mtime;
3883}