blob: 93f8b68aed0ac5d062ceea8b155dfd99ecc6d7f8 [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>
Felipe Leme75876a22016-10-27 16:31:27 -070081#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070082#include <private/android_filesystem_config.h>
83#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080084#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070085#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080086#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070087#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070088#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080089
Hunter Knepshield8540faf2020-02-04 19:47:20 -080090using IDumpstateDevice_1_0 = ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
91using IDumpstateDevice_1_1 = ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
92using ::android::hardware::dumpstate::V1_1::DumpstateMode;
93using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
94using ::android::hardware::dumpstate::V1_1::toString;
Vishnu Naire97d6122018-01-18 13:58:56 -080095using ::std::literals::chrono_literals::operator""ms;
96using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080097
Felipe Leme47e9be22016-12-21 15:37:07 -080098// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080099using android::defaultServiceManager;
100using android::Dumpsys;
101using android::INVALID_OPERATION;
102using android::IServiceManager;
103using android::OK;
104using android::sp;
105using android::status_t;
106using android::String16;
107using android::String8;
108using android::TIMED_OUT;
109using android::UNKNOWN_ERROR;
110using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +0000111using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000112using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -0800113using android::os::dumpstate::CommandOptions;
114using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -0800115using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -0800116
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100117// Keep in sync with
118// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
119static const int TRACE_DUMP_TIMEOUT_MS = 10000; // 10 seconds
120
121/* Most simple commands have 10 as timeout, so 5 is a good estimate */
122static const int32_t WEIGHT_FILE = 5;
123
124// TODO: temporary variables and functions used during C++ refactoring
125static Dumpstate& ds = Dumpstate::GetInstance();
126static int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +0100127 const CommandOptions& options = CommandOptions::DEFAULT,
128 bool verbose_duration = false) {
129 return ds.RunCommand(title, full_command, options, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +0100130}
131
132// Reasonable value for max stats.
133static const int STATS_MAX_N_RUNS = 1000;
134static const long STATS_MAX_AVERAGE = 100000;
135
136CommandOptions Dumpstate::DEFAULT_DUMPSYS = CommandOptions::WithTimeout(30).Build();
137
Nandana Duttd2f5f082019-01-18 17:13:52 +0000138typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
139
Colin Crossf45fa6b2012-03-26 12:38:26 -0700140/* read before root is shed */
141static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700142static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000143static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Hunter Knepshield70610fa2020-01-03 15:27:33 -0800144// Because telephony reports are significantly faster to collect (< 10 seconds vs. > 2 minutes),
145// it's often the case that they time out far too quickly for consent with such a hefty dialog for
146// the user to read. For telephony reports only, we increase the default timeout to 2 minutes to
147// roughly match full reports' durations.
148static const uint64_t TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS = 2 * 60 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700149
Felipe Leme1d486fe2016-10-14 18:06:47 -0700150// TODO: variables and functions below should be part of dumpstate object
151
Felipe Leme635ca312016-01-05 14:23:02 -0800152static std::set<std::string> mount_points;
153void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800154
Todd Poynor2a83daa2013-11-22 15:44:22 -0800155#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700156#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700157#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800158
Felipe Lemee82a27d2016-01-05 13:35:44 -0800159#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700160#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700161#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700162#define LOGPERSIST_DATA_DIR "/data/misc/logd"
Jerry Changa1df8a92020-01-02 16:03:39 +0800163#define PREREBOOT_DATA_DIR "/data/misc/prereboot"
David Brazdild2991962016-06-03 14:40:44 +0100164#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
165#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800166#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900167#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800168#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Yifan Hong3945e1b2019-10-29 12:59:23 -0700169#define OTA_METADATA_DIR "/metadata/ota"
Yifan Hong0efa7972020-02-03 16:45:02 -0800170#define SNAPSHOTCTL_LOG_DIR "/data/misc/snapshotctl_log"
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +0900171#define LINKERCONFIG_DIR "/linkerconfig"
Calin Juravlef84d3692020-04-28 15:31:12 -0700172#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700173
Narayan Kamath8f788292017-05-25 13:20:39 +0100174// TODO(narayan): Since this information has to be kept in sync
175// with tombstoned, we should just put it in a common header.
176//
177// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100178static const std::string TOMBSTONE_DIR = "/data/tombstones/";
179static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
180static const std::string ANR_DIR = "/data/anr/";
181static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700182
Felipe Lemee844a9d2016-09-21 15:01:39 -0700183// TODO: temporary variables and functions used during C++ refactoring
Nandana Dutt979388e2018-11-30 16:48:55 +0000184
Nandana Dutt5c390032019-03-12 10:52:56 +0000185#define RETURN_IF_USER_DENIED_CONSENT() \
186 if (ds.IsUserConsentDenied()) { \
187 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
188 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
189 }
190
191// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
192// if consent is found to be denied.
193#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
194 RETURN_IF_USER_DENIED_CONSENT(); \
195 func_ptr(__VA_ARGS__); \
196 RETURN_IF_USER_DENIED_CONSENT();
197
Sahana Raof35ed432019-07-12 10:47:52 +0100198static const char* WAKE_LOCK_NAME = "dumpstate_wakelock";
199
Nandana Dutt979388e2018-11-30 16:48:55 +0000200namespace android {
201namespace os {
202namespace {
203
204static int Open(std::string path, int flags, mode_t mode = 0) {
205 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
206 if (fd == -1) {
207 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
208 }
209 return fd;
210}
211
Nandana Dutt979388e2018-11-30 16:48:55 +0000212
213static int OpenForRead(std::string path) {
214 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
215}
216
217bool CopyFile(int in_fd, int out_fd) {
218 char buf[4096];
219 ssize_t byte_count;
220 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
221 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
222 return false;
223 }
224 }
225 return (byte_count != -1);
226}
227
228static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000229 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000230
231 // Obtain a handle to the source file.
232 android::base::unique_fd in_fd(OpenForRead(input_file));
233 if (out_fd != -1 && in_fd.get() != -1) {
234 if (CopyFile(in_fd.get(), out_fd)) {
235 return true;
236 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000237 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000238 }
239 return false;
240}
241
Nandana Duttd2f5f082019-01-18 17:13:52 +0000242static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt8ae16e62020-03-27 10:20:22 +0000243 if (file.empty()) {
244 return false;
245 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000246 if (unlink(file.c_str())) {
247 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000248 return false;
249 }
250 return true;
251}
Nandana Dutt979388e2018-11-30 16:48:55 +0000252
Nikita Ioffea325a572019-05-16 19:49:47 +0100253int64_t GetModuleMetadataVersion() {
254 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
255 if (binder == nullptr) {
256 MYLOGE("Failed to retrieve package_native service");
257 return 0L;
258 }
259 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
260 std::string package_name;
261 auto status = package_service->getModuleMetadataPackageName(&package_name);
262 if (!status.isOk()) {
263 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
264 return 0L;
265 }
Nandana Duttdb379fa2019-10-09 16:54:41 +0100266 MYLOGD("Module metadata package name: %s\n", package_name.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100267 int64_t version_code;
268 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
269 &version_code);
270 if (!status.isOk()) {
271 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
272 return 0L;
273 }
274 return version_code;
275}
276
Nandana Dutt979388e2018-11-30 16:48:55 +0000277} // namespace
278} // namespace os
279} // namespace android
280
Felipe Leme678727a2016-09-21 17:22:11 -0700281static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800282 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800283 long dumpsysTimeoutMs = 0) {
284 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700285}
286static int DumpFile(const std::string& title, const std::string& path) {
287 return ds.DumpFile(title, path);
288}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800289
Felipe Lemee844a9d2016-09-21 15:01:39 -0700290// Relative directory (inside the zip) for all files copied as-is into the bugreport.
291static const std::string ZIP_ROOT_DIR = "FS";
292
Vishnu Naire97d6122018-01-18 13:58:56 -0800293static const std::string kProtoPath = "proto/";
294static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700295static const std::string kDumpstateBoardFiles[] = {
296 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700297 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700298};
299static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
300
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700301static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700302static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700303
Felipe Lemef0292972016-11-22 13:57:05 -0800304static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
305
Narayan Kamath8f788292017-05-25 13:20:39 +0100306/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100307 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
Rhed Jao01dc0c62020-06-03 17:13:30 +0800308 * The returned vector is sorted by the mtimes of the dumps with descending
309 * order. If |limit_by_mtime| is set, the vector only contains files that
310 * were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100311 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700312static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
313 const std::string& file_prefix,
Elliott Hughesdb6d2112019-09-26 15:24:51 -0700314 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100315 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
316
Narayan Kamathbd863722017-06-01 18:50:12 +0100317 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100318
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700319 if (dump_dir == nullptr) {
320 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700321 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700322 }
323
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700324 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100325 struct dirent* entry = nullptr;
326 while ((entry = readdir(dump_dir.get()))) {
327 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100328 continue;
329 }
330
Narayan Kamathbd863722017-06-01 18:50:12 +0100331 const std::string base_name(entry->d_name);
332 if (base_name.find(file_prefix) != 0) {
333 continue;
334 }
335
336 const std::string abs_path = dir_path + base_name;
337 android::base::unique_fd fd(
338 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
339 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700340 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100341 break;
342 }
343
344 struct stat st = {};
345 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700346 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100347 continue;
348 }
349
Narayan Kamath3f31b632018-02-22 19:42:36 +0000350 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100351 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100352 continue;
353 }
354
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700355 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700356 }
Rhed Jao01dc0c62020-06-03 17:13:30 +0800357 if (!dump_data.empty()) {
358 std::sort(dump_data.begin(), dump_data.end(),
359 [](const auto& a, const auto& b) { return a.mtime > b.mtime; });
360 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100361
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700362 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100363}
364
Narayan Kamathbd863722017-06-01 18:50:12 +0100365static bool AddDumps(const std::vector<DumpData>::const_iterator start,
366 const std::vector<DumpData>::const_iterator end,
367 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100368 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100369 for (auto it = start; it != end; ++it) {
370 const std::string& name = it->name;
371 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100372 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100373
374 // Seek to the beginning of the file before dumping any data. A given
375 // DumpData entry might be dumped multiple times in the report.
376 //
377 // For example, the most recent ANR entry is dumped to the body of the
378 // main entry and it also shows up as a separate entry in the bugreport
379 // ZIP file.
380 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
381 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
382 strerror(errno));
383 }
384
Narayan Kamath8f788292017-05-25 13:20:39 +0100385 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800386 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100387 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100388 }
389 } else {
390 dump_file_from_fd(type_name, name.c_str(), fd);
391 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100392 }
393
394 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700395}
396
Felipe Leme635ca312016-01-05 14:23:02 -0800397// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700398void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800399 char path[PATH_MAX];
400
401 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
402 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700403 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800404 char linkname[PATH_MAX];
405 ssize_t r = readlink(path, linkname, PATH_MAX);
406 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800407 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800408 return;
409 }
410 linkname[r] = '\0';
411
412 if (mount_points.find(linkname) == mount_points.end()) {
413 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700414 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700415 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800416 mount_points.insert(linkname);
417 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800418 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800419 }
420 }
421}
422
423void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700424 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700425 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800426 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800427 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700428 for_each_pid(do_mountinfo, nullptr);
429 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800430}
431
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700432static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
433{
434 DIR *d;
435 struct dirent *de;
436 char path[PATH_MAX];
437
438 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700439 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700440 return;
441 }
442
443 while ((de = readdir(d))) {
444 if (de->d_type != DT_LNK) {
445 continue;
446 }
447 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700448 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700449 }
450
451 closedir(d);
452}
453
Mark Salyzyn326842f2015-04-30 09:49:41 -0700454static bool skip_not_stat(const char *path) {
455 static const char stat[] = "/stat";
456 size_t len = strlen(path);
457 if (path[len - 1] == '/') { /* Directory? */
458 return false;
459 }
460 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
461}
462
Felipe Leme4c2d6632016-09-28 14:32:00 -0700463static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800464 return false;
465}
466
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700467unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700468
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800469//
470// stat offsets
471// Name units description
472// ---- ----- -----------
473// read I/Os requests number of read I/Os processed
474#define __STAT_READ_IOS 0
475// read merges requests number of read I/Os merged with in-queue I/O
476#define __STAT_READ_MERGES 1
477// read sectors sectors number of sectors read
478#define __STAT_READ_SECTORS 2
479// read ticks milliseconds total wait time for read requests
480#define __STAT_READ_TICKS 3
481// write I/Os requests number of write I/Os processed
482#define __STAT_WRITE_IOS 4
483// write merges requests number of write I/Os merged with in-queue I/O
484#define __STAT_WRITE_MERGES 5
485// write sectors sectors number of sectors written
486#define __STAT_WRITE_SECTORS 6
487// write ticks milliseconds total wait time for write requests
488#define __STAT_WRITE_TICKS 7
489// in_flight requests number of I/Os currently in flight
490#define __STAT_IN_FLIGHT 8
491// io_ticks milliseconds total time this block device has been active
492#define __STAT_IO_TICKS 9
493// time_in_queue milliseconds total wait time for all requests
494#define __STAT_IN_QUEUE 10
495#define __STAT_NUMBER_FIELD 11
496//
497// read I/Os, write I/Os
498// =====================
499//
500// These values increment when an I/O request completes.
501//
502// read merges, write merges
503// =========================
504//
505// These values increment when an I/O request is merged with an
506// already-queued I/O request.
507//
508// read sectors, write sectors
509// ===========================
510//
511// These values count the number of sectors read from or written to this
512// block device. The "sectors" in question are the standard UNIX 512-byte
513// sectors, not any device- or filesystem-specific block size. The
514// counters are incremented when the I/O completes.
515#define SECTOR_SIZE 512
516//
517// read ticks, write ticks
518// =======================
519//
520// These values count the number of milliseconds that I/O requests have
521// waited on this block device. If there are multiple I/O requests waiting,
522// these values will increase at a rate greater than 1000/second; for
523// example, if 60 read requests wait for an average of 30 ms, the read_ticks
524// field will increase by 60*30 = 1800.
525//
526// in_flight
527// =========
528//
529// This value counts the number of I/O requests that have been issued to
530// the device driver but have not yet completed. It does not include I/O
531// requests that are in the queue but not yet issued to the device driver.
532//
533// io_ticks
534// ========
535//
536// This value counts the number of milliseconds during which the device has
537// had I/O requests queued.
538//
539// time_in_queue
540// =============
541//
542// This value counts the number of milliseconds that I/O requests have waited
543// on this block device. If there are multiple I/O requests waiting, this
544// value will increase as the product of the number of milliseconds times the
545// number of requests waiting (see "read ticks" above for an example).
546#define S_TO_MS 1000
547//
548
Mark Salyzyn326842f2015-04-30 09:49:41 -0700549static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800550 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700551 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700552 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700553 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700554 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700555 getline(&buffer, &i, fp);
556 fclose(fp);
557 if (!buffer) {
558 return -errno;
559 }
560 i = strlen(buffer);
561 while ((i > 0) && (buffer[i - 1] == '\n')) {
562 buffer[--i] = '\0';
563 }
564 if (!*buffer) {
565 free(buffer);
566 return 0;
567 }
568 z = true;
569 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800570 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700571 if (fields[i] != 0) {
572 z = false;
573 }
574 }
575 if (z) { /* never accessed */
576 free(buffer);
577 return 0;
578 }
579
Wei Wang509bb5d2017-06-09 14:42:12 -0700580 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
581 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700582 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700583
584 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
585 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
586 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700587 free(buffer);
588
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800589 if (fields[__STAT_IO_TICKS]) {
590 unsigned long read_perf = 0;
591 unsigned long read_ios = 0;
592 if (fields[__STAT_READ_TICKS]) {
593 unsigned long long divisor = fields[__STAT_READ_TICKS]
594 * fields[__STAT_IO_TICKS];
595 read_perf = ((unsigned long long)SECTOR_SIZE
596 * fields[__STAT_READ_SECTORS]
597 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
598 / divisor;
599 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
600 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
601 / divisor;
602 }
603
604 unsigned long write_perf = 0;
605 unsigned long write_ios = 0;
606 if (fields[__STAT_WRITE_TICKS]) {
607 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
608 * fields[__STAT_IO_TICKS];
609 write_perf = ((unsigned long long)SECTOR_SIZE
610 * fields[__STAT_WRITE_SECTORS]
611 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
612 / divisor;
613 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
614 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
615 / divisor;
616 }
617
618 unsigned queue = (fields[__STAT_IN_QUEUE]
619 + (fields[__STAT_IO_TICKS] >> 1))
620 / fields[__STAT_IO_TICKS];
621
622 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700623 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 -0800624 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700625 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 -0800626 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 }
628
629 /* bugreport timeout factor adjustment */
630 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
631 worst_write_perf = write_perf;
632 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700633 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 return 0;
635}
636
Yao Chenbe3bbc12018-01-17 16:31:10 -0800637static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
638
639/* timeout in ms to read a list of buffers */
640static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
641 unsigned long timeout_ms = 0;
642 for (const auto& buffer : buffers) {
643 log_id_t id = android_name_to_log_id(buffer.c_str());
644 unsigned long property_size = __android_logger_get_buffer_size(id);
645 /* Engineering margin is ten-fold our guess */
646 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
647 }
648 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700649}
650
Nandana Duttd2f5f082019-01-18 17:13:52 +0000651Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
652}
653
654android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
655 std::lock_guard<std::mutex> lock(lock_);
656 result_ = APPROVED;
657 MYLOGD("User approved consent to share bugreport\n");
Paul Chang0d2aad72020-02-13 20:04:03 +0800658
659 // Maybe copy screenshot so calling app can display the screenshot to the user as soon as
660 // consent is granted.
661 if (ds.options_->is_screenshot_copied) {
662 return android::binder::Status::ok();
663 }
664
665 if (!ds.options_->do_screenshot || ds.options_->screenshot_fd.get() == -1 ||
666 !ds.do_early_screenshot_) {
667 return android::binder::Status::ok();
668 }
669
670 bool copy_succeeded = android::os::CopyFileToFd(ds.screenshot_path_,
671 ds.options_->screenshot_fd.get());
672 ds.options_->is_screenshot_copied = copy_succeeded;
673 if (copy_succeeded) {
674 android::os::UnlinkAndLogOnError(ds.screenshot_path_);
675 }
Nandana Duttd2f5f082019-01-18 17:13:52 +0000676 return android::binder::Status::ok();
677}
678
679android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
680 std::lock_guard<std::mutex> lock(lock_);
681 result_ = DENIED;
682 MYLOGW("User denied consent to share bugreport\n");
683 return android::binder::Status::ok();
684}
685
686UserConsentResult Dumpstate::ConsentCallback::getResult() {
687 std::lock_guard<std::mutex> lock(lock_);
688 return result_;
689}
690
691uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
Hunter Knepshieldf0a39052020-01-03 14:53:04 -0800692 return (Nanotime() - start_time_) / NANOS_PER_MILLI;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000693}
694
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700695void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700696 std::string build, fingerprint, radio, bootloader, network;
697 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700698
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700699 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
700 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700701 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
702 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
703 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700704 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700705
Felipe Lemed8b94e52016-12-08 10:21:44 -0800706 printf("========================================================\n");
707 printf("== dumpstate: %s\n", date);
708 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700709
Felipe Lemed8b94e52016-12-08 10:21:44 -0800710 printf("\n");
711 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700712 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800713 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
714 printf("Bootloader: %s\n", bootloader.c_str());
715 printf("Radio: %s\n", radio.c_str());
716 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100717 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
718 if (module_metadata_version != 0) {
719 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
720 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700721
Felipe Lemed8b94e52016-12-08 10:21:44 -0800722 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800723 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800724 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800725 printf("Uptime: ");
726 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
727 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800728 printf("Bugreport format version: %s\n", version_.c_str());
Abhijeet Kaure370d682019-10-01 16:49:30 +0100729 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s bugreport_mode=%s\n", id_, pid_,
730 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->bugreport_mode.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800731 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800732}
733
Felipe Leme24b66ee2016-06-16 10:55:26 -0700734// List of file extensions that can cause a zip file attachment to be rejected by some email
735// service providers.
736static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
737 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
738 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
739 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
740};
741
Vishnu Naire97d6122018-01-18 13:58:56 -0800742status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
743 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700744 if (!IsZipping()) {
745 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
746 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800747 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800748 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700749 std::string valid_name = entry_name;
750
751 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700752 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700753 if (idx != std::string::npos) {
754 std::string extension = entry_name.substr(idx);
755 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
756 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
757 valid_name = entry_name + ".renamed";
758 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
759 }
760 }
761
Felipe Leme6fe9db62016-02-12 09:04:16 -0800762 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
763 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700764 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
765 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700766 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700767 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700768 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800769 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800770 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000771 bool finished_entry = false;
772 auto finish_entry = [this, &finished_entry] {
773 if (!finished_entry) {
774 // This should only be called when we're going to return an earlier error,
775 // which would've been logged. This may imply the file is already corrupt
776 // and any further logging from FinishEntry is more likely to mislead than
777 // not.
778 this->zip_writer_->FinishEntry();
779 }
780 };
781 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800782 auto start = std::chrono::steady_clock::now();
783 auto end = start + timeout;
784 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800785
Felipe Leme770410d2016-01-26 17:07:14 -0800786 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800787 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800788 if (timeout.count() > 0) {
789 // lambda to recalculate the timeout.
790 auto time_left_ms = [end]() {
791 auto now = std::chrono::steady_clock::now();
792 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
793 return std::max(diff.count(), 0LL);
794 };
795
796 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
797 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000798 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
799 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800800 return -errno;
801 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000802 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800803 entry_name.c_str(), strerror(errno), timeout.count());
804 return TIMED_OUT;
805 }
806 }
807
Zach Riggle22200402016-08-18 01:01:24 -0400808 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800809 if (bytes_read == 0) {
810 break;
811 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800812 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800813 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800814 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700815 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800816 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700817 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800818 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800819 }
820 }
821
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700822 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000823 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700824 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700825 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800826 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800827 }
828
Vishnu Naire97d6122018-01-18 13:58:56 -0800829 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800830}
831
Felipe Leme1d486fe2016-10-14 18:06:47 -0700832bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
833 android::base::unique_fd fd(
834 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700835 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800836 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800837 return false;
838 }
839
Vishnu Naire97d6122018-01-18 13:58:56 -0800840 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800841}
842
843/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700844static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800845 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800846}
847
Felipe Leme1d486fe2016-10-14 18:06:47 -0700848void Dumpstate::AddDir(const std::string& dir, bool recursive) {
849 if (!IsZipping()) {
850 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800851 return;
852 }
Felipe Leme678727a2016-09-21 17:22:11 -0700853 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800854 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700855 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800856}
857
Felipe Leme1d486fe2016-10-14 18:06:47 -0700858bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
859 if (!IsZipping()) {
860 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
861 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800862 return false;
863 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800864 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700865 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700866 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700867 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800869 return false;
870 }
871
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700872 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700873 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700874 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700875 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800876 return false;
877 }
878
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700879 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700880 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700881 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800882 return false;
883 }
884
885 return true;
886}
887
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800888static void DoKmsg() {
889 struct stat st;
890 if (!stat(PSTORE_LAST_KMSG, &st)) {
891 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
892 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
893 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
894 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
895 } else {
896 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
897 DumpFile("LAST KMSG", "/proc/last_kmsg");
898 }
899}
900
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800901static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800902 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800903 RunCommand(
904 "KERNEL LOG",
905 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
906 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
907}
908
Nandana Duttdb379fa2019-10-09 16:54:41 +0100909static void DoSystemLogcat(time_t since) {
910 char since_str[80];
911 strftime(since_str, sizeof(since_str), "%Y-%m-%d %H:%M:%S.000", localtime(&since));
912
913 unsigned long timeout_ms = logcat_timeout({"main", "system", "crash"});
914 RunCommand("SYSTEM LOG",
915 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v", "-T",
916 since_str},
917 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
918}
919
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800920static void DoRadioLogcat() {
921 unsigned long timeout_ms = logcat_timeout({"radio"});
922 RunCommand(
923 "RADIO LOG",
924 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
925 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
926}
927
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800928static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800929 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800930 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
931 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800932 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100933 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800934 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
935 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800936 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800937 RunCommand(
938 "EVENT LOG",
939 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +0100940 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Yao Chenbe3bbc12018-01-17 16:31:10 -0800941 timeout_ms = logcat_timeout({"stats"});
942 RunCommand(
943 "STATS LOG",
944 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
Nandana Dutt8d945c02019-08-14 13:30:07 +0100945 CommandOptions::WithTimeoutInMs(timeout_ms).Build(), true /* verbose_duration */);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800946 DoRadioLogcat();
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800947
948 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
949
950 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800951 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
952 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800953}
954
Mike Ma5c267872019-08-21 11:31:34 -0700955static void DumpIncidentReport() {
956 if (!ds.IsZipping()) {
957 MYLOGD("Not dumping incident report because it's not a zipped bugreport\n");
958 return;
959 }
960 DurationReporter duration_reporter("INCIDENT REPORT");
961 const std::string path = ds.bugreport_internal_dir_ + "/tmp_incident_report";
962 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
963 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
964 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
965 if (fd < 0) {
966 MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
967 return;
968 }
969 RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
970 bool empty = 0 == lseek(fd, 0, SEEK_END);
971 if (!empty) {
972 // Use a different name from "incident.proto"
973 // /proto/incident.proto is reserved for incident service dump
974 // i.e. metadata for debugging.
975 ds.AddZipEntry(kProtoPath + "incident_report" + kProtoExt, path);
976 }
977 unlink(path.c_str());
978}
979
Sunny Goyal35949782019-11-19 15:54:36 -0800980static void DumpVisibleWindowViews() {
981 if (!ds.IsZipping()) {
982 MYLOGD("Not dumping visible views because it's not a zipped bugreport\n");
983 return;
984 }
985 DurationReporter duration_reporter("VISIBLE WINDOW VIEWS");
986 const std::string path = ds.bugreport_internal_dir_ + "/tmp_visible_window_views";
987 auto fd = android::base::unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(),
988 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
989 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
990 if (fd < 0) {
991 MYLOGE("Could not open %s to dump visible views.\n", path.c_str());
992 return;
993 }
994 RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
995 CommandOptions::WithTimeout(120).Build());
996 bool empty = 0 == lseek(fd, 0, SEEK_END);
997 if (!empty) {
998 ds.AddZipEntry("visible_windows.zip", path);
999 } else {
1000 MYLOGW("Failed to dump visible windows\n");
1001 }
1002 unlink(path.c_str());
1003}
1004
Jayachandran Ca94c7172017-06-10 15:08:12 -07001005static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001006 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
1007 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +09001008 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001009 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +09001010 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1011 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1012 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1013 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001014}
1015
David Andersond9ba4752018-12-11 18:26:59 -08001016static void DumpDynamicPartitionInfo() {
1017 if (!::android::base::GetBoolProperty("ro.boot.dynamic_partitions", false)) {
1018 return;
1019 }
1020
1021 RunCommand("LPDUMP", {"lpdump", "--all"});
David Anderson6650ade2019-10-02 15:18:59 -07001022 RunCommand("DEVICE-MAPPER", {"gsid", "dump-device-mapper"});
David Andersond9ba4752018-12-11 18:26:59 -08001023}
1024
Narayan Kamath8f788292017-05-25 13:20:39 +01001025static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1026 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1027 anr_traces_dir.c_str());
1028
1029 // If we're here, dump_traces_path will always be a temporary file
1030 // (created with mkostemp or similar) that contains dumps taken earlier
1031 // on in the process.
1032 if (dump_traces_path != nullptr) {
1033 if (add_to_zip) {
1034 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1035 } else {
1036 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1037 dump_traces_path);
1038 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1039 }
1040
1041 const int ret = unlink(dump_traces_path);
1042 if (ret == -1) {
1043 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1044 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001045 }
1046 }
1047
Narayan Kamathbd863722017-06-01 18:50:12 +01001048 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001049 if (ds.anr_data_.size() > 0) {
1050 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001051 "VM TRACES AT LAST ANR", add_to_zip);
1052
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001053 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1054 // it will be present in the body of the main entry if |add_to_zip| == false.
1055 //
1056 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001057 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001058 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001059 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001060 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1061 }
1062}
1063
1064static void AddAnrTraceFiles() {
1065 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1066
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001067 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001068
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001069 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001070
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001071 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1072
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001073 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001074 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001075 int i = 0;
1076 while (true) {
1077 const std::string slow_trace_path =
1078 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1079 if (stat(slow_trace_path.c_str(), &st)) {
1080 // No traces file at this index, done with the files.
1081 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001082 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001083 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1084 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001085 }
1086}
1087
Wei Wang509bb5d2017-06-09 14:42:12 -07001088static void DumpBlockStatFiles() {
1089 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001090
Wei Wang1dc1ef52017-06-12 11:28:37 -07001091 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1092
1093 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001094 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1095 return;
1096 }
1097
1098 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001099 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001100 if ((d->d_name[0] == '.')
1101 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1102 || (d->d_name[1] == '\0'))) {
1103 continue;
1104 }
1105 const std::string new_path =
1106 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1107 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1108 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1109 printf("\n");
1110 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001111 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001112}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001113
1114static void DumpPacketStats() {
1115 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1116 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1117 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1118 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1119 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1120}
1121
1122static void DumpIpAddrAndRules() {
1123 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1124 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1125 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1126 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1127 RunCommand("IP RULES", {"ip", "rule", "show"});
1128 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1129}
1130
Nandana Dutt5c390032019-03-12 10:52:56 +00001131static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1132 std::chrono::milliseconds timeout,
1133 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001134 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001135 sp<android::IServiceManager> sm = defaultServiceManager();
1136 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001137 Vector<String16> args;
1138 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001139 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1140 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001141 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001142 std::string path(title);
1143 path.append(" - ").append(String8(service).c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -08001144 size_t bytes_written = 0;
Steven Moreland5a30d342019-10-08 13:53:28 -07001145 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001146 if (status == OK) {
1147 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1148 std::chrono::duration<double> elapsed_seconds;
1149 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1150 /* as_proto = */ false, elapsed_seconds, bytes_written);
Vishnu Naire97d6122018-01-18 13:58:56 -08001151 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1152 bool dump_complete = (status == OK);
1153 dumpsys.stopDumpThread(dump_complete);
1154 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001155
1156 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1157 std::chrono::steady_clock::now() - start);
1158 if (elapsed_duration > timeout) {
1159 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1160 elapsed_duration.count());
1161 break;
1162 }
1163 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001164 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001165}
1166
Vishnu Nair64afc022018-02-01 15:29:34 -08001167static void RunDumpsysText(const std::string& title, int priority,
1168 std::chrono::milliseconds timeout,
1169 std::chrono::milliseconds service_timeout) {
1170 DurationReporter duration_reporter(title);
1171 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1172 fsync(STDOUT_FILENO);
1173 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1174}
1175
1176/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001177static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1178 std::chrono::milliseconds timeout,
1179 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001180 DurationReporter duration_reporter(title);
1181 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1182 fsync(STDOUT_FILENO);
1183 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1184 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001185
1186 RETURN_IF_USER_DENIED_CONSENT();
1187
1188 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1189 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001190}
1191
Nandana Dutt5c390032019-03-12 10:52:56 +00001192static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1193 std::chrono::milliseconds timeout,
1194 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001195 if (!ds.IsZipping()) {
1196 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001197 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001198 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001199 sp<android::IServiceManager> sm = defaultServiceManager();
1200 Dumpsys dumpsys(sm.get());
1201 Vector<String16> args;
1202 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1203 DurationReporter duration_reporter(title);
1204
1205 auto start = std::chrono::steady_clock::now();
1206 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1207 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001208 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001209 std::string path(kProtoPath);
1210 path.append(String8(service).c_str());
1211 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1212 path.append("_CRITICAL");
1213 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1214 path.append("_HIGH");
1215 }
1216 path.append(kProtoExt);
Steven Moreland5a30d342019-10-08 13:53:28 -07001217 status_t status = dumpsys.startDumpThread(Dumpsys::Type::DUMP, service, args);
Vishnu Naire97d6122018-01-18 13:58:56 -08001218 if (status == OK) {
1219 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1220 bool dumpTerminated = (status == OK);
1221 dumpsys.stopDumpThread(dumpTerminated);
1222 }
1223 ZipWriter::FileEntry file_entry;
1224 ds.zip_writer_->GetLastEntry(&file_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -08001225
1226 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1227 std::chrono::steady_clock::now() - start);
1228 if (elapsed_duration > timeout) {
1229 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1230 elapsed_duration.count());
1231 break;
1232 }
1233 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001234 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001235}
1236
Nandana Dutta7db6342018-11-21 14:53:34 +00001237// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001238static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001239 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1240 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001241
1242 RETURN_IF_USER_DENIED_CONSENT();
1243
1244 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1245 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001246}
1247
1248// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001249static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001250 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1251 // high priority. Reduce timeout once they are able to dump in a shorter time or
1252 // moved to a parallel task.
1253 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1254 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001255
1256 RETURN_IF_USER_DENIED_CONSENT();
1257
1258 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1259 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001260}
1261
1262// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001263static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001264 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001265
1266 RETURN_IF_USER_DENIED_CONSENT();
1267
1268 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1269 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001270}
1271
Steven Moreland44cd9482018-01-04 16:24:13 -08001272static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001273 if (!ds.IsZipping()) {
1274 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1275 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1276 return;
1277 }
1278 DurationReporter duration_reporter("DUMP HALS");
1279 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
Greg Kaiser3dfeda32019-05-16 10:32:51 -07001280 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001281
Steven Moreland44cd9482018-01-04 16:24:13 -08001282 using android::hidl::manager::V1_0::IServiceManager;
1283 using android::hardware::defaultServiceManager;
1284
1285 sp<IServiceManager> sm = defaultServiceManager();
1286 if (sm == nullptr) {
1287 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1288 return;
1289 }
1290
1291 auto ret = sm->list([&](const auto& interfaces) {
1292 for (const std::string& interface : interfaces) {
1293 std::string cleanName = interface;
1294 std::replace_if(cleanName.begin(),
1295 cleanName.end(),
1296 [](char c) {
1297 return !isalnum(c) &&
1298 std::string("@-_:.").find(c) == std::string::npos;
1299 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001300 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001301
1302 {
1303 auto fd = android::base::unique_fd(
1304 TEMP_FAILURE_RETRY(open(path.c_str(),
1305 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1306 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1307 if (fd < 0) {
1308 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1309 continue;
1310 }
1311 RunCommandToFd(fd,
1312 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001313 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001314 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1315
1316 bool empty = 0 == lseek(fd, 0, SEEK_END);
1317 if (!empty) {
1318 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1319 }
1320 }
1321
1322 unlink(path.c_str());
1323 }
1324 });
1325
1326 if (!ret.isOk()) {
1327 MYLOGE("Could not list hals from hwservicemanager.\n");
1328 }
1329}
1330
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001331static void DumpExternalFragmentationInfo() {
1332 struct stat st;
1333 if (stat("/proc/buddyinfo", &st) != 0) {
1334 MYLOGE("Unable to dump external fragmentation info\n");
1335 return;
1336 }
1337
1338 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1339 std::ifstream ifs("/proc/buddyinfo");
1340 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1341 for (std::string line; std::getline(ifs, line);) {
1342 std::smatch match_results;
1343 if (std::regex_match(line, match_results, unusable_index_regex)) {
1344 std::stringstream free_pages(std::string{match_results[3]});
1345 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1346 std::istream_iterator<int>());
1347
1348 int total_free_pages = 0;
1349 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1350 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1351 }
1352
1353 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1354 match_results[2].str().c_str());
1355
1356 int usable_free_pages = total_free_pages;
1357 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1358 auto unusable_index = (total_free_pages - usable_free_pages) /
1359 static_cast<double>(total_free_pages);
1360 printf(" %5.3f", unusable_index);
1361 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1362 }
1363
1364 printf("\n");
1365 }
1366 }
1367 printf("\n");
1368}
1369
mhasankf56bbb22020-05-26 18:02:39 -07001370static void DumpstateArcOnly() {
1371 // Trimmed-down version of dumpstate to only include a whitelisted
1372 // set of logs (system log, event log, and system server / system app
1373 // crashes, and ARC networking logs). See b/136273873 and b/138459828
1374 // for context. New sections must be first approved by Chrome OS Privacy
1375 // and then added to server side cros monitoring PII scrubber before adding
1376 // them here. See cl/312126645 for an example.
1377 DurationReporter duration_reporter("DUMPSTATE");
1378 unsigned long timeout_ms;
1379 // calculate timeout
1380 timeout_ms = logcat_timeout({"main", "system", "crash"});
1381 RunCommand("SYSTEM LOG",
1382 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1383 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1384 timeout_ms = logcat_timeout({"events"});
1385 RunCommand(
1386 "EVENT LOG",
1387 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1388 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1389
1390 printf("========================================================\n");
1391 printf("== Networking Service\n");
1392 printf("========================================================\n");
1393
1394 // ARC networking service implements dumpsys by reusing the 'wifi' service name.
1395 // The top-level handler is implemented in handleDump() in
1396 // vendor/google_arc/libs/arc-services/src/com/android/server/arc/net/ArcNetworkService.java.
1397 // It outputs a subset of Android system server state relevant for debugging ARC
1398 // connectivity issues, in a PII-free manner. See b/147270970.
1399 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1400 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1401
1402 printf("========================================================\n");
1403 printf("== Dropbox crashes\n");
1404 printf("========================================================\n");
1405
1406 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1407 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1408
1409 printf("========================================================\n");
1410 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1411 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1412 printf("========================================================\n");
1413 printf("== dumpstate: done (id %d)\n", ds.id_);
1414 printf("========================================================\n");
1415}
1416
Nandana Dutt5c390032019-03-12 10:52:56 +00001417// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1418// via the consent they are shown. Ignores other errors that occur while running various
1419// commands. The consent checking is currently done around long running tasks, which happen to
1420// be distributed fairly evenly throughout the function.
1421static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001422 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001423
Nandana Dutt5c390032019-03-12 10:52:56 +00001424 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1425 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1426 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001427 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001428 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001429 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001430 DumpFile("MEMORY INFO", "/proc/meminfo");
1431 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001432 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001433
1434 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1435
Sunny Goyal35949782019-11-19 15:54:36 -08001436 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1437
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001438 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1439 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1440 DumpFile("SLAB INFO", "/proc/slabinfo");
1441 DumpFile("ZONEINFO", "/proc/zoneinfo");
1442 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1443 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001444 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001445
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001446 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1447 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001448
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001449 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001450 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001451
1452 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1453 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001454
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001455 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001456
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001457 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001458 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001459 struct stat s;
1460 if (stat("/proc/modules", &s) != 0) {
1461 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1462 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001463 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001464 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001465
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001466 if (__android_logger_property_get_bool(
1467 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1468 DoKernelLogcat();
1469 } else {
1470 do_dmesg();
1471 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001472
Felipe Lemef0292972016-11-22 13:57:05 -08001473 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001474
1475 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1476
Jeff Brown1dc94e32014-09-11 14:15:27 -07001477 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001478 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001479
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001480 /* Dump Bluetooth HCI logs */
1481 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001482
Paul Chang0d2aad72020-02-13 20:04:03 +08001483 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001484 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001485 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001486 }
1487
Felipe Lemee184f662016-10-27 10:04:47 -07001488 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001489
Narayan Kamath8f788292017-05-25 13:20:39 +01001490 // NOTE: tombstones are always added as separate entries in the zip archive
1491 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001492 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001493 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001494 if (!tombstones_dumped) {
1495 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001496 }
1497
Jayachandran Ca94c7172017-06-10 15:08:12 -07001498 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001499
Chenbo Feng276a3b62018-08-07 11:44:49 -07001500 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1501
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001502 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001503
Jayachandran Ca94c7172017-06-10 15:08:12 -07001504 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001505
1506 dump_route_tables();
1507
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001508 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1509 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1510 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001511
Nandana Dutt5c390032019-03-12 10:52:56 +00001512 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001513
Elliott Hughes23ccc622017-02-28 10:14:22 -08001514 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001515
Jin Qianf334d662017-10-10 14:41:37 -07001516 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001517
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001518 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001519
Colin Crossf45fa6b2012-03-26 12:38:26 -07001520 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001521 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1522 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1523
1524 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1525 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1526 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1527 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1528 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001529
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001530 /* Add window and surface trace files. */
1531 if (!PropertiesHelper::IsUserBuild()) {
1532 ds.AddDir(WMTRACE_DATA_DIR, false);
1533 }
1534
Yifan Hongd90cc652020-02-08 16:52:02 -08001535 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1536
Nandana Dutt5c390032019-03-12 10:52:56 +00001537 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001538
Steven Moreland7440ddb2016-12-15 16:13:39 -08001539 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001540 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1541 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001542 // su does not exist on user builds, so try running without it.
1543 // This way any implementations of vril-dump that do not require
1544 // root can run on user builds.
1545 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001546 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001547 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001548 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001549 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001550 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001551 }
1552
Felipe Lemed8b94e52016-12-08 10:21:44 -08001553 printf("========================================================\n");
1554 printf("== Android Framework Services\n");
1555 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001556
Nandana Dutt5c390032019-03-12 10:52:56 +00001557 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001558
Felipe Lemed8b94e52016-12-08 10:21:44 -08001559 printf("========================================================\n");
1560 printf("== Checkins\n");
1561 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001562
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001563 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001564
1565 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1566
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001567 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1568 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1569 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1570 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001571
Felipe Lemed8b94e52016-12-08 10:21:44 -08001572 printf("========================================================\n");
1573 printf("== Running Application Activities\n");
1574 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001575
Makoto Onuki60780982018-04-16 15:34:00 -07001576 // The following dumpsys internally collects output from running apps, so it can take a long
1577 // time. So let's extend the timeout.
1578
1579 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1580
1581 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001582
Felipe Lemed8b94e52016-12-08 10:21:44 -08001583 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001584 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001585 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001586
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001587 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001588 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001589
Felipe Lemed8b94e52016-12-08 10:21:44 -08001590 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001591 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001592 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001593
Makoto Onuki60780982018-04-16 15:34:00 -07001594 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1595 DUMPSYS_COMPONENTS_OPTIONS);
1596
1597 printf("========================================================\n");
1598 printf("== Running Application Providers (platform)\n");
1599 printf("========================================================\n");
1600
1601 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1602 DUMPSYS_COMPONENTS_OPTIONS);
1603
1604 printf("========================================================\n");
1605 printf("== Running Application Providers (non-platform)\n");
1606 printf("========================================================\n");
1607
1608 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1609 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001610
Adrian Roos8b397ab2017-04-04 16:35:44 -07001611 printf("========================================================\n");
1612 printf("== Dropbox crashes\n");
1613 printf("========================================================\n");
1614
1615 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1616 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1617
Felipe Lemed8b94e52016-12-08 10:21:44 -08001618 printf("========================================================\n");
1619 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1620 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1621 printf("========================================================\n");
1622 printf("== dumpstate: done (id %d)\n", ds.id_);
1623 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001624
1625 printf("========================================================\n");
1626 printf("== Obtaining statsd metadata\n");
1627 printf("========================================================\n");
1628 // This differs from the usual dumpsys stats, which is the stats report data.
1629 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001630
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001631 // Add linker configuration directory
1632 ds.AddDir(LINKERCONFIG_DIR, true);
1633
Mike Ma5c267872019-08-21 11:31:34 -07001634 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
1635
Nandana Dutt5c390032019-03-12 10:52:56 +00001636 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001637}
1638
Nandana Dutt5c390032019-03-12 10:52:56 +00001639/*
1640 * Dumps state for the default case; drops root after it's no longer necessary.
1641 *
1642 * Returns RunStatus::OK if everything went fine.
1643 * Returns RunStatus::ERROR if there was an error.
1644 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1645 * with the caller.
1646 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001647Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001648 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1649 // buffer.
1650 DoLogcat();
1651 // Capture timestamp after first logcat to use in next logcat
1652 time_t logcat_ts = time(nullptr);
1653
Nandana Dutt4be45d12018-09-26 15:04:23 +01001654 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001655 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001656
1657 /* Run some operations that require root. */
1658 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1659 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1660
1661 ds.AddDir(RECOVERY_DIR, true);
1662 ds.AddDir(RECOVERY_DATA_DIR, true);
1663 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1664 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1665 if (!PropertiesHelper::IsUserBuild()) {
1666 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1667 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001668 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001669 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001670 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001671 add_mountinfo();
1672 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001673 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001674 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001675
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001676 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001677 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1678
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001679 // Dump IPsec stats. No keys are exposed here.
1680 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1681
Nandana Dutt4be45d12018-09-26 15:04:23 +01001682 // Run ss as root so we can see socket marks.
1683 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1684
1685 // Run iotop as root to show top 100 IO threads
1686 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1687
Erick Reyese68df822019-02-11 14:46:36 -08001688 // Gather shared memory buffer info if the product implements it
1689 struct stat st;
1690 if (!stat("/product/bin/dmabuf_dump", &st)) {
1691 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1692 }
1693
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001694 DumpFile("PSI cpu", "/proc/pressure/cpu");
1695 DumpFile("PSI memory", "/proc/pressure/memory");
1696 DumpFile("PSI io", "/proc/pressure/io");
1697
Nandana Dutt4be45d12018-09-26 15:04:23 +01001698 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001699 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001700 }
1701
Nandana Dutt5c390032019-03-12 10:52:56 +00001702 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001703 Dumpstate::RunStatus status = dumpstate();
1704 // Capture logcat since the last time we did it.
1705 DoSystemLogcat(logcat_ts);
1706 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001707}
1708
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001709// This method collects common dumpsys for telephony and wifi. Typically, wifi
1710// reports are fine to include all information, but telephony reports on user
1711// builds need to strip some content (see DumpstateTelephonyOnly).
1712static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001713 DumpIpTablesAsRoot();
1714
Jayachandran Cb4389d92019-07-08 09:46:05 -07001715 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1716
Jayachandran Ca94c7172017-06-10 15:08:12 -07001717 if (!DropRootUser()) {
1718 return;
1719 }
1720
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001721 // We need to be picky about some stuff for telephony reports on user builds.
1722 if (!include_sensitive_info) {
1723 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1724 DoRadioLogcat();
1725 } else {
1726 // Contains various system properties and process startup info.
1727 do_dmesg();
1728 // Logs other than the radio buffer may contain package/component names and potential PII.
1729 DoLogcat();
1730 // Too broad for connectivity problems.
1731 DoKmsg();
1732 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
1733 DumpHals();
1734 }
1735
Jayachandran Ca94c7172017-06-10 15:08:12 -07001736 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001737 DumpIpAddrAndRules();
1738 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001739 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1740 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001741}
1742
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001743// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1744// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1745// for what can be included on user builds: all reported information MUST directly relate to
1746// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1747// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1748// names are not), and MUST NOT contain logs of user application traffic.
1749// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001750static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001751 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001752
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001753 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001754
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001755 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001756
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001757 DumpstateRadioCommon(include_sensitive_info);
1758
1759 if (include_sensitive_info) {
1760 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1761 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1762 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1763 // way.
1764 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1765 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001766
1767 printf("========================================================\n");
1768 printf("== Android Framework Services\n");
1769 printf("========================================================\n");
1770
Vishnu Nair652cc802017-11-30 15:18:30 -08001771 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1772 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001773 if (include_sensitive_info) {
1774 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1775 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1776 SEC_TO_MSEC(10));
1777 } else {
1778 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1779 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1780 // give a higher timeout as well.
1781 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1782 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1783 }
1784 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001785 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1786 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001787 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001788 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1789 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001790 if (include_sensitive_info) {
1791 // Contains raw IP addresses, omit from reports on user builds.
1792 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1793 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1794 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1795 SEC_TO_MSEC(10));
1796 // Contains package/component names, omit from reports on user builds.
1797 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1798 SEC_TO_MSEC(10));
1799 // Contains package names, but should be relatively simple to remove them (also contains
1800 // UIDs already), omit from reports on user builds.
1801 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1802 SEC_TO_MSEC(10));
1803 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001804
1805 printf("========================================================\n");
1806 printf("== Running Application Services\n");
1807 printf("========================================================\n");
1808
1809 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1810
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001811 if (include_sensitive_info) {
1812 printf("========================================================\n");
1813 printf("== Running Application Services (non-platform)\n");
1814 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001815
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001816 // Contains package/component names and potential PII, omit from reports on user builds.
1817 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1818 // carrier_config dumpsys instead.
1819 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1820 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001821
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001822 printf("========================================================\n");
1823 printf("== Checkins\n");
1824 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001825
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001826 // Contains package/component names, omit from reports on user builds.
1827 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1828 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001829
1830 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001831 printf("== dumpstate: done (id %d)\n", ds.id_);
1832 printf("========================================================\n");
1833}
1834
mukesh agrawal253dad42018-01-23 21:59:59 -08001835// This method collects dumpsys for wifi debugging only
1836static void DumpstateWifiOnly() {
1837 DurationReporter duration_reporter("DUMPSTATE");
1838
1839 DumpstateRadioCommon();
1840
1841 printf("========================================================\n");
1842 printf("== Android Framework Services\n");
1843 printf("========================================================\n");
1844
1845 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1846 SEC_TO_MSEC(10));
1847 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1848 SEC_TO_MSEC(10));
1849
1850 printf("========================================================\n");
1851 printf("== dumpstate: done (id %d)\n", ds.id_);
1852 printf("========================================================\n");
1853}
1854
Nandana Duttcf419a72019-03-14 10:40:17 +00001855Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001856 DurationReporter duration_reporter("DUMP TRACES");
1857
1858 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1859 const size_t buf_size = temp_file_pattern.length() + 1;
1860 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1861 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1862
1863 // Create a new, empty file to receive all trace dumps.
1864 //
1865 // TODO: This can be simplified once we remove support for the old style
1866 // dumps. We can have a file descriptor passed in to dump_traces instead
1867 // of creating a file, closing it and then reopening it again.
1868 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1869 if (fd < 0) {
1870 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001871 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001872 }
1873
1874 // Nobody should have access to this temporary file except dumpstate, but we
1875 // temporarily grant 'read' to 'others' here because this file is created
1876 // when tombstoned is still running as root, but dumped after dropping. This
1877 // can go away once support for old style dumping has.
1878 const int chmod_ret = fchmod(fd, 0666);
1879 if (chmod_ret < 0) {
1880 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001881 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001882 }
1883
1884 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1885 if (proc.get() == nullptr) {
1886 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001887 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001888 }
1889
1890 // Number of times process dumping has timed out. If we encounter too many
1891 // failures, we'll give up.
1892 int timeout_failures = 0;
1893 bool dalvik_found = false;
1894
1895 const std::set<int> hal_pids = get_interesting_hal_pids();
1896
1897 struct dirent* d;
1898 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001899 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001900 int pid = atoi(d->d_name);
1901 if (pid <= 0) {
1902 continue;
1903 }
1904
1905 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1906 std::string exe;
1907 if (!android::base::Readlink(link_name, &exe)) {
1908 continue;
1909 }
1910
1911 bool is_java_process;
1912 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1913 // Don't bother dumping backtraces for the zygote.
1914 if (IsZygote(pid)) {
1915 continue;
1916 }
1917
1918 dalvik_found = true;
1919 is_java_process = true;
1920 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1921 is_java_process = false;
1922 } else {
1923 // Probably a native process we don't care about, continue.
1924 continue;
1925 }
1926
1927 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1928 if (timeout_failures == 3) {
1929 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1930 break;
1931 }
1932
1933 const uint64_t start = Nanotime();
1934 const int ret = dump_backtrace_to_file_timeout(
1935 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1936 is_java_process ? 5 : 20, fd);
1937
1938 if (ret == -1) {
1939 // For consistency, the header and footer to this message match those
1940 // dumped by debuggerd in the success case.
1941 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1942 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1943 dprintf(fd, "---- end %d ----", pid);
1944 timeout_failures++;
1945 continue;
1946 }
1947
1948 // We've successfully dumped stack traces, reset the failure count
1949 // and write a summary of the elapsed time to the file and continue with the
1950 // next process.
1951 timeout_failures = 0;
1952
1953 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1954 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1955 }
1956
1957 if (!dalvik_found) {
1958 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1959 }
1960
Nandana Duttcf419a72019-03-14 10:40:17 +00001961 *path = file_name_buf.release();
1962 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001963}
1964
Felipe Leme6f674ae2016-11-18 17:10:33 -08001965void Dumpstate::DumpstateBoard() {
1966 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001967 printf("========================================================\n");
1968 printf("== Board\n");
1969 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001970
Felipe Leme6f674ae2016-11-18 17:10:33 -08001971 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001972 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001973 return;
1974 }
1975
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001976 std::vector<std::string> paths;
1977 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001978 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001979 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1980 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001981 remover.emplace_back(android::base::make_scope_guard(
1982 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001983 }
Jie Song9fbfad02017-06-20 16:29:42 -07001984
Hunter Knepshield8540faf2020-02-04 19:47:20 -08001985 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
1986 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07001987 MYLOGE("No IDumpstateDevice implementation\n");
1988 return;
1989 }
1990
1991 using ScopedNativeHandle =
1992 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1993 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1994 [](native_handle_t* handle) {
1995 native_handle_close(handle);
1996 native_handle_delete(handle);
1997 });
1998 if (handle == nullptr) {
1999 MYLOGE("Could not create native_handle\n");
2000 return;
2001 }
2002
Nandana Dutt5c390032019-03-12 10:52:56 +00002003 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07002004 for (size_t i = 0; i < paths.size(); i++) {
2005 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
2006
2007 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2008 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2009 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2010 if (fd < 0) {
2011 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2012 return;
2013 }
2014 handle.get()->data[i] = fd.release();
2015 }
2016
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002017 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2018 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2019 // will kill the HAL and grab whatever it dumped in time.
2020 constexpr size_t timeout_sec = 30;
2021 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2022 // implement just 1.0.
2023 const char* descriptor_to_kill;
2024 using DumpstateBoardTask = std::packaged_task<bool()>;
2025 DumpstateBoardTask dumpstate_board_task;
2026 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2027 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2028 if (dumpstate_device_1_1 != nullptr) {
2029 MYLOGI("Using IDumpstateDevice v1.1");
2030 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2031 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2032 ::android::hardware::Return<DumpstateStatus> status =
2033 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2034 SEC_TO_MSEC(timeout_sec));
2035 if (!status.isOk()) {
2036 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2037 return false;
2038 } else if (status != DumpstateStatus::OK) {
2039 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2040 return false;
2041 }
2042 return true;
2043 });
2044 } else {
2045 MYLOGI("Using IDumpstateDevice v1.0");
2046 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2047 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2048 ::android::hardware::Return<void> status =
2049 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002050 if (!status.isOk()) {
2051 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002052 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002053 }
Wei Wang587eac92018-04-05 12:17:20 -07002054 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002055 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002056 }
2057 auto result = dumpstate_board_task.get_future();
2058 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002059
Wei Wang587eac92018-04-05 12:17:20 -07002060 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2061 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002062 if (!android::base::SetProperty(
2063 "ctl.interface_restart",
2064 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002065 MYLOGE("Couldn't restart dumpstate HAL\n");
2066 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002067 }
Wei Wang587eac92018-04-05 12:17:20 -07002068 // Wait some time for init to kill dumpstate vendor HAL
2069 constexpr size_t killing_timeout_sec = 10;
2070 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2071 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2072 "there might be racing in content\n", killing_timeout_sec);
2073 }
2074
2075 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2076 for (size_t i = 0; i < paths.size(); i++) {
2077 struct stat s;
2078 if (fstat(handle.get()->data[i], &s) == -1) {
2079 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2080 strerror(errno));
2081 file_sizes[i] = -1;
2082 continue;
2083 }
2084 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002085 }
2086
2087 for (size_t i = 0; i < paths.size(); i++) {
2088 if (file_sizes[i] == -1) {
2089 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002090 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002091 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002092 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002093 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002094 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002095 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002096 printf("*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002097 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002098}
2099
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002100static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002101 fprintf(stderr,
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002102 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
mhasankf56bbb22020-05-26 18:02:39 -07002103 "[-z] [-s] [-S] [-q] [-P] [-R] [-A] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002104 " -h: display this help message\n"
2105 " -b: play sound file instead of vibrate, at beginning of job\n"
2106 " -e: play sound file instead of vibrate, at end of job\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002107 " -d: append date to filename\n"
2108 " -p: capture screenshot to filename.png\n"
2109 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002110 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002111 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002112 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002113 " -P: send broadcast when started and do progress updates\n"
2114 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002115 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankf56bbb22020-05-26 18:02:39 -07002116 " -A: output limited information that is safe for submission in ARC++ bugreports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002117 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002118}
2119
Wei Liuf87959e2016-08-26 14:51:42 -07002120static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002121 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002122}
2123
Felipe Leme1d486fe2016-10-14 18:06:47 -07002124bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002125 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002126 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002127 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002128 // Final timestamp
2129 char date[80];
2130 time_t the_real_now_please_stand_up = time(nullptr);
2131 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002132 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002133 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002134
Felipe Leme9a523ae2016-10-20 15:10:33 -07002135 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002136 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002137 return false;
2138 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002139 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002140 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002141 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002142 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002143
Felipe Leme0f3fb202016-06-10 17:10:53 -07002144 // Add log file (which contains stderr output) to zip...
2145 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002146 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002147 MYLOGE("Failed to add dumpstate log to .zip file\n");
2148 return false;
2149 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002150 // TODO: Should truncate the existing file.
2151 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002152 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2153 return false;
2154 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002155 fprintf(stderr, "\n");
2156
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002157 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002158 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002159 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002160 return false;
2161 }
2162
Felipe Leme1d486fe2016-10-14 18:06:47 -07002163 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2164 ds.zip_file.reset(nullptr);
2165
Felipe Lemee9d2c542016-11-15 11:48:26 -08002166 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002167 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002168
Felipe Leme1e9edc62015-12-21 16:02:13 -08002169 return true;
2170}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002171
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002172static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2173 // clang-format off
2174 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2175 "--receiver-foreground", "--receiver-include-background", "-a", action};
2176 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002177
2178 am.insert(am.end(), args.begin(), args.end());
2179
Felipe Leme8d2410e2017-02-08 09:46:08 -08002180 RunCommand("", am,
2181 CommandOptions::WithTimeout(20)
2182 .Log("Sending broadcast: '%s'\n")
2183 .Always()
2184 .DropRoot()
2185 .RedirectStderr()
2186 .Build());
2187}
2188
Felipe Leme35b8cf12017-02-10 15:47:29 -08002189static void Vibrate(int duration_ms) {
2190 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002191 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002192 CommandOptions::WithTimeout(10)
2193 .Log("Vibrate: '%s'\n")
2194 .Always()
2195 .Build());
2196 // clang-format on
2197}
2198
Nandana Dutt979388e2018-11-30 16:48:55 +00002199static void MaybeResolveSymlink(std::string* path) {
2200 std::string resolved_path;
2201 if (android::base::Readlink(*path, &resolved_path)) {
2202 *path = resolved_path;
2203 }
2204}
2205
Nandana Dutt4be45d12018-09-26 15:04:23 +01002206/*
2207 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2208 * if we are writing zip files and adds the version file.
2209 */
2210static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002211 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2212
Nandana Dutt4be45d12018-09-26 15:04:23 +01002213 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2214 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002215 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002216 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002217 char date[80];
2218 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2219 ds.name_ = date;
2220 } else {
2221 ds.name_ = "undated";
2222 }
2223
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002224 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002225 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002226 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002227 ds.base_name_ += "-wifi";
2228 }
2229
Paul Chang0d2aad72020-02-13 20:04:03 +08002230 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002231 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002232 }
2233 ds.tmp_path_ = ds.GetPath(".tmp");
2234 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2235
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002236 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002237 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002238 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002239 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002240 "Bugreport dir: [%s] "
2241 "Base name: [%s] "
2242 "Suffix: [%s] "
2243 "Log path: [%s] "
2244 "Temporary path: [%s] "
2245 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002246 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2247 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002248
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002249 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002250 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002251 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2252 create_parent_dirs(ds.path_.c_str());
2253 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2254 if (ds.zip_file == nullptr) {
2255 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2256 } else {
2257 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2258 }
2259 ds.AddTextZipEntry("version.txt", ds.version_);
2260 }
2261}
2262
2263/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002264 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002265 * printing zipped file status, etc.
2266 */
2267static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002268 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002269 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002270 if (!ds.FinishZipFile()) {
2271 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2272 do_text_file = true;
2273 } else {
2274 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002275 }
2276 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002277 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002278 if (do_text_file) {
2279 dprintf(ds.control_socket_fd_,
2280 "FAIL:could not create zip file, check %s "
2281 "for more details\n",
2282 ds.log_path_.c_str());
2283 } else {
2284 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2285 }
2286 }
2287}
2288
Nandana Dutt4be45d12018-09-26 15:04:23 +01002289
Nandana Dutt58d72e22018-11-16 10:30:48 +00002290static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2291 switch (mode) {
2292 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2293 return "BUGREPORT_FULL";
2294 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2295 return "BUGREPORT_INTERACTIVE";
2296 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2297 return "BUGREPORT_REMOTE";
2298 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2299 return "BUGREPORT_WEAR";
2300 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2301 return "BUGREPORT_TELEPHONY";
2302 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2303 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002304 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2305 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002306 }
2307}
2308
Paul Changf59c2b72020-03-10 02:08:55 +08002309static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2310 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002311 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2312 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002313 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002314 switch (mode) {
2315 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002316 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002317 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002318 break;
2319 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002320 // Currently, the dumpstate binder is only used by Shell to update progress.
2321 options->do_start_service = true;
2322 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002323 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002324 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002325 break;
2326 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002327 options->do_vibrate = false;
2328 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002329 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002330 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002331 break;
2332 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002333 options->do_start_service = true;
2334 options->do_progress_updates = true;
2335 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002336 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002337 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002338 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002339 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002340 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002341 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002342 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002343 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002344 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002345 break;
2346 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002347 options->wifi_only = true;
2348 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002349 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002350 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002351 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002352 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2353 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002354 }
2355}
2356
Nandana Dutt58d72e22018-11-16 10:30:48 +00002357static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002358 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002359 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002360 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002361 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankf56bbb22020-05-26 18:02:39 -07002362 "arc_only: %d args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002363 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002364 options.do_screenshot, options.is_remote_mode, options.show_header_only,
mhasankf56bbb22020-05-26 18:02:39 -07002365 options.do_start_service, options.telephony_only, options.wifi_only,
2366 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2367 toString(options.dumpstate_hal_mode).c_str(), options.arc_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002368}
2369
Nandana Dutt54dbd672019-01-11 12:58:05 +00002370void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2371 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002372 const android::base::unique_fd& screenshot_fd_in,
2373 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002374 // In the new API world, date is always added; output is always a zip file.
2375 // TODO(111441001): remove these options once they are obsolete.
2376 do_add_date = true;
2377 do_zip_file = true;
2378
Nandana Dutt54dbd672019-01-11 12:58:05 +00002379 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2380 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2381 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002382
Paul Changf59c2b72020-03-10 02:08:55 +08002383 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002384}
2385
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002386Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2387 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002388 int c;
mhasankf56bbb22020-05-26 18:02:39 -07002389 while ((c = getopt(argc, argv, "dho:svqzpAPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002390 switch (c) {
2391 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002392 case 'd': do_add_date = true; break;
2393 case 'z': do_zip_file = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002394 case 's': use_socket = true; break;
2395 case 'S': use_control_socket = true; break;
2396 case 'v': show_header_only = true; break;
2397 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002398 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002399 case 'P': do_progress_updates = true; break;
2400 case 'R': is_remote_mode = true; break;
mhasankf56bbb22020-05-26 18:02:39 -07002401 case 'A': arc_only = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002402 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002403 case 'w':
2404 // This was already processed
2405 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002406 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002407 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002408 break;
2409 default:
2410 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002411 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002412 break;
2413 // clang-format on
2414 }
2415 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002416
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002417 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002418 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002419 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002420 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002421 }
2422 }
2423
2424 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2425 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002426
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002427 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002428}
2429
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002430bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002431 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002432 return false;
2433 }
2434
Abhijeet Kaure370d682019-10-01 16:49:30 +01002435 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002436 return false;
2437 }
2438
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002439 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002440 return false;
2441 }
2442
Abhijeet Kaure370d682019-10-01 16:49:30 +01002443 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002444 return false;
2445 }
2446 return true;
2447}
2448
Nandana Dutt197661d2018-11-16 16:40:21 +00002449void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2450 options_ = std::move(options);
2451}
2452
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002453void Dumpstate::Initialize() {
2454 /* gets the sequential id */
2455 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2456 id_ = ++last_id;
2457 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2458}
2459
Nandana Duttd2f5f082019-01-18 17:13:52 +00002460Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2461 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002462 if (listener_ != nullptr) {
2463 switch (status) {
2464 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002465 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002466 break;
2467 case Dumpstate::RunStatus::HELP:
2468 break;
2469 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002470 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002471 break;
2472 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002473 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2474 break;
2475 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2476 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2477 break;
2478 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2479 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002480 break;
2481 }
2482 }
2483 return status;
2484}
2485
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002486void Dumpstate::Cancel() {
2487 CleanupTmpFiles();
2488 android::os::UnlinkAndLogOnError(log_path_);
2489 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2490 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2491 kDumpstateBoardFiles[i]);
2492 }
2493 tombstone_data_.clear();
2494 anr_data_.clear();
2495}
2496
Nandana Dutt979388e2018-11-30 16:48:55 +00002497/*
2498 * Dumps relevant information to a bugreport based on the given options.
2499 *
2500 * The bugreport can be dumped to a file or streamed to a socket.
2501 *
2502 * How dumping to file works:
2503 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2504 * stderr is redirected a log file.
2505 *
2506 * The temporary bugreport is then populated via printfs, dumping contents of files and
2507 * output of commands to stdout.
2508 *
2509 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2510 * text file.
2511 *
2512 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2513 * gets added to the archive.
2514 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002515 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2516 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002517 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002518Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2519 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002520 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002521 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002522 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002523 return RunStatus::INVALID_INPUT;
2524 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002525 /* set as high priority, and protect from OOM killer */
2526 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002527
Felipe Lemed071c682016-10-20 16:48:00 -07002528 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002529 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002530 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002531 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002532 } else {
2533 /* fallback to kernels <= 2.6.35 */
2534 oom_adj = fopen("/proc/self/oom_adj", "we");
2535 if (oom_adj) {
2536 fputs("-17", oom_adj);
2537 fclose(oom_adj);
2538 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002539 }
2540
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002541 if (version_ == VERSION_DEFAULT) {
2542 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002543 }
2544
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002545 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002546 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002547 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002548 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002549 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002550 }
2551
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002552 if (options_->show_header_only) {
2553 PrintHeader();
2554 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002555 }
2556
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002557 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2558 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002559
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002560 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002561 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002562
2563 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002564 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002565 is_redirecting
2566 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2567 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002568 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002569
Sahana Raof35ed432019-07-12 10:47:52 +01002570 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2571 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2572 } else {
2573 // Wake lock will be released automatically on process death
2574 MYLOGD("Wake lock acquired.\n");
2575 }
2576
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002577 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002578
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002579 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002580 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002581 MYLOGI("Starting 'dumpstate' service\n");
2582 android::status_t ret;
2583 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2584 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2585 }
2586 }
2587
Felipe Lemef0292972016-11-22 13:57:05 -08002588 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002589 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2590 }
2591
Nandana Dutt235c6672019-11-14 15:22:32 +00002592 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2593 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002594
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002595 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002596
Christopher Ferrised9354f2014-10-01 17:35:01 -07002597 // If we are going to use a socket, do it as early as possible
2598 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002599 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002600 if (!redirect_to_socket(stdout, "dumpstate")) {
2601 return ERROR;
2602 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002603 }
2604
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002605 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002606 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002607 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002608 if (control_socket_fd_ == -1) {
2609 return ERROR;
2610 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002611 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002612 }
2613
Felipe Leme71bbfc52015-11-23 14:14:51 -08002614 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002615 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002616
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002617 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002618 // clang-format off
2619 std::vector<std::string> am_args = {
2620 "--receiver-permission", "android.permission.DUMP",
2621 };
2622 // clang-format on
2623 // Send STARTED broadcast for apps that listen to bugreport generation events
2624 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002625 if (options_->use_control_socket) {
2626 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002627 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002628 }
2629 }
2630
Nick Kralevichf3599b32016-01-25 15:05:16 -08002631 /* read /proc/cmdline before dropping root */
2632 FILE *cmdline = fopen("/proc/cmdline", "re");
2633 if (cmdline) {
2634 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2635 fclose(cmdline);
2636 }
2637
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002638 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002639 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002640 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002641
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002642 if (options_->do_zip_file && zip_file != nullptr) {
2643 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2644 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002645 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002646 }
2647 }
2648
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002649 int dup_stdout_fd;
2650 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002651 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002652 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002653 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002654 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2655 return ERROR;
2656 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002657 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2658 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2659 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002660 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002661
2662 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2663 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002664 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002665 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002666 /* TODO: rather than generating a text file now and zipping it later,
2667 it would be more efficient to redirect stdout to the zip entry
2668 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002669 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2670 return ERROR;
2671 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002672 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002673 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002674 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002675 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002676 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002677
2678 // Don't buffer stdout
2679 setvbuf(stdout, nullptr, _IONBF, 0);
2680
Felipe Leme608385d2016-02-01 10:35:38 -08002681 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2682 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002683 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002684 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002685
mhasankf56bbb22020-05-26 18:02:39 -07002686 // TODO(nandana) reduce code repetition in if branches
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002687 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002688 MaybeTakeEarlyScreenshot();
Paul Changeb4b4642020-05-28 22:05:47 +08002689 onUiIntensiveBugreportDumpsFinished(calling_uid);
Jichao Lie89d9c12019-11-21 19:02:51 -08002690 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002691 DumpstateTelephonyOnly(calling_package);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002692 DumpstateBoard();
2693 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002694 MaybeTakeEarlyScreenshot();
Paul Changeb4b4642020-05-28 22:05:47 +08002695 onUiIntensiveBugreportDumpsFinished(calling_uid);
Jichao Lie89d9c12019-11-21 19:02:51 -08002696 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002697 DumpstateWifiOnly();
mhasankf56bbb22020-05-26 18:02:39 -07002698 } else if (options_->arc_only) {
2699 MaybeTakeEarlyScreenshot();
Paul Changeb4b4642020-05-28 22:05:47 +08002700 onUiIntensiveBugreportDumpsFinished(calling_uid);
mhasankf56bbb22020-05-26 18:02:39 -07002701 MaybeCheckUserConsent(calling_uid, calling_package);
2702 DumpstateArcOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002703 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002704 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002705 RunDumpsysCritical();
2706
Paul Chang0d2aad72020-02-13 20:04:03 +08002707 // Take screenshot and get consent only after critical dumpsys has finished.
2708 MaybeTakeEarlyScreenshot();
Paul Changeb4b4642020-05-28 22:05:47 +08002709 onUiIntensiveBugreportDumpsFinished(calling_uid);
Jichao Lie89d9c12019-11-21 19:02:51 -08002710 MaybeCheckUserConsent(calling_uid, calling_package);
2711
Nandana Dutt4be45d12018-09-26 15:04:23 +01002712 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002713 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002714 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002715 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002716 HandleUserConsentDenied();
2717 }
2718 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002719 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002720 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002721
Felipe Leme55b42a62015-11-10 17:39:08 -08002722 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002723 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002724 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002725 }
2726
Abhijeet Kaure370d682019-10-01 16:49:30 +01002727 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002728 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002729 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002730 }
2731
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002732 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002733 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002734 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002735 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002736 if (status != Dumpstate::RunStatus::OK &&
2737 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2738 // Do an early return if there were errors. We make an exception for consent
2739 // timing out because it's possible the user got distracted. In this case the
2740 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002741 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002742 return status;
2743 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002744 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2745 MYLOGI(
2746 "Did not receive user consent yet."
2747 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002748 const String16 incidentcompanion("incidentcompanion");
2749 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2750 if (ics != nullptr) {
2751 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2752 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2753 consent_callback_.get());
2754 } else {
2755 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2756 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002757 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002758 }
2759
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002760 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002761 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002762 for (int i = 0; i < 3; i++) {
2763 Vibrate(75);
2764 usleep((75 + 50) * 1000);
2765 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002766 }
2767
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002768 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2769 progress_->GetInitialMax());
2770 progress_->Save();
2771 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002772
Felipe Leme107a05f2016-03-08 15:11:15 -08002773 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002774 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002775 }
2776
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002777 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002778 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002779 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002780 }
2781
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002782 tombstone_data_.clear();
2783 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002784
Nandana Duttd2f5f082019-01-18 17:13:52 +00002785 return (consent_callback_ != nullptr &&
2786 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2787 ? USER_CONSENT_TIMED_OUT
2788 : RunStatus::OK;
2789}
2790
Paul Chang0d2aad72020-02-13 20:04:03 +08002791void Dumpstate::MaybeTakeEarlyScreenshot() {
2792 if (!options_->do_screenshot || !do_early_screenshot_) {
2793 return;
2794 }
2795
2796 TakeScreenshot();
2797}
2798
Paul Changeb4b4642020-05-28 22:05:47 +08002799void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid) {
Paul Changc490e662020-04-11 18:14:09 +08002800 if (calling_uid == AID_SHELL || !CalledByApi()) {
2801 return;
2802 }
2803 if (listener_ != nullptr) {
2804 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2805 // handling if required.
Paul Changeb4b4642020-05-28 22:05:47 +08002806 listener_->onUiIntensiveBugreportDumpsFinished();
Paul Changc490e662020-04-11 18:14:09 +08002807 }
2808}
2809
Jichao Lie89d9c12019-11-21 19:02:51 -08002810void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2811 if (calling_uid == AID_SHELL || !CalledByApi()) {
2812 // No need to get consent for shell triggered dumpstates, or not through
2813 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002814 return;
2815 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002816 consent_callback_ = new ConsentCallback();
2817 const String16 incidentcompanion("incidentcompanion");
2818 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002819 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002820 if (ics != nullptr) {
2821 MYLOGD("Checking user consent via incidentcompanion service\n");
2822 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002823 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002824 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002825 } else {
2826 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2827 }
2828}
2829
Nandana Dutt5c390032019-03-12 10:52:56 +00002830bool Dumpstate::IsUserConsentDenied() const {
2831 return ds.consent_callback_ != nullptr &&
2832 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2833}
2834
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002835bool Dumpstate::CalledByApi() const {
2836 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2837}
2838
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002839void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002840 android::os::UnlinkAndLogOnError(tmp_path_);
2841 android::os::UnlinkAndLogOnError(screenshot_path_);
2842 android::os::UnlinkAndLogOnError(path_);
2843}
2844
2845Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2846 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002847 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00002848 return USER_CONSENT_DENIED;
2849}
2850
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002851Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002852 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002853 // user consent (unless the caller is Shell).
2854 UserConsentResult consent_result;
2855 if (calling_uid == AID_SHELL) {
2856 consent_result = UserConsentResult::APPROVED;
2857 } else {
2858 consent_result = consent_callback_->getResult();
2859 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002860 if (consent_result == UserConsentResult::UNAVAILABLE) {
2861 // User has not responded yet.
2862 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08002863 // Telephony is a fast report type, particularly on user builds where information may be
2864 // more aggressively limited. To give the user time to read the consent dialog, increase the
2865 // timeout.
2866 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
2867 : USER_CONSENT_TIMEOUT_MS;
2868 if (elapsed_ms < timeout_ms) {
2869 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00002870 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2871 sleep(delay_seconds);
2872 }
2873 consent_result = consent_callback_->getResult();
2874 }
2875 if (consent_result == UserConsentResult::DENIED) {
2876 // User has explicitly denied sharing with the app. To be safe delete the
2877 // internal bugreport & tmp files.
2878 return HandleUserConsentDenied();
2879 }
2880 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002881 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2882 if (copy_succeeded) {
2883 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01002884 if (options_->do_screenshot &&
2885 options_->screenshot_fd.get() != -1 &&
2886 !options_->is_screenshot_copied) {
2887 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2888 options_->screenshot_fd.get());
2889 options_->is_screenshot_copied = copy_succeeded;
2890 if (copy_succeeded) {
2891 android::os::UnlinkAndLogOnError(screenshot_path_);
2892 }
2893 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002894 }
2895 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2896 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2897 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2898 // Since we do not have user consent to share the bugreport it does not get
2899 // copied over to the calling app but remains in the internal directory from
2900 // where the user can manually pull it.
2901 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2902 }
2903 // Unknown result; must be a programming error.
2904 MYLOGE("Unknown user consent result:%d\n", consent_result);
2905 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002906}
2907
Nandana Duttf02564e2019-02-15 15:24:24 +00002908Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002909 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2910 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2911 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002912 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002913 // When directly running dumpstate binary, the output is not expected to be written
2914 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002915 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002916
2917 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002918 // an app; they are irrelevant here because bugreport is triggered via command line.
2919 // Update Last ID before calling Run().
2920 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00002921 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002922 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002923 return status;
2924}
2925
2926/* Main entry point for dumpstate binary. */
2927int run_main(int argc, char* argv[]) {
2928 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002929
2930 switch (status) {
2931 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002932 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002933 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002934 ShowUsage();
2935 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002936 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002937 fprintf(stderr, "Invalid combination of args\n");
2938 ShowUsage();
2939 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002940 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002941 FALLTHROUGH_INTENDED;
2942 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2943 FALLTHROUGH_INTENDED;
2944 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002945 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002946 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002947}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002948
2949// TODO(111441001): Default DumpOptions to sensible values.
2950Dumpstate::Dumpstate(const std::string& version)
2951 : pid_(getpid()),
2952 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01002953 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002954 version_(version),
2955 now_(time(nullptr)) {
2956}
2957
2958Dumpstate& Dumpstate::GetInstance() {
2959 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
2960 return singleton_;
2961}
2962
Nandana Dutt8d945c02019-08-14 13:30:07 +01002963DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
2964 : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002965 if (!title_.empty()) {
2966 started_ = Nanotime();
2967 }
2968}
2969
2970DurationReporter::~DurationReporter() {
2971 if (!title_.empty()) {
2972 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08002973 if (elapsed >= .5f || verbose_) {
2974 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002975 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08002976 if (!logcat_only_) {
2977 // Use "Yoda grammar" to make it easier to grep|sort sections.
2978 printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002979 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002980 }
2981}
2982
2983const int32_t Progress::kDefaultMax = 5000;
2984
2985Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
2986}
2987
2988Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
2989 : Progress(initial_max, growth_factor, "") {
2990 progress_ = progress;
2991}
2992
2993Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
2994 : initial_max_(initial_max),
2995 progress_(0),
2996 max_(initial_max),
2997 growth_factor_(growth_factor),
2998 n_runs_(0),
2999 average_max_(0),
3000 path_(path) {
3001 if (!path_.empty()) {
3002 Load();
3003 }
3004}
3005
3006void Progress::Load() {
3007 MYLOGD("Loading stats from %s\n", path_.c_str());
3008 std::string content;
3009 if (!android::base::ReadFileToString(path_, &content)) {
3010 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3011 return;
3012 }
3013 if (content.empty()) {
3014 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3015 return;
3016 }
3017 std::vector<std::string> lines = android::base::Split(content, "\n");
3018
3019 if (lines.size() < 1) {
3020 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3021 (int)lines.size(), max_);
3022 return;
3023 }
3024 char* ptr;
3025 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3026 average_max_ = strtol(ptr, nullptr, 10);
3027 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3028 average_max_ > STATS_MAX_AVERAGE) {
3029 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3030 initial_max_ = Progress::kDefaultMax;
3031 } else {
3032 initial_max_ = average_max_;
3033 }
3034 max_ = initial_max_;
3035
3036 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3037}
3038
3039void Progress::Save() {
3040 int32_t total = n_runs_ * average_max_ + progress_;
3041 int32_t runs = n_runs_ + 1;
3042 int32_t average = floor(((float)total) / runs);
3043 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3044 path_.c_str());
3045 if (path_.empty()) {
3046 return;
3047 }
3048
3049 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3050 if (!android::base::WriteStringToFile(content, path_)) {
3051 MYLOGE("Could not save stats on %s\n", path_.c_str());
3052 }
3053}
3054
3055int32_t Progress::Get() const {
3056 return progress_;
3057}
3058
3059bool Progress::Inc(int32_t delta_sec) {
3060 bool changed = false;
3061 if (delta_sec >= 0) {
3062 progress_ += delta_sec;
3063 if (progress_ > max_) {
3064 int32_t old_max = max_;
3065 max_ = floor((float)progress_ * growth_factor_);
3066 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3067 changed = true;
3068 }
3069 }
3070 return changed;
3071}
3072
3073int32_t Progress::GetMax() const {
3074 return max_;
3075}
3076
3077int32_t Progress::GetInitialMax() const {
3078 return initial_max_;
3079}
3080
3081void Progress::Dump(int fd, const std::string& prefix) const {
3082 const char* pr = prefix.c_str();
3083 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3084 dprintf(fd, "%smax: %d\n", pr, max_);
3085 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3086 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3087 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3088 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3089 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3090}
3091
3092bool Dumpstate::IsZipping() const {
3093 return zip_writer_ != nullptr;
3094}
3095
3096std::string Dumpstate::GetPath(const std::string& suffix) const {
3097 return GetPath(bugreport_internal_dir_, suffix);
3098}
3099
3100std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3101 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3102 name_.c_str(), suffix.c_str());
3103}
3104
3105void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3106 progress_ = std::move(progress);
3107}
3108
3109void for_each_userid(void (*func)(int), const char *header) {
3110 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3111 "for_each_userid(%s)", header);
3112 DurationReporter duration_reporter(title);
3113 if (PropertiesHelper::IsDryRun()) return;
3114
3115 DIR *d;
3116 struct dirent *de;
3117
3118 if (header) printf("\n------ %s ------\n", header);
3119 func(0);
3120
3121 if (!(d = opendir("/data/system/users"))) {
3122 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3123 return;
3124 }
3125
3126 while ((de = readdir(d))) {
3127 int userid;
3128 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3129 continue;
3130 }
3131 func(userid);
3132 }
3133
3134 closedir(d);
3135}
3136
3137static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3138 DIR *d;
3139 struct dirent *de;
3140
3141 if (!(d = opendir("/proc"))) {
3142 printf("Failed to open /proc (%s)\n", strerror(errno));
3143 return;
3144 }
3145
3146 if (header) printf("\n------ %s ------\n", header);
3147 while ((de = readdir(d))) {
3148 if (ds.IsUserConsentDenied()) {
3149 MYLOGE(
3150 "Returning early because user denied consent to share bugreport with calling app.");
3151 closedir(d);
3152 return;
3153 }
3154 int pid;
3155 int fd;
3156 char cmdpath[255];
3157 char cmdline[255];
3158
3159 if (!(pid = atoi(de->d_name))) {
3160 continue;
3161 }
3162
3163 memset(cmdline, 0, sizeof(cmdline));
3164
3165 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3166 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3167 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3168 close(fd);
3169 if (cmdline[0]) {
3170 helper(pid, cmdline, arg);
3171 continue;
3172 }
3173 }
3174
3175 // if no cmdline, a kernel thread has comm
3176 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3177 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3178 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3179 close(fd);
3180 if (cmdline[1]) {
3181 cmdline[0] = '[';
3182 size_t len = strcspn(cmdline, "\f\b\r\n");
3183 cmdline[len] = ']';
3184 cmdline[len+1] = '\0';
3185 }
3186 }
3187 if (!cmdline[0]) {
3188 strcpy(cmdline, "N/A");
3189 }
3190 helper(pid, cmdline, arg);
3191 }
3192
3193 closedir(d);
3194}
3195
3196static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3197 for_each_pid_func *func = (for_each_pid_func*) arg;
3198 func(pid, cmdline);
3199}
3200
3201void for_each_pid(for_each_pid_func func, const char *header) {
3202 std::string title = header == nullptr ? "for_each_pid"
3203 : android::base::StringPrintf("for_each_pid(%s)", header);
3204 DurationReporter duration_reporter(title);
3205 if (PropertiesHelper::IsDryRun()) return;
3206
3207 __for_each_pid(for_each_pid_helper, header, (void *) func);
3208}
3209
3210static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3211 DIR *d;
3212 struct dirent *de;
3213 char taskpath[255];
3214 for_each_tid_func *func = (for_each_tid_func *) arg;
3215
3216 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3217
3218 if (!(d = opendir(taskpath))) {
3219 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3220 return;
3221 }
3222
3223 func(pid, pid, cmdline);
3224
3225 while ((de = readdir(d))) {
3226 if (ds.IsUserConsentDenied()) {
3227 MYLOGE(
3228 "Returning early because user denied consent to share bugreport with calling app.");
3229 closedir(d);
3230 return;
3231 }
3232 int tid;
3233 int fd;
3234 char commpath[255];
3235 char comm[255];
3236
3237 if (!(tid = atoi(de->d_name))) {
3238 continue;
3239 }
3240
3241 if (tid == pid)
3242 continue;
3243
3244 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3245 memset(comm, 0, sizeof(comm));
3246 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3247 strcpy(comm, "N/A");
3248 } else {
3249 char *c;
3250 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3251 close(fd);
3252
3253 c = strrchr(comm, '\n');
3254 if (c) {
3255 *c = '\0';
3256 }
3257 }
3258 func(pid, tid, comm);
3259 }
3260
3261 closedir(d);
3262}
3263
3264void for_each_tid(for_each_tid_func func, const char *header) {
3265 std::string title = header == nullptr ? "for_each_tid"
3266 : android::base::StringPrintf("for_each_tid(%s)", header);
3267 DurationReporter duration_reporter(title);
3268
3269 if (PropertiesHelper::IsDryRun()) return;
3270
3271 __for_each_pid(for_each_tid_helper, header, (void *) func);
3272}
3273
3274void show_wchan(int pid, int tid, const char *name) {
3275 if (PropertiesHelper::IsDryRun()) return;
3276
3277 char path[255];
3278 char buffer[255];
3279 int fd, ret, save_errno;
3280 char name_buffer[255];
3281
3282 memset(buffer, 0, sizeof(buffer));
3283
3284 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3285 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3286 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3287 return;
3288 }
3289
3290 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3291 save_errno = errno;
3292 close(fd);
3293
3294 if (ret < 0) {
3295 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3296 return;
3297 }
3298
3299 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3300 pid == tid ? 0 : 3, "", name);
3301
3302 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3303
3304 return;
3305}
3306
3307// print time in centiseconds
3308static void snprcent(char *buffer, size_t len, size_t spc,
3309 unsigned long long time) {
3310 static long hz; // cache discovered hz
3311
3312 if (hz <= 0) {
3313 hz = sysconf(_SC_CLK_TCK);
3314 if (hz <= 0) {
3315 hz = 1000;
3316 }
3317 }
3318
3319 // convert to centiseconds
3320 time = (time * 100 + (hz / 2)) / hz;
3321
3322 char str[16];
3323
3324 snprintf(str, sizeof(str), " %llu.%02u",
3325 time / 100, (unsigned)(time % 100));
3326 size_t offset = strlen(buffer);
3327 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3328 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3329}
3330
3331// print permille as a percent
3332static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3333 char str[16];
3334
3335 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3336 size_t offset = strlen(buffer);
3337 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3338 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3339}
3340
3341void show_showtime(int pid, const char *name) {
3342 if (PropertiesHelper::IsDryRun()) return;
3343
3344 char path[255];
3345 char buffer[1023];
3346 int fd, ret, save_errno;
3347
3348 memset(buffer, 0, sizeof(buffer));
3349
3350 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3351 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3352 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3353 return;
3354 }
3355
3356 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3357 save_errno = errno;
3358 close(fd);
3359
3360 if (ret < 0) {
3361 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3362 return;
3363 }
3364
3365 // field 14 is utime
3366 // field 15 is stime
3367 // field 42 is iotime
3368 unsigned long long utime = 0, stime = 0, iotime = 0;
3369 if (sscanf(buffer,
3370 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3371 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3372 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3373 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3374 &utime, &stime, &iotime) != 3) {
3375 return;
3376 }
3377
3378 unsigned long long total = utime + stime;
3379 if (!total) {
3380 return;
3381 }
3382
3383 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3384 if (permille > 1000) {
3385 permille = 1000;
3386 }
3387
3388 // try to beautify and stabilize columns at <80 characters
3389 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3390 if ((name[0] != '[') || utime) {
3391 snprcent(buffer, sizeof(buffer), 57, utime);
3392 }
3393 snprcent(buffer, sizeof(buffer), 65, stime);
3394 if ((name[0] != '[') || iotime) {
3395 snprcent(buffer, sizeof(buffer), 73, iotime);
3396 }
3397 if (iotime) {
3398 snprdec(buffer, sizeof(buffer), 79, permille);
3399 }
3400 puts(buffer); // adds a trailing newline
3401
3402 return;
3403}
3404
3405void do_dmesg() {
3406 const char *title = "KERNEL LOG (dmesg)";
3407 DurationReporter duration_reporter(title);
3408 printf("------ %s ------\n", title);
3409
3410 if (PropertiesHelper::IsDryRun()) return;
3411
3412 /* Get size of kernel buffer */
3413 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3414 if (size <= 0) {
3415 printf("Unexpected klogctl return value: %d\n\n", size);
3416 return;
3417 }
3418 char *buf = (char *) malloc(size + 1);
3419 if (buf == nullptr) {
3420 printf("memory allocation failed\n\n");
3421 return;
3422 }
3423 int retval = klogctl(KLOG_READ_ALL, buf, size);
3424 if (retval < 0) {
3425 printf("klogctl failure\n\n");
3426 free(buf);
3427 return;
3428 }
3429 buf[retval] = '\0';
3430 printf("%s\n\n", buf);
3431 free(buf);
3432 return;
3433}
3434
3435void do_showmap(int pid, const char *name) {
3436 char title[255];
3437 char arg[255];
3438
3439 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3440 snprintf(arg, sizeof(arg), "%d", pid);
3441 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3442}
3443
3444int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3445 DurationReporter duration_reporter(title);
3446
3447 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3448
3449 UpdateProgress(WEIGHT_FILE);
3450
3451 return status;
3452}
3453
3454int read_file_as_long(const char *path, long int *output) {
3455 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3456 if (fd < 0) {
3457 int err = errno;
3458 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3459 return -1;
3460 }
3461 char buffer[50];
3462 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3463 if (bytes_read == -1) {
3464 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3465 return -2;
3466 }
3467 if (bytes_read == 0) {
3468 MYLOGE("File %s is empty\n", path);
3469 return -3;
3470 }
3471 *output = atoi(buffer);
3472 return 0;
3473}
3474
3475/* calls skip to gate calling dump_from_fd recursively
3476 * in the specified directory. dump_from_fd defaults to
3477 * dump_file_from_fd above when set to NULL. skip defaults
3478 * to false when set to NULL. dump_from_fd will always be
3479 * called with title NULL.
3480 */
3481int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3482 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3483 DurationReporter duration_reporter(title);
3484 DIR *dirp;
3485 struct dirent *d;
3486 char *newpath = nullptr;
3487 const char *slash = "/";
3488 int retval = 0;
3489
3490 if (!title.empty()) {
3491 printf("------ %s (%s) ------\n", title.c_str(), dir);
3492 }
3493 if (PropertiesHelper::IsDryRun()) return 0;
3494
3495 if (dir[strlen(dir) - 1] == '/') {
3496 ++slash;
3497 }
3498 dirp = opendir(dir);
3499 if (dirp == nullptr) {
3500 retval = -errno;
3501 MYLOGE("%s: %s\n", dir, strerror(errno));
3502 return retval;
3503 }
3504
3505 if (!dump_from_fd) {
3506 dump_from_fd = dump_file_from_fd;
3507 }
3508 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3509 if ((d->d_name[0] == '.')
3510 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3511 || (d->d_name[1] == '\0'))) {
3512 continue;
3513 }
3514 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3515 (d->d_type == DT_DIR) ? "/" : "");
3516 if (!newpath) {
3517 retval = -errno;
3518 continue;
3519 }
3520 if (skip && (*skip)(newpath)) {
3521 continue;
3522 }
3523 if (d->d_type == DT_DIR) {
3524 int ret = dump_files("", newpath, skip, dump_from_fd);
3525 if (ret < 0) {
3526 retval = ret;
3527 }
3528 continue;
3529 }
3530 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3531 if (fd.get() < 0) {
3532 retval = -1;
3533 printf("*** %s: %s\n", newpath, strerror(errno));
3534 continue;
3535 }
3536 (*dump_from_fd)(nullptr, newpath, fd.get());
3537 }
3538 closedir(dirp);
3539 if (!title.empty()) {
3540 printf("\n");
3541 }
3542 return retval;
3543}
3544
3545/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3546 * it's possible to avoid issues where opening the file itself can get
3547 * stuck.
3548 */
3549int dump_file_from_fd(const char *title, const char *path, int fd) {
3550 if (PropertiesHelper::IsDryRun()) return 0;
3551
3552 int flags = fcntl(fd, F_GETFL);
3553 if (flags == -1) {
3554 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3555 return -1;
3556 } else if (!(flags & O_NONBLOCK)) {
3557 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3558 return -1;
3559 }
3560 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3561}
3562
3563int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +01003564 const CommandOptions& options, bool verbose_duration) {
3565 DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003566
3567 int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
3568
3569 /* TODO: for now we're simplifying the progress calculation by using the
3570 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3571 * where its weight should be much higher proportionally to its timeout.
3572 * Ideally, it should use a options.EstimatedDuration() instead...*/
3573 UpdateProgress(options.Timeout());
3574
3575 return status;
3576}
3577
3578void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3579 const CommandOptions& options, long dumpsysTimeoutMs) {
3580 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3581 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3582 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3583 RunCommand(title, dumpsys, options);
3584}
3585
3586int open_socket(const char *service) {
3587 int s = android_get_control_socket(service);
3588 if (s < 0) {
3589 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3590 return -1;
3591 }
3592 fcntl(s, F_SETFD, FD_CLOEXEC);
3593
3594 // Set backlog to 0 to make sure that queue size will be minimum.
3595 // In Linux, because the minimum queue will be 1, connect() will be blocked
3596 // if the other clients already called connect() and the connection request was not accepted.
3597 if (listen(s, 0) < 0) {
3598 MYLOGE("listen(control socket): %s\n", strerror(errno));
3599 return -1;
3600 }
3601
3602 struct sockaddr addr;
3603 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003604 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003605
3606 // Close socket just after accept(), to make sure that connect() by client will get error
3607 // when the socket is used by the other services.
3608 // There is still a race condition possibility between accept and close, but there is no way
3609 // to close-on-accept atomically.
3610 // See detail; b/123306389#comment25
3611 close(s);
3612
3613 if (fd < 0) {
3614 MYLOGE("accept(control socket): %s\n", strerror(errno));
3615 return -1;
3616 }
3617
3618 return fd;
3619}
3620
3621/* redirect output to a service control socket */
3622bool redirect_to_socket(FILE* redirect, const char* service) {
3623 int fd = open_socket(service);
3624 if (fd == -1) {
3625 return false;
3626 }
3627 fflush(redirect);
3628 // TODO: handle dup2 failure
3629 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3630 close(fd);
3631 return true;
3632}
3633
3634// TODO: should call is_valid_output_file and/or be merged into it.
3635void create_parent_dirs(const char *path) {
3636 char *chp = const_cast<char *> (path);
3637
3638 /* skip initial slash */
3639 if (chp[0] == '/')
3640 chp++;
3641
3642 /* create leading directories, if necessary */
3643 struct stat dir_stat;
3644 while (chp && chp[0]) {
3645 chp = strchr(chp, '/');
3646 if (chp) {
3647 *chp = 0;
3648 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3649 MYLOGI("Creating directory %s\n", path);
3650 if (mkdir(path, 0770)) { /* drwxrwx--- */
3651 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3652 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3653 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3654 }
3655 }
3656 *chp++ = '/';
3657 }
3658 }
3659}
3660
3661bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3662 create_parent_dirs(path);
3663
3664 int fd = TEMP_FAILURE_RETRY(open(path,
3665 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3666 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3667 if (fd < 0) {
3668 MYLOGE("%s: %s\n", path, strerror(errno));
3669 return false;
3670 }
3671
3672 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3673 close(fd);
3674 return true;
3675}
3676
3677bool redirect_to_file(FILE* redirect, char* path) {
3678 return _redirect_to_file(redirect, path, O_TRUNC);
3679}
3680
3681bool redirect_to_existing_file(FILE* redirect, char* path) {
3682 return _redirect_to_file(redirect, path, O_APPEND);
3683}
3684
3685void dump_route_tables() {
3686 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3687 if (PropertiesHelper::IsDryRun()) return;
3688 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3689 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3690 FILE* fp = fopen(RT_TABLES_PATH, "re");
3691 if (!fp) {
3692 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3693 return;
3694 }
3695 char table[16];
3696 // Each line has an integer (the table number), a space, and a string (the table name). We only
3697 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3698 // Add a fixed max limit so this doesn't go awry.
3699 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3700 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3701 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3702 }
3703 fclose(fp);
3704}
3705
3706// TODO: make this function thread safe if sections are generated in parallel.
3707void Dumpstate::UpdateProgress(int32_t delta_sec) {
3708 if (progress_ == nullptr) {
3709 MYLOGE("UpdateProgress: progress_ not set\n");
3710 return;
3711 }
3712
3713 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01003714 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003715
3716 // ...but only notifiy listeners when necessary.
3717 if (!options_->do_progress_updates) return;
3718
3719 int progress = progress_->Get();
3720 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01003721 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003722
Nandana Dutt402a8392019-06-14 14:25:13 +01003723 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003724 return;
3725 }
Nandana Dutt402a8392019-06-14 14:25:13 +01003726 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003727
3728 if (control_socket_fd_ >= 0) {
3729 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3730 fsync(control_socket_fd_);
3731 }
3732
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003733 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003734 if (percent % 10 == 0) {
3735 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003736 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003737 } else {
3738 // stderr is ignored on normal invocations, but useful when calling
3739 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003740 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003741 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003742
3743 listener_->onProgress(percent);
3744 }
3745}
3746
3747void Dumpstate::TakeScreenshot(const std::string& path) {
3748 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3749 int status =
3750 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3751 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3752 if (status == 0) {
3753 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3754 } else {
3755 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3756 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003757 if (listener_ != nullptr) {
3758 // Show a visual indication to indicate screenshot is taken via
3759 // IDumpstateListener.onScreenshotTaken()
3760 listener_->onScreenshotTaken(status == 0);
3761 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003762}
3763
3764bool is_dir(const char* pathname) {
3765 struct stat info;
3766 if (stat(pathname, &info) == -1) {
3767 return false;
3768 }
3769 return S_ISDIR(info.st_mode);
3770}
3771
3772time_t get_mtime(int fd, time_t default_mtime) {
3773 struct stat info;
3774 if (fstat(fd, &info) == -1) {
3775 return default_mtime;
3776 }
3777 return info.st_mtime;
3778}