blob: 5359619d66e39eb0537f12b9162e7ad5b617492c [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
Nandana Dutt5c390032019-03-12 10:52:56 +00001370// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1371// via the consent they are shown. Ignores other errors that occur while running various
1372// commands. The consent checking is currently done around long running tasks, which happen to
1373// be distributed fairly evenly throughout the function.
1374static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001375 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001376
Nandana Dutt5c390032019-03-12 10:52:56 +00001377 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1378 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1379 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001380 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001381 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001382 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001383 DumpFile("MEMORY INFO", "/proc/meminfo");
1384 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001385 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001386
1387 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1388
Sunny Goyal35949782019-11-19 15:54:36 -08001389 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1390
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001391 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1392 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1393 DumpFile("SLAB INFO", "/proc/slabinfo");
1394 DumpFile("ZONEINFO", "/proc/zoneinfo");
1395 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1396 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001397 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001398
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001399 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1400 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001401
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001402 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001403 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001404
1405 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1406 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001407
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001408 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001409
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001410 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001411 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001412 struct stat s;
1413 if (stat("/proc/modules", &s) != 0) {
1414 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1415 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001416 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001417 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001418
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001419 if (__android_logger_property_get_bool(
1420 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1421 DoKernelLogcat();
1422 } else {
1423 do_dmesg();
1424 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001425
Felipe Lemef0292972016-11-22 13:57:05 -08001426 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001427
1428 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1429
Jeff Brown1dc94e32014-09-11 14:15:27 -07001430 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001431 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001432
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001433 /* Dump Bluetooth HCI logs */
1434 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001435
Paul Chang0d2aad72020-02-13 20:04:03 +08001436 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001437 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001438 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001439 }
1440
Felipe Lemee184f662016-10-27 10:04:47 -07001441 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001442
Narayan Kamath8f788292017-05-25 13:20:39 +01001443 // NOTE: tombstones are always added as separate entries in the zip archive
1444 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001445 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001446 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001447 if (!tombstones_dumped) {
1448 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001449 }
1450
Jayachandran Ca94c7172017-06-10 15:08:12 -07001451 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001452
Chenbo Feng276a3b62018-08-07 11:44:49 -07001453 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1454
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001455 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001456
Jayachandran Ca94c7172017-06-10 15:08:12 -07001457 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001458
1459 dump_route_tables();
1460
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001461 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1462 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1463 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001464
Nandana Dutt5c390032019-03-12 10:52:56 +00001465 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001466
Elliott Hughes23ccc622017-02-28 10:14:22 -08001467 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001468
Jin Qianf334d662017-10-10 14:41:37 -07001469 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001470
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001471 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001472
Colin Crossf45fa6b2012-03-26 12:38:26 -07001473 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001474 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1475 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1476
1477 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1478 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1479 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1480 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1481 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001482
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001483 /* Add window and surface trace files. */
1484 if (!PropertiesHelper::IsUserBuild()) {
1485 ds.AddDir(WMTRACE_DATA_DIR, false);
1486 }
1487
Yifan Hongd90cc652020-02-08 16:52:02 -08001488 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1489
Nandana Dutt5c390032019-03-12 10:52:56 +00001490 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001491
Steven Moreland7440ddb2016-12-15 16:13:39 -08001492 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001493 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1494 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001495 // su does not exist on user builds, so try running without it.
1496 // This way any implementations of vril-dump that do not require
1497 // root can run on user builds.
1498 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001499 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001500 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001501 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001502 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001503 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001504 }
1505
Felipe Lemed8b94e52016-12-08 10:21:44 -08001506 printf("========================================================\n");
1507 printf("== Android Framework Services\n");
1508 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001509
Nandana Dutt5c390032019-03-12 10:52:56 +00001510 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001511
Felipe Lemed8b94e52016-12-08 10:21:44 -08001512 printf("========================================================\n");
1513 printf("== Checkins\n");
1514 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001515
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001516 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001517
1518 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1519
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001520 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1521 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1522 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1523 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001524
Felipe Lemed8b94e52016-12-08 10:21:44 -08001525 printf("========================================================\n");
1526 printf("== Running Application Activities\n");
1527 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001528
Makoto Onuki60780982018-04-16 15:34:00 -07001529 // The following dumpsys internally collects output from running apps, so it can take a long
1530 // time. So let's extend the timeout.
1531
1532 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1533
1534 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001535
Felipe Lemed8b94e52016-12-08 10:21:44 -08001536 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001537 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001538 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001539
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001540 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001541 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001542
Felipe Lemed8b94e52016-12-08 10:21:44 -08001543 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001544 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001545 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001546
Makoto Onuki60780982018-04-16 15:34:00 -07001547 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1548 DUMPSYS_COMPONENTS_OPTIONS);
1549
1550 printf("========================================================\n");
1551 printf("== Running Application Providers (platform)\n");
1552 printf("========================================================\n");
1553
1554 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1555 DUMPSYS_COMPONENTS_OPTIONS);
1556
1557 printf("========================================================\n");
1558 printf("== Running Application Providers (non-platform)\n");
1559 printf("========================================================\n");
1560
1561 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1562 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001563
Adrian Roos8b397ab2017-04-04 16:35:44 -07001564 printf("========================================================\n");
1565 printf("== Dropbox crashes\n");
1566 printf("========================================================\n");
1567
1568 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1569 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1570
Felipe Lemed8b94e52016-12-08 10:21:44 -08001571 printf("========================================================\n");
1572 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1573 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1574 printf("========================================================\n");
1575 printf("== dumpstate: done (id %d)\n", ds.id_);
1576 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001577
1578 printf("========================================================\n");
1579 printf("== Obtaining statsd metadata\n");
1580 printf("========================================================\n");
1581 // This differs from the usual dumpsys stats, which is the stats report data.
1582 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001583
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001584 // Add linker configuration directory
1585 ds.AddDir(LINKERCONFIG_DIR, true);
1586
Mike Ma5c267872019-08-21 11:31:34 -07001587 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
1588
Nandana Dutt5c390032019-03-12 10:52:56 +00001589 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001590}
1591
Nandana Dutt5c390032019-03-12 10:52:56 +00001592/*
1593 * Dumps state for the default case; drops root after it's no longer necessary.
1594 *
1595 * Returns RunStatus::OK if everything went fine.
1596 * Returns RunStatus::ERROR if there was an error.
1597 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1598 * with the caller.
1599 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001600Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001601 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1602 // buffer.
1603 DoLogcat();
1604 // Capture timestamp after first logcat to use in next logcat
1605 time_t logcat_ts = time(nullptr);
1606
Nandana Dutt4be45d12018-09-26 15:04:23 +01001607 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001608 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001609
1610 /* Run some operations that require root. */
1611 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1612 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1613
1614 ds.AddDir(RECOVERY_DIR, true);
1615 ds.AddDir(RECOVERY_DATA_DIR, true);
1616 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1617 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1618 if (!PropertiesHelper::IsUserBuild()) {
1619 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1620 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001621 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001622 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001623 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001624 add_mountinfo();
1625 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001626 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001627 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001628
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001629 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001630 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1631
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001632 // Dump IPsec stats. No keys are exposed here.
1633 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1634
Nandana Dutt4be45d12018-09-26 15:04:23 +01001635 // Run ss as root so we can see socket marks.
1636 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1637
1638 // Run iotop as root to show top 100 IO threads
1639 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1640
Erick Reyese68df822019-02-11 14:46:36 -08001641 // Gather shared memory buffer info if the product implements it
1642 struct stat st;
1643 if (!stat("/product/bin/dmabuf_dump", &st)) {
1644 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1645 }
1646
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001647 DumpFile("PSI cpu", "/proc/pressure/cpu");
1648 DumpFile("PSI memory", "/proc/pressure/memory");
1649 DumpFile("PSI io", "/proc/pressure/io");
1650
Nandana Dutt4be45d12018-09-26 15:04:23 +01001651 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001652 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001653 }
1654
Nandana Dutt5c390032019-03-12 10:52:56 +00001655 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001656 Dumpstate::RunStatus status = dumpstate();
1657 // Capture logcat since the last time we did it.
1658 DoSystemLogcat(logcat_ts);
1659 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001660}
1661
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001662// This method collects common dumpsys for telephony and wifi. Typically, wifi
1663// reports are fine to include all information, but telephony reports on user
1664// builds need to strip some content (see DumpstateTelephonyOnly).
1665static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001666 DumpIpTablesAsRoot();
1667
Jayachandran Cb4389d92019-07-08 09:46:05 -07001668 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1669
Jayachandran Ca94c7172017-06-10 15:08:12 -07001670 if (!DropRootUser()) {
1671 return;
1672 }
1673
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001674 // We need to be picky about some stuff for telephony reports on user builds.
1675 if (!include_sensitive_info) {
1676 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1677 DoRadioLogcat();
1678 } else {
1679 // Contains various system properties and process startup info.
1680 do_dmesg();
1681 // Logs other than the radio buffer may contain package/component names and potential PII.
1682 DoLogcat();
1683 // Too broad for connectivity problems.
1684 DoKmsg();
1685 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
1686 DumpHals();
1687 }
1688
Jayachandran Ca94c7172017-06-10 15:08:12 -07001689 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001690 DumpIpAddrAndRules();
1691 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001692 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1693 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001694}
1695
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001696// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1697// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1698// for what can be included on user builds: all reported information MUST directly relate to
1699// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1700// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1701// names are not), and MUST NOT contain logs of user application traffic.
1702// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001703static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001704 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001705
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001706 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001707
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001708 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001709
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001710 DumpstateRadioCommon(include_sensitive_info);
1711
1712 if (include_sensitive_info) {
1713 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1714 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1715 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1716 // way.
1717 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1718 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001719
1720 printf("========================================================\n");
1721 printf("== Android Framework Services\n");
1722 printf("========================================================\n");
1723
Vishnu Nair652cc802017-11-30 15:18:30 -08001724 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1725 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001726 if (include_sensitive_info) {
1727 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1728 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1729 SEC_TO_MSEC(10));
1730 } else {
1731 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1732 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1733 // give a higher timeout as well.
1734 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1735 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1736 }
1737 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001738 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1739 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001740 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001741 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1742 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001743 if (include_sensitive_info) {
1744 // Contains raw IP addresses, omit from reports on user builds.
1745 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1746 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1747 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1748 SEC_TO_MSEC(10));
1749 // Contains package/component names, omit from reports on user builds.
1750 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1751 SEC_TO_MSEC(10));
1752 // Contains package names, but should be relatively simple to remove them (also contains
1753 // UIDs already), omit from reports on user builds.
1754 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1755 SEC_TO_MSEC(10));
1756 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001757
1758 printf("========================================================\n");
1759 printf("== Running Application Services\n");
1760 printf("========================================================\n");
1761
1762 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1763
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001764 if (include_sensitive_info) {
1765 printf("========================================================\n");
1766 printf("== Running Application Services (non-platform)\n");
1767 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001768
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001769 // Contains package/component names and potential PII, omit from reports on user builds.
1770 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1771 // carrier_config dumpsys instead.
1772 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1773 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001774
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001775 printf("========================================================\n");
1776 printf("== Checkins\n");
1777 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001778
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001779 // Contains package/component names, omit from reports on user builds.
1780 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1781 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001782
1783 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001784 printf("== dumpstate: done (id %d)\n", ds.id_);
1785 printf("========================================================\n");
1786}
1787
mukesh agrawal253dad42018-01-23 21:59:59 -08001788// This method collects dumpsys for wifi debugging only
1789static void DumpstateWifiOnly() {
1790 DurationReporter duration_reporter("DUMPSTATE");
1791
1792 DumpstateRadioCommon();
1793
1794 printf("========================================================\n");
1795 printf("== Android Framework Services\n");
1796 printf("========================================================\n");
1797
1798 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1799 SEC_TO_MSEC(10));
1800 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1801 SEC_TO_MSEC(10));
1802
1803 printf("========================================================\n");
1804 printf("== dumpstate: done (id %d)\n", ds.id_);
1805 printf("========================================================\n");
1806}
1807
Nandana Duttcf419a72019-03-14 10:40:17 +00001808Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001809 DurationReporter duration_reporter("DUMP TRACES");
1810
1811 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1812 const size_t buf_size = temp_file_pattern.length() + 1;
1813 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1814 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1815
1816 // Create a new, empty file to receive all trace dumps.
1817 //
1818 // TODO: This can be simplified once we remove support for the old style
1819 // dumps. We can have a file descriptor passed in to dump_traces instead
1820 // of creating a file, closing it and then reopening it again.
1821 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1822 if (fd < 0) {
1823 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001824 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001825 }
1826
1827 // Nobody should have access to this temporary file except dumpstate, but we
1828 // temporarily grant 'read' to 'others' here because this file is created
1829 // when tombstoned is still running as root, but dumped after dropping. This
1830 // can go away once support for old style dumping has.
1831 const int chmod_ret = fchmod(fd, 0666);
1832 if (chmod_ret < 0) {
1833 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001834 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001835 }
1836
1837 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1838 if (proc.get() == nullptr) {
1839 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001840 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001841 }
1842
1843 // Number of times process dumping has timed out. If we encounter too many
1844 // failures, we'll give up.
1845 int timeout_failures = 0;
1846 bool dalvik_found = false;
1847
1848 const std::set<int> hal_pids = get_interesting_hal_pids();
1849
1850 struct dirent* d;
1851 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001852 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001853 int pid = atoi(d->d_name);
1854 if (pid <= 0) {
1855 continue;
1856 }
1857
1858 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1859 std::string exe;
1860 if (!android::base::Readlink(link_name, &exe)) {
1861 continue;
1862 }
1863
1864 bool is_java_process;
1865 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1866 // Don't bother dumping backtraces for the zygote.
1867 if (IsZygote(pid)) {
1868 continue;
1869 }
1870
1871 dalvik_found = true;
1872 is_java_process = true;
1873 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1874 is_java_process = false;
1875 } else {
1876 // Probably a native process we don't care about, continue.
1877 continue;
1878 }
1879
1880 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1881 if (timeout_failures == 3) {
1882 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1883 break;
1884 }
1885
1886 const uint64_t start = Nanotime();
1887 const int ret = dump_backtrace_to_file_timeout(
1888 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1889 is_java_process ? 5 : 20, fd);
1890
1891 if (ret == -1) {
1892 // For consistency, the header and footer to this message match those
1893 // dumped by debuggerd in the success case.
1894 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1895 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1896 dprintf(fd, "---- end %d ----", pid);
1897 timeout_failures++;
1898 continue;
1899 }
1900
1901 // We've successfully dumped stack traces, reset the failure count
1902 // and write a summary of the elapsed time to the file and continue with the
1903 // next process.
1904 timeout_failures = 0;
1905
1906 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1907 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1908 }
1909
1910 if (!dalvik_found) {
1911 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1912 }
1913
Nandana Duttcf419a72019-03-14 10:40:17 +00001914 *path = file_name_buf.release();
1915 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001916}
1917
Felipe Leme6f674ae2016-11-18 17:10:33 -08001918void Dumpstate::DumpstateBoard() {
1919 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001920 printf("========================================================\n");
1921 printf("== Board\n");
1922 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001923
Felipe Leme6f674ae2016-11-18 17:10:33 -08001924 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001925 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001926 return;
1927 }
1928
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001929 std::vector<std::string> paths;
1930 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001931 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001932 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1933 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001934 remover.emplace_back(android::base::make_scope_guard(
1935 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001936 }
Jie Song9fbfad02017-06-20 16:29:42 -07001937
Hunter Knepshield8540faf2020-02-04 19:47:20 -08001938 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
1939 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07001940 MYLOGE("No IDumpstateDevice implementation\n");
1941 return;
1942 }
1943
1944 using ScopedNativeHandle =
1945 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1946 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1947 [](native_handle_t* handle) {
1948 native_handle_close(handle);
1949 native_handle_delete(handle);
1950 });
1951 if (handle == nullptr) {
1952 MYLOGE("Could not create native_handle\n");
1953 return;
1954 }
1955
Nandana Dutt5c390032019-03-12 10:52:56 +00001956 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001957 for (size_t i = 0; i < paths.size(); i++) {
1958 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1959
1960 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1961 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1962 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1963 if (fd < 0) {
1964 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1965 return;
1966 }
1967 handle.get()->data[i] = fd.release();
1968 }
1969
Hunter Knepshield8540faf2020-02-04 19:47:20 -08001970 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
1971 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
1972 // will kill the HAL and grab whatever it dumped in time.
1973 constexpr size_t timeout_sec = 30;
1974 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
1975 // implement just 1.0.
1976 const char* descriptor_to_kill;
1977 using DumpstateBoardTask = std::packaged_task<bool()>;
1978 DumpstateBoardTask dumpstate_board_task;
1979 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
1980 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
1981 if (dumpstate_device_1_1 != nullptr) {
1982 MYLOGI("Using IDumpstateDevice v1.1");
1983 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
1984 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
1985 ::android::hardware::Return<DumpstateStatus> status =
1986 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
1987 SEC_TO_MSEC(timeout_sec));
1988 if (!status.isOk()) {
1989 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1990 return false;
1991 } else if (status != DumpstateStatus::OK) {
1992 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
1993 return false;
1994 }
1995 return true;
1996 });
1997 } else {
1998 MYLOGI("Using IDumpstateDevice v1.0");
1999 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2000 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2001 ::android::hardware::Return<void> status =
2002 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002003 if (!status.isOk()) {
2004 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002005 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002006 }
Wei Wang587eac92018-04-05 12:17:20 -07002007 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002008 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002009 }
2010 auto result = dumpstate_board_task.get_future();
2011 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002012
Wei Wang587eac92018-04-05 12:17:20 -07002013 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2014 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002015 if (!android::base::SetProperty(
2016 "ctl.interface_restart",
2017 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002018 MYLOGE("Couldn't restart dumpstate HAL\n");
2019 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002020 }
Wei Wang587eac92018-04-05 12:17:20 -07002021 // Wait some time for init to kill dumpstate vendor HAL
2022 constexpr size_t killing_timeout_sec = 10;
2023 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2024 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2025 "there might be racing in content\n", killing_timeout_sec);
2026 }
2027
2028 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2029 for (size_t i = 0; i < paths.size(); i++) {
2030 struct stat s;
2031 if (fstat(handle.get()->data[i], &s) == -1) {
2032 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2033 strerror(errno));
2034 file_sizes[i] = -1;
2035 continue;
2036 }
2037 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002038 }
2039
2040 for (size_t i = 0; i < paths.size(); i++) {
2041 if (file_sizes[i] == -1) {
2042 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002043 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002044 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002045 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002046 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002047 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002048 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002049 printf("*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002050 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002051}
2052
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002053static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002054 fprintf(stderr,
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002055 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002056 "[-z] [-s] [-S] [-q] [-P] [-R] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002057 " -h: display this help message\n"
2058 " -b: play sound file instead of vibrate, at beginning of job\n"
2059 " -e: play sound file instead of vibrate, at end of job\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002060 " -d: append date to filename\n"
2061 " -p: capture screenshot to filename.png\n"
2062 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002063 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002064 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002065 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002066 " -P: send broadcast when started and do progress updates\n"
2067 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002068 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002069 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002070}
2071
Wei Liuf87959e2016-08-26 14:51:42 -07002072static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002073 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002074}
2075
Felipe Leme1d486fe2016-10-14 18:06:47 -07002076bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002077 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002078 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002079 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002080 // Final timestamp
2081 char date[80];
2082 time_t the_real_now_please_stand_up = time(nullptr);
2083 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002084 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002085 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002086
Felipe Leme9a523ae2016-10-20 15:10:33 -07002087 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002088 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002089 return false;
2090 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002091 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002092 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002093 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002094 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002095
Felipe Leme0f3fb202016-06-10 17:10:53 -07002096 // Add log file (which contains stderr output) to zip...
2097 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002098 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002099 MYLOGE("Failed to add dumpstate log to .zip file\n");
2100 return false;
2101 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002102 // TODO: Should truncate the existing file.
2103 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002104 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2105 return false;
2106 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002107 fprintf(stderr, "\n");
2108
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002109 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002110 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002111 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002112 return false;
2113 }
2114
Felipe Leme1d486fe2016-10-14 18:06:47 -07002115 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2116 ds.zip_file.reset(nullptr);
2117
Felipe Lemee9d2c542016-11-15 11:48:26 -08002118 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002119 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002120
Felipe Leme1e9edc62015-12-21 16:02:13 -08002121 return true;
2122}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002123
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002124static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2125 // clang-format off
2126 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2127 "--receiver-foreground", "--receiver-include-background", "-a", action};
2128 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002129
2130 am.insert(am.end(), args.begin(), args.end());
2131
Felipe Leme8d2410e2017-02-08 09:46:08 -08002132 RunCommand("", am,
2133 CommandOptions::WithTimeout(20)
2134 .Log("Sending broadcast: '%s'\n")
2135 .Always()
2136 .DropRoot()
2137 .RedirectStderr()
2138 .Build());
2139}
2140
Felipe Leme35b8cf12017-02-10 15:47:29 -08002141static void Vibrate(int duration_ms) {
2142 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002143 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002144 CommandOptions::WithTimeout(10)
2145 .Log("Vibrate: '%s'\n")
2146 .Always()
2147 .Build());
2148 // clang-format on
2149}
2150
Nandana Dutt979388e2018-11-30 16:48:55 +00002151static void MaybeResolveSymlink(std::string* path) {
2152 std::string resolved_path;
2153 if (android::base::Readlink(*path, &resolved_path)) {
2154 *path = resolved_path;
2155 }
2156}
2157
Nandana Dutt4be45d12018-09-26 15:04:23 +01002158/*
2159 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2160 * if we are writing zip files and adds the version file.
2161 */
2162static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002163 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2164
Nandana Dutt4be45d12018-09-26 15:04:23 +01002165 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2166 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002167 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002168 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002169 char date[80];
2170 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2171 ds.name_ = date;
2172 } else {
2173 ds.name_ = "undated";
2174 }
2175
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002176 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002177 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002178 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002179 ds.base_name_ += "-wifi";
2180 }
2181
Paul Chang0d2aad72020-02-13 20:04:03 +08002182 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002183 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002184 }
2185 ds.tmp_path_ = ds.GetPath(".tmp");
2186 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2187
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002188 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002189 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002190 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002191 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002192 "Bugreport dir: [%s] "
2193 "Base name: [%s] "
2194 "Suffix: [%s] "
2195 "Log path: [%s] "
2196 "Temporary path: [%s] "
2197 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002198 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2199 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002200
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002201 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002202 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002203 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2204 create_parent_dirs(ds.path_.c_str());
2205 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2206 if (ds.zip_file == nullptr) {
2207 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2208 } else {
2209 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2210 }
2211 ds.AddTextZipEntry("version.txt", ds.version_);
2212 }
2213}
2214
2215/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002216 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002217 * printing zipped file status, etc.
2218 */
2219static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002220 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002221 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002222 if (!ds.FinishZipFile()) {
2223 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2224 do_text_file = true;
2225 } else {
2226 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002227 }
2228 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002229 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002230 if (do_text_file) {
2231 dprintf(ds.control_socket_fd_,
2232 "FAIL:could not create zip file, check %s "
2233 "for more details\n",
2234 ds.log_path_.c_str());
2235 } else {
2236 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2237 }
2238 }
2239}
2240
Nandana Dutt4be45d12018-09-26 15:04:23 +01002241
Nandana Dutt58d72e22018-11-16 10:30:48 +00002242static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2243 switch (mode) {
2244 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2245 return "BUGREPORT_FULL";
2246 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2247 return "BUGREPORT_INTERACTIVE";
2248 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2249 return "BUGREPORT_REMOTE";
2250 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2251 return "BUGREPORT_WEAR";
2252 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2253 return "BUGREPORT_TELEPHONY";
2254 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2255 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002256 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2257 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002258 }
2259}
2260
Paul Changf59c2b72020-03-10 02:08:55 +08002261static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2262 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002263 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2264 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002265 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002266 switch (mode) {
2267 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002268 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002269 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002270 break;
2271 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002272 // Currently, the dumpstate binder is only used by Shell to update progress.
2273 options->do_start_service = true;
2274 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002275 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002276 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002277 break;
2278 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002279 options->do_vibrate = false;
2280 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002281 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002282 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002283 break;
2284 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002285 options->do_start_service = true;
2286 options->do_progress_updates = true;
2287 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002288 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002289 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002290 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002291 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002292 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002293 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002294 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002295 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002296 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002297 break;
2298 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002299 options->wifi_only = true;
2300 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002301 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002302 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002303 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002304 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2305 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002306 }
2307}
2308
Nandana Dutt58d72e22018-11-16 10:30:48 +00002309static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002310 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002311 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002312 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002313 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
2314 "args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002315 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002316 options.do_screenshot, options.is_remote_mode, options.show_header_only,
2317 options.do_start_service,
Nandana Dutt235c6672019-11-14 15:22:32 +00002318 options.telephony_only, options.wifi_only, options.do_progress_updates,
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002319 options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2320 toString(options.dumpstate_hal_mode).c_str(), options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002321}
2322
Nandana Dutt54dbd672019-01-11 12:58:05 +00002323void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2324 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002325 const android::base::unique_fd& screenshot_fd_in,
2326 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002327 // In the new API world, date is always added; output is always a zip file.
2328 // TODO(111441001): remove these options once they are obsolete.
2329 do_add_date = true;
2330 do_zip_file = true;
2331
Nandana Dutt54dbd672019-01-11 12:58:05 +00002332 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2333 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2334 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002335
Paul Changf59c2b72020-03-10 02:08:55 +08002336 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002337}
2338
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002339Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2340 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002341 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002342 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002343 switch (c) {
2344 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002345 case 'd': do_add_date = true; break;
2346 case 'z': do_zip_file = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002347 case 's': use_socket = true; break;
2348 case 'S': use_control_socket = true; break;
2349 case 'v': show_header_only = true; break;
2350 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002351 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002352 case 'P': do_progress_updates = true; break;
2353 case 'R': is_remote_mode = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002354 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002355 case 'w':
2356 // This was already processed
2357 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002358 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002359 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002360 break;
2361 default:
2362 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002363 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002364 break;
2365 // clang-format on
2366 }
2367 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002368
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002369 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002370 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002371 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002372 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002373 }
2374 }
2375
2376 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2377 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002378
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002379 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002380}
2381
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002382bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002383 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002384 return false;
2385 }
2386
Abhijeet Kaure370d682019-10-01 16:49:30 +01002387 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002388 return false;
2389 }
2390
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002391 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002392 return false;
2393 }
2394
Abhijeet Kaure370d682019-10-01 16:49:30 +01002395 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002396 return false;
2397 }
2398 return true;
2399}
2400
Nandana Dutt197661d2018-11-16 16:40:21 +00002401void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2402 options_ = std::move(options);
2403}
2404
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002405void Dumpstate::Initialize() {
2406 /* gets the sequential id */
2407 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2408 id_ = ++last_id;
2409 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2410}
2411
Nandana Duttd2f5f082019-01-18 17:13:52 +00002412Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2413 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002414 if (listener_ != nullptr) {
2415 switch (status) {
2416 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002417 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002418 break;
2419 case Dumpstate::RunStatus::HELP:
2420 break;
2421 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002422 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002423 break;
2424 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002425 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2426 break;
2427 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2428 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2429 break;
2430 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2431 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002432 break;
2433 }
2434 }
2435 return status;
2436}
2437
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002438void Dumpstate::Cancel() {
2439 CleanupTmpFiles();
2440 android::os::UnlinkAndLogOnError(log_path_);
2441 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2442 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2443 kDumpstateBoardFiles[i]);
2444 }
2445 tombstone_data_.clear();
2446 anr_data_.clear();
2447}
2448
Nandana Dutt979388e2018-11-30 16:48:55 +00002449/*
2450 * Dumps relevant information to a bugreport based on the given options.
2451 *
2452 * The bugreport can be dumped to a file or streamed to a socket.
2453 *
2454 * How dumping to file works:
2455 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2456 * stderr is redirected a log file.
2457 *
2458 * The temporary bugreport is then populated via printfs, dumping contents of files and
2459 * output of commands to stdout.
2460 *
2461 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2462 * text file.
2463 *
2464 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2465 * gets added to the archive.
2466 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002467 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2468 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002469 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002470Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2471 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002472 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002473 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002474 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002475 return RunStatus::INVALID_INPUT;
2476 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002477 /* set as high priority, and protect from OOM killer */
2478 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002479
Felipe Lemed071c682016-10-20 16:48:00 -07002480 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002481 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002482 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002483 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002484 } else {
2485 /* fallback to kernels <= 2.6.35 */
2486 oom_adj = fopen("/proc/self/oom_adj", "we");
2487 if (oom_adj) {
2488 fputs("-17", oom_adj);
2489 fclose(oom_adj);
2490 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002491 }
2492
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002493 if (version_ == VERSION_DEFAULT) {
2494 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002495 }
2496
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002497 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002498 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002499 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002500 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002501 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002502 }
2503
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002504 if (options_->show_header_only) {
2505 PrintHeader();
2506 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002507 }
2508
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002509 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2510 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002511
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002512 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002513 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002514
2515 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002516 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002517 is_redirecting
2518 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2519 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002520 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002521
Sahana Raof35ed432019-07-12 10:47:52 +01002522 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2523 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2524 } else {
2525 // Wake lock will be released automatically on process death
2526 MYLOGD("Wake lock acquired.\n");
2527 }
2528
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002529 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002530
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002531 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002532 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002533 MYLOGI("Starting 'dumpstate' service\n");
2534 android::status_t ret;
2535 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2536 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2537 }
2538 }
2539
Felipe Lemef0292972016-11-22 13:57:05 -08002540 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002541 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2542 }
2543
Nandana Dutt235c6672019-11-14 15:22:32 +00002544 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2545 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002546
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002547 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002548
Christopher Ferrised9354f2014-10-01 17:35:01 -07002549 // If we are going to use a socket, do it as early as possible
2550 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002551 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002552 if (!redirect_to_socket(stdout, "dumpstate")) {
2553 return ERROR;
2554 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002555 }
2556
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002557 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002558 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002559 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002560 if (control_socket_fd_ == -1) {
2561 return ERROR;
2562 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002563 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002564 }
2565
Felipe Leme71bbfc52015-11-23 14:14:51 -08002566 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002567 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002568
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002569 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002570 // clang-format off
2571 std::vector<std::string> am_args = {
2572 "--receiver-permission", "android.permission.DUMP",
2573 };
2574 // clang-format on
2575 // Send STARTED broadcast for apps that listen to bugreport generation events
2576 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002577 if (options_->use_control_socket) {
2578 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002579 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002580 }
2581 }
2582
Nick Kralevichf3599b32016-01-25 15:05:16 -08002583 /* read /proc/cmdline before dropping root */
2584 FILE *cmdline = fopen("/proc/cmdline", "re");
2585 if (cmdline) {
2586 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2587 fclose(cmdline);
2588 }
2589
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002590 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002591 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002592 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002593
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002594 if (options_->do_zip_file && zip_file != nullptr) {
2595 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2596 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002597 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002598 }
2599 }
2600
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002601 int dup_stdout_fd;
2602 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002603 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002604 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002605 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002606 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2607 return ERROR;
2608 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002609 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2610 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2611 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002612 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002613
2614 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2615 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002616 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002617 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002618 /* TODO: rather than generating a text file now and zipping it later,
2619 it would be more efficient to redirect stdout to the zip entry
2620 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002621 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2622 return ERROR;
2623 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002624 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002625 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002626 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002627 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002628 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002629
2630 // Don't buffer stdout
2631 setvbuf(stdout, nullptr, _IONBF, 0);
2632
Felipe Leme608385d2016-02-01 10:35:38 -08002633 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2634 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002635 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002636 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002637
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002638 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002639 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002640 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002641 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002642 DumpstateTelephonyOnly(calling_package);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002643 DumpstateBoard();
2644 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002645 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002646 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002647 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002648 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002649 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002650 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002651 RunDumpsysCritical();
2652
Paul Chang0d2aad72020-02-13 20:04:03 +08002653 // Take screenshot and get consent only after critical dumpsys has finished.
2654 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002655 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002656 MaybeCheckUserConsent(calling_uid, calling_package);
2657
Nandana Dutt4be45d12018-09-26 15:04:23 +01002658 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002659 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002660 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002661 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002662 HandleUserConsentDenied();
2663 }
2664 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002665 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002666 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002667
Felipe Leme55b42a62015-11-10 17:39:08 -08002668 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002669 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002670 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002671 }
2672
Abhijeet Kaure370d682019-10-01 16:49:30 +01002673 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002674 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002675 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002676 }
2677
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002678 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002679 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002680 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002681 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002682 if (status != Dumpstate::RunStatus::OK &&
2683 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2684 // Do an early return if there were errors. We make an exception for consent
2685 // timing out because it's possible the user got distracted. In this case the
2686 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002687 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002688 return status;
2689 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002690 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2691 MYLOGI(
2692 "Did not receive user consent yet."
2693 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002694 const String16 incidentcompanion("incidentcompanion");
2695 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2696 if (ics != nullptr) {
2697 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2698 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2699 consent_callback_.get());
2700 } else {
2701 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2702 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002703 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002704 }
2705
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002706 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002707 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002708 for (int i = 0; i < 3; i++) {
2709 Vibrate(75);
2710 usleep((75 + 50) * 1000);
2711 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002712 }
2713
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002714 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2715 progress_->GetInitialMax());
2716 progress_->Save();
2717 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002718
Felipe Leme107a05f2016-03-08 15:11:15 -08002719 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002720 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002721 }
2722
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002723 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002724 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002725 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002726 }
2727
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002728 tombstone_data_.clear();
2729 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002730
Nandana Duttd2f5f082019-01-18 17:13:52 +00002731 return (consent_callback_ != nullptr &&
2732 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2733 ? USER_CONSENT_TIMED_OUT
2734 : RunStatus::OK;
2735}
2736
Paul Chang0d2aad72020-02-13 20:04:03 +08002737void Dumpstate::MaybeTakeEarlyScreenshot() {
2738 if (!options_->do_screenshot || !do_early_screenshot_) {
2739 return;
2740 }
2741
2742 TakeScreenshot();
2743}
2744
Paul Changc490e662020-04-11 18:14:09 +08002745void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
2746 const std::string& calling_package) {
2747 if (calling_uid == AID_SHELL || !CalledByApi()) {
2748 return;
2749 }
2750 if (listener_ != nullptr) {
2751 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2752 // handling if required.
2753 android::String16 package(calling_package.c_str());
2754 listener_->onUiIntensiveBugreportDumpsFinished(package);
2755 }
2756}
2757
Jichao Lie89d9c12019-11-21 19:02:51 -08002758void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2759 if (calling_uid == AID_SHELL || !CalledByApi()) {
2760 // No need to get consent for shell triggered dumpstates, or not through
2761 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002762 return;
2763 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002764 consent_callback_ = new ConsentCallback();
2765 const String16 incidentcompanion("incidentcompanion");
2766 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002767 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002768 if (ics != nullptr) {
2769 MYLOGD("Checking user consent via incidentcompanion service\n");
2770 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002771 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002772 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002773 } else {
2774 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2775 }
2776}
2777
Nandana Dutt5c390032019-03-12 10:52:56 +00002778bool Dumpstate::IsUserConsentDenied() const {
2779 return ds.consent_callback_ != nullptr &&
2780 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2781}
2782
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002783bool Dumpstate::CalledByApi() const {
2784 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2785}
2786
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002787void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002788 android::os::UnlinkAndLogOnError(tmp_path_);
2789 android::os::UnlinkAndLogOnError(screenshot_path_);
2790 android::os::UnlinkAndLogOnError(path_);
2791}
2792
2793Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2794 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002795 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00002796 return USER_CONSENT_DENIED;
2797}
2798
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002799Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002800 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002801 // user consent (unless the caller is Shell).
2802 UserConsentResult consent_result;
2803 if (calling_uid == AID_SHELL) {
2804 consent_result = UserConsentResult::APPROVED;
2805 } else {
2806 consent_result = consent_callback_->getResult();
2807 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002808 if (consent_result == UserConsentResult::UNAVAILABLE) {
2809 // User has not responded yet.
2810 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08002811 // Telephony is a fast report type, particularly on user builds where information may be
2812 // more aggressively limited. To give the user time to read the consent dialog, increase the
2813 // timeout.
2814 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
2815 : USER_CONSENT_TIMEOUT_MS;
2816 if (elapsed_ms < timeout_ms) {
2817 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00002818 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2819 sleep(delay_seconds);
2820 }
2821 consent_result = consent_callback_->getResult();
2822 }
2823 if (consent_result == UserConsentResult::DENIED) {
2824 // User has explicitly denied sharing with the app. To be safe delete the
2825 // internal bugreport & tmp files.
2826 return HandleUserConsentDenied();
2827 }
2828 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002829 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2830 if (copy_succeeded) {
2831 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01002832 if (options_->do_screenshot &&
2833 options_->screenshot_fd.get() != -1 &&
2834 !options_->is_screenshot_copied) {
2835 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2836 options_->screenshot_fd.get());
2837 options_->is_screenshot_copied = copy_succeeded;
2838 if (copy_succeeded) {
2839 android::os::UnlinkAndLogOnError(screenshot_path_);
2840 }
2841 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002842 }
2843 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2844 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2845 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2846 // Since we do not have user consent to share the bugreport it does not get
2847 // copied over to the calling app but remains in the internal directory from
2848 // where the user can manually pull it.
2849 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2850 }
2851 // Unknown result; must be a programming error.
2852 MYLOGE("Unknown user consent result:%d\n", consent_result);
2853 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002854}
2855
Nandana Duttf02564e2019-02-15 15:24:24 +00002856Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002857 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2858 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2859 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002860 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002861 // When directly running dumpstate binary, the output is not expected to be written
2862 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002863 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002864
2865 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002866 // an app; they are irrelevant here because bugreport is triggered via command line.
2867 // Update Last ID before calling Run().
2868 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00002869 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002870 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002871 return status;
2872}
2873
2874/* Main entry point for dumpstate binary. */
2875int run_main(int argc, char* argv[]) {
2876 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002877
2878 switch (status) {
2879 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002880 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002881 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002882 ShowUsage();
2883 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002884 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002885 fprintf(stderr, "Invalid combination of args\n");
2886 ShowUsage();
2887 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002888 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002889 FALLTHROUGH_INTENDED;
2890 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2891 FALLTHROUGH_INTENDED;
2892 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002893 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002894 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002895}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002896
2897// TODO(111441001): Default DumpOptions to sensible values.
2898Dumpstate::Dumpstate(const std::string& version)
2899 : pid_(getpid()),
2900 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01002901 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002902 version_(version),
2903 now_(time(nullptr)) {
2904}
2905
2906Dumpstate& Dumpstate::GetInstance() {
2907 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
2908 return singleton_;
2909}
2910
Nandana Dutt8d945c02019-08-14 13:30:07 +01002911DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
2912 : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002913 if (!title_.empty()) {
2914 started_ = Nanotime();
2915 }
2916}
2917
2918DurationReporter::~DurationReporter() {
2919 if (!title_.empty()) {
2920 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08002921 if (elapsed >= .5f || verbose_) {
2922 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002923 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08002924 if (!logcat_only_) {
2925 // Use "Yoda grammar" to make it easier to grep|sort sections.
2926 printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002927 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002928 }
2929}
2930
2931const int32_t Progress::kDefaultMax = 5000;
2932
2933Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
2934}
2935
2936Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
2937 : Progress(initial_max, growth_factor, "") {
2938 progress_ = progress;
2939}
2940
2941Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
2942 : initial_max_(initial_max),
2943 progress_(0),
2944 max_(initial_max),
2945 growth_factor_(growth_factor),
2946 n_runs_(0),
2947 average_max_(0),
2948 path_(path) {
2949 if (!path_.empty()) {
2950 Load();
2951 }
2952}
2953
2954void Progress::Load() {
2955 MYLOGD("Loading stats from %s\n", path_.c_str());
2956 std::string content;
2957 if (!android::base::ReadFileToString(path_, &content)) {
2958 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
2959 return;
2960 }
2961 if (content.empty()) {
2962 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
2963 return;
2964 }
2965 std::vector<std::string> lines = android::base::Split(content, "\n");
2966
2967 if (lines.size() < 1) {
2968 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
2969 (int)lines.size(), max_);
2970 return;
2971 }
2972 char* ptr;
2973 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
2974 average_max_ = strtol(ptr, nullptr, 10);
2975 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
2976 average_max_ > STATS_MAX_AVERAGE) {
2977 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
2978 initial_max_ = Progress::kDefaultMax;
2979 } else {
2980 initial_max_ = average_max_;
2981 }
2982 max_ = initial_max_;
2983
2984 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
2985}
2986
2987void Progress::Save() {
2988 int32_t total = n_runs_ * average_max_ + progress_;
2989 int32_t runs = n_runs_ + 1;
2990 int32_t average = floor(((float)total) / runs);
2991 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
2992 path_.c_str());
2993 if (path_.empty()) {
2994 return;
2995 }
2996
2997 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
2998 if (!android::base::WriteStringToFile(content, path_)) {
2999 MYLOGE("Could not save stats on %s\n", path_.c_str());
3000 }
3001}
3002
3003int32_t Progress::Get() const {
3004 return progress_;
3005}
3006
3007bool Progress::Inc(int32_t delta_sec) {
3008 bool changed = false;
3009 if (delta_sec >= 0) {
3010 progress_ += delta_sec;
3011 if (progress_ > max_) {
3012 int32_t old_max = max_;
3013 max_ = floor((float)progress_ * growth_factor_);
3014 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3015 changed = true;
3016 }
3017 }
3018 return changed;
3019}
3020
3021int32_t Progress::GetMax() const {
3022 return max_;
3023}
3024
3025int32_t Progress::GetInitialMax() const {
3026 return initial_max_;
3027}
3028
3029void Progress::Dump(int fd, const std::string& prefix) const {
3030 const char* pr = prefix.c_str();
3031 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3032 dprintf(fd, "%smax: %d\n", pr, max_);
3033 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3034 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3035 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3036 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3037 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3038}
3039
3040bool Dumpstate::IsZipping() const {
3041 return zip_writer_ != nullptr;
3042}
3043
3044std::string Dumpstate::GetPath(const std::string& suffix) const {
3045 return GetPath(bugreport_internal_dir_, suffix);
3046}
3047
3048std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3049 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3050 name_.c_str(), suffix.c_str());
3051}
3052
3053void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3054 progress_ = std::move(progress);
3055}
3056
3057void for_each_userid(void (*func)(int), const char *header) {
3058 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3059 "for_each_userid(%s)", header);
3060 DurationReporter duration_reporter(title);
3061 if (PropertiesHelper::IsDryRun()) return;
3062
3063 DIR *d;
3064 struct dirent *de;
3065
3066 if (header) printf("\n------ %s ------\n", header);
3067 func(0);
3068
3069 if (!(d = opendir("/data/system/users"))) {
3070 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3071 return;
3072 }
3073
3074 while ((de = readdir(d))) {
3075 int userid;
3076 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3077 continue;
3078 }
3079 func(userid);
3080 }
3081
3082 closedir(d);
3083}
3084
3085static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3086 DIR *d;
3087 struct dirent *de;
3088
3089 if (!(d = opendir("/proc"))) {
3090 printf("Failed to open /proc (%s)\n", strerror(errno));
3091 return;
3092 }
3093
3094 if (header) printf("\n------ %s ------\n", header);
3095 while ((de = readdir(d))) {
3096 if (ds.IsUserConsentDenied()) {
3097 MYLOGE(
3098 "Returning early because user denied consent to share bugreport with calling app.");
3099 closedir(d);
3100 return;
3101 }
3102 int pid;
3103 int fd;
3104 char cmdpath[255];
3105 char cmdline[255];
3106
3107 if (!(pid = atoi(de->d_name))) {
3108 continue;
3109 }
3110
3111 memset(cmdline, 0, sizeof(cmdline));
3112
3113 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3114 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3115 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3116 close(fd);
3117 if (cmdline[0]) {
3118 helper(pid, cmdline, arg);
3119 continue;
3120 }
3121 }
3122
3123 // if no cmdline, a kernel thread has comm
3124 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3125 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3126 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3127 close(fd);
3128 if (cmdline[1]) {
3129 cmdline[0] = '[';
3130 size_t len = strcspn(cmdline, "\f\b\r\n");
3131 cmdline[len] = ']';
3132 cmdline[len+1] = '\0';
3133 }
3134 }
3135 if (!cmdline[0]) {
3136 strcpy(cmdline, "N/A");
3137 }
3138 helper(pid, cmdline, arg);
3139 }
3140
3141 closedir(d);
3142}
3143
3144static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3145 for_each_pid_func *func = (for_each_pid_func*) arg;
3146 func(pid, cmdline);
3147}
3148
3149void for_each_pid(for_each_pid_func func, const char *header) {
3150 std::string title = header == nullptr ? "for_each_pid"
3151 : android::base::StringPrintf("for_each_pid(%s)", header);
3152 DurationReporter duration_reporter(title);
3153 if (PropertiesHelper::IsDryRun()) return;
3154
3155 __for_each_pid(for_each_pid_helper, header, (void *) func);
3156}
3157
3158static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3159 DIR *d;
3160 struct dirent *de;
3161 char taskpath[255];
3162 for_each_tid_func *func = (for_each_tid_func *) arg;
3163
3164 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3165
3166 if (!(d = opendir(taskpath))) {
3167 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3168 return;
3169 }
3170
3171 func(pid, pid, cmdline);
3172
3173 while ((de = readdir(d))) {
3174 if (ds.IsUserConsentDenied()) {
3175 MYLOGE(
3176 "Returning early because user denied consent to share bugreport with calling app.");
3177 closedir(d);
3178 return;
3179 }
3180 int tid;
3181 int fd;
3182 char commpath[255];
3183 char comm[255];
3184
3185 if (!(tid = atoi(de->d_name))) {
3186 continue;
3187 }
3188
3189 if (tid == pid)
3190 continue;
3191
3192 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3193 memset(comm, 0, sizeof(comm));
3194 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3195 strcpy(comm, "N/A");
3196 } else {
3197 char *c;
3198 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3199 close(fd);
3200
3201 c = strrchr(comm, '\n');
3202 if (c) {
3203 *c = '\0';
3204 }
3205 }
3206 func(pid, tid, comm);
3207 }
3208
3209 closedir(d);
3210}
3211
3212void for_each_tid(for_each_tid_func func, const char *header) {
3213 std::string title = header == nullptr ? "for_each_tid"
3214 : android::base::StringPrintf("for_each_tid(%s)", header);
3215 DurationReporter duration_reporter(title);
3216
3217 if (PropertiesHelper::IsDryRun()) return;
3218
3219 __for_each_pid(for_each_tid_helper, header, (void *) func);
3220}
3221
3222void show_wchan(int pid, int tid, const char *name) {
3223 if (PropertiesHelper::IsDryRun()) return;
3224
3225 char path[255];
3226 char buffer[255];
3227 int fd, ret, save_errno;
3228 char name_buffer[255];
3229
3230 memset(buffer, 0, sizeof(buffer));
3231
3232 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3233 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3234 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3235 return;
3236 }
3237
3238 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3239 save_errno = errno;
3240 close(fd);
3241
3242 if (ret < 0) {
3243 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3244 return;
3245 }
3246
3247 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3248 pid == tid ? 0 : 3, "", name);
3249
3250 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3251
3252 return;
3253}
3254
3255// print time in centiseconds
3256static void snprcent(char *buffer, size_t len, size_t spc,
3257 unsigned long long time) {
3258 static long hz; // cache discovered hz
3259
3260 if (hz <= 0) {
3261 hz = sysconf(_SC_CLK_TCK);
3262 if (hz <= 0) {
3263 hz = 1000;
3264 }
3265 }
3266
3267 // convert to centiseconds
3268 time = (time * 100 + (hz / 2)) / hz;
3269
3270 char str[16];
3271
3272 snprintf(str, sizeof(str), " %llu.%02u",
3273 time / 100, (unsigned)(time % 100));
3274 size_t offset = strlen(buffer);
3275 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3276 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3277}
3278
3279// print permille as a percent
3280static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3281 char str[16];
3282
3283 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3284 size_t offset = strlen(buffer);
3285 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3286 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3287}
3288
3289void show_showtime(int pid, const char *name) {
3290 if (PropertiesHelper::IsDryRun()) return;
3291
3292 char path[255];
3293 char buffer[1023];
3294 int fd, ret, save_errno;
3295
3296 memset(buffer, 0, sizeof(buffer));
3297
3298 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3299 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3300 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3301 return;
3302 }
3303
3304 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3305 save_errno = errno;
3306 close(fd);
3307
3308 if (ret < 0) {
3309 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3310 return;
3311 }
3312
3313 // field 14 is utime
3314 // field 15 is stime
3315 // field 42 is iotime
3316 unsigned long long utime = 0, stime = 0, iotime = 0;
3317 if (sscanf(buffer,
3318 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3319 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3320 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3321 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3322 &utime, &stime, &iotime) != 3) {
3323 return;
3324 }
3325
3326 unsigned long long total = utime + stime;
3327 if (!total) {
3328 return;
3329 }
3330
3331 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3332 if (permille > 1000) {
3333 permille = 1000;
3334 }
3335
3336 // try to beautify and stabilize columns at <80 characters
3337 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3338 if ((name[0] != '[') || utime) {
3339 snprcent(buffer, sizeof(buffer), 57, utime);
3340 }
3341 snprcent(buffer, sizeof(buffer), 65, stime);
3342 if ((name[0] != '[') || iotime) {
3343 snprcent(buffer, sizeof(buffer), 73, iotime);
3344 }
3345 if (iotime) {
3346 snprdec(buffer, sizeof(buffer), 79, permille);
3347 }
3348 puts(buffer); // adds a trailing newline
3349
3350 return;
3351}
3352
3353void do_dmesg() {
3354 const char *title = "KERNEL LOG (dmesg)";
3355 DurationReporter duration_reporter(title);
3356 printf("------ %s ------\n", title);
3357
3358 if (PropertiesHelper::IsDryRun()) return;
3359
3360 /* Get size of kernel buffer */
3361 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3362 if (size <= 0) {
3363 printf("Unexpected klogctl return value: %d\n\n", size);
3364 return;
3365 }
3366 char *buf = (char *) malloc(size + 1);
3367 if (buf == nullptr) {
3368 printf("memory allocation failed\n\n");
3369 return;
3370 }
3371 int retval = klogctl(KLOG_READ_ALL, buf, size);
3372 if (retval < 0) {
3373 printf("klogctl failure\n\n");
3374 free(buf);
3375 return;
3376 }
3377 buf[retval] = '\0';
3378 printf("%s\n\n", buf);
3379 free(buf);
3380 return;
3381}
3382
3383void do_showmap(int pid, const char *name) {
3384 char title[255];
3385 char arg[255];
3386
3387 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3388 snprintf(arg, sizeof(arg), "%d", pid);
3389 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3390}
3391
3392int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3393 DurationReporter duration_reporter(title);
3394
3395 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3396
3397 UpdateProgress(WEIGHT_FILE);
3398
3399 return status;
3400}
3401
3402int read_file_as_long(const char *path, long int *output) {
3403 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3404 if (fd < 0) {
3405 int err = errno;
3406 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3407 return -1;
3408 }
3409 char buffer[50];
3410 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3411 if (bytes_read == -1) {
3412 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3413 return -2;
3414 }
3415 if (bytes_read == 0) {
3416 MYLOGE("File %s is empty\n", path);
3417 return -3;
3418 }
3419 *output = atoi(buffer);
3420 return 0;
3421}
3422
3423/* calls skip to gate calling dump_from_fd recursively
3424 * in the specified directory. dump_from_fd defaults to
3425 * dump_file_from_fd above when set to NULL. skip defaults
3426 * to false when set to NULL. dump_from_fd will always be
3427 * called with title NULL.
3428 */
3429int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3430 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3431 DurationReporter duration_reporter(title);
3432 DIR *dirp;
3433 struct dirent *d;
3434 char *newpath = nullptr;
3435 const char *slash = "/";
3436 int retval = 0;
3437
3438 if (!title.empty()) {
3439 printf("------ %s (%s) ------\n", title.c_str(), dir);
3440 }
3441 if (PropertiesHelper::IsDryRun()) return 0;
3442
3443 if (dir[strlen(dir) - 1] == '/') {
3444 ++slash;
3445 }
3446 dirp = opendir(dir);
3447 if (dirp == nullptr) {
3448 retval = -errno;
3449 MYLOGE("%s: %s\n", dir, strerror(errno));
3450 return retval;
3451 }
3452
3453 if (!dump_from_fd) {
3454 dump_from_fd = dump_file_from_fd;
3455 }
3456 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3457 if ((d->d_name[0] == '.')
3458 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3459 || (d->d_name[1] == '\0'))) {
3460 continue;
3461 }
3462 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3463 (d->d_type == DT_DIR) ? "/" : "");
3464 if (!newpath) {
3465 retval = -errno;
3466 continue;
3467 }
3468 if (skip && (*skip)(newpath)) {
3469 continue;
3470 }
3471 if (d->d_type == DT_DIR) {
3472 int ret = dump_files("", newpath, skip, dump_from_fd);
3473 if (ret < 0) {
3474 retval = ret;
3475 }
3476 continue;
3477 }
3478 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3479 if (fd.get() < 0) {
3480 retval = -1;
3481 printf("*** %s: %s\n", newpath, strerror(errno));
3482 continue;
3483 }
3484 (*dump_from_fd)(nullptr, newpath, fd.get());
3485 }
3486 closedir(dirp);
3487 if (!title.empty()) {
3488 printf("\n");
3489 }
3490 return retval;
3491}
3492
3493/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3494 * it's possible to avoid issues where opening the file itself can get
3495 * stuck.
3496 */
3497int dump_file_from_fd(const char *title, const char *path, int fd) {
3498 if (PropertiesHelper::IsDryRun()) return 0;
3499
3500 int flags = fcntl(fd, F_GETFL);
3501 if (flags == -1) {
3502 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3503 return -1;
3504 } else if (!(flags & O_NONBLOCK)) {
3505 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3506 return -1;
3507 }
3508 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3509}
3510
3511int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +01003512 const CommandOptions& options, bool verbose_duration) {
3513 DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003514
3515 int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
3516
3517 /* TODO: for now we're simplifying the progress calculation by using the
3518 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3519 * where its weight should be much higher proportionally to its timeout.
3520 * Ideally, it should use a options.EstimatedDuration() instead...*/
3521 UpdateProgress(options.Timeout());
3522
3523 return status;
3524}
3525
3526void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3527 const CommandOptions& options, long dumpsysTimeoutMs) {
3528 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3529 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3530 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3531 RunCommand(title, dumpsys, options);
3532}
3533
3534int open_socket(const char *service) {
3535 int s = android_get_control_socket(service);
3536 if (s < 0) {
3537 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3538 return -1;
3539 }
3540 fcntl(s, F_SETFD, FD_CLOEXEC);
3541
3542 // Set backlog to 0 to make sure that queue size will be minimum.
3543 // In Linux, because the minimum queue will be 1, connect() will be blocked
3544 // if the other clients already called connect() and the connection request was not accepted.
3545 if (listen(s, 0) < 0) {
3546 MYLOGE("listen(control socket): %s\n", strerror(errno));
3547 return -1;
3548 }
3549
3550 struct sockaddr addr;
3551 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003552 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003553
3554 // Close socket just after accept(), to make sure that connect() by client will get error
3555 // when the socket is used by the other services.
3556 // There is still a race condition possibility between accept and close, but there is no way
3557 // to close-on-accept atomically.
3558 // See detail; b/123306389#comment25
3559 close(s);
3560
3561 if (fd < 0) {
3562 MYLOGE("accept(control socket): %s\n", strerror(errno));
3563 return -1;
3564 }
3565
3566 return fd;
3567}
3568
3569/* redirect output to a service control socket */
3570bool redirect_to_socket(FILE* redirect, const char* service) {
3571 int fd = open_socket(service);
3572 if (fd == -1) {
3573 return false;
3574 }
3575 fflush(redirect);
3576 // TODO: handle dup2 failure
3577 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3578 close(fd);
3579 return true;
3580}
3581
3582// TODO: should call is_valid_output_file and/or be merged into it.
3583void create_parent_dirs(const char *path) {
3584 char *chp = const_cast<char *> (path);
3585
3586 /* skip initial slash */
3587 if (chp[0] == '/')
3588 chp++;
3589
3590 /* create leading directories, if necessary */
3591 struct stat dir_stat;
3592 while (chp && chp[0]) {
3593 chp = strchr(chp, '/');
3594 if (chp) {
3595 *chp = 0;
3596 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3597 MYLOGI("Creating directory %s\n", path);
3598 if (mkdir(path, 0770)) { /* drwxrwx--- */
3599 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3600 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3601 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3602 }
3603 }
3604 *chp++ = '/';
3605 }
3606 }
3607}
3608
3609bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3610 create_parent_dirs(path);
3611
3612 int fd = TEMP_FAILURE_RETRY(open(path,
3613 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3614 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3615 if (fd < 0) {
3616 MYLOGE("%s: %s\n", path, strerror(errno));
3617 return false;
3618 }
3619
3620 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3621 close(fd);
3622 return true;
3623}
3624
3625bool redirect_to_file(FILE* redirect, char* path) {
3626 return _redirect_to_file(redirect, path, O_TRUNC);
3627}
3628
3629bool redirect_to_existing_file(FILE* redirect, char* path) {
3630 return _redirect_to_file(redirect, path, O_APPEND);
3631}
3632
3633void dump_route_tables() {
3634 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3635 if (PropertiesHelper::IsDryRun()) return;
3636 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3637 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3638 FILE* fp = fopen(RT_TABLES_PATH, "re");
3639 if (!fp) {
3640 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3641 return;
3642 }
3643 char table[16];
3644 // Each line has an integer (the table number), a space, and a string (the table name). We only
3645 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3646 // Add a fixed max limit so this doesn't go awry.
3647 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3648 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3649 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3650 }
3651 fclose(fp);
3652}
3653
3654// TODO: make this function thread safe if sections are generated in parallel.
3655void Dumpstate::UpdateProgress(int32_t delta_sec) {
3656 if (progress_ == nullptr) {
3657 MYLOGE("UpdateProgress: progress_ not set\n");
3658 return;
3659 }
3660
3661 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01003662 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003663
3664 // ...but only notifiy listeners when necessary.
3665 if (!options_->do_progress_updates) return;
3666
3667 int progress = progress_->Get();
3668 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01003669 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003670
Nandana Dutt402a8392019-06-14 14:25:13 +01003671 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003672 return;
3673 }
Nandana Dutt402a8392019-06-14 14:25:13 +01003674 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003675
3676 if (control_socket_fd_ >= 0) {
3677 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3678 fsync(control_socket_fd_);
3679 }
3680
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003681 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003682 if (percent % 10 == 0) {
3683 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003684 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003685 } else {
3686 // stderr is ignored on normal invocations, but useful when calling
3687 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003688 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003689 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003690
3691 listener_->onProgress(percent);
3692 }
3693}
3694
3695void Dumpstate::TakeScreenshot(const std::string& path) {
3696 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3697 int status =
3698 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3699 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3700 if (status == 0) {
3701 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3702 } else {
3703 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3704 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003705 if (listener_ != nullptr) {
3706 // Show a visual indication to indicate screenshot is taken via
3707 // IDumpstateListener.onScreenshotTaken()
3708 listener_->onScreenshotTaken(status == 0);
3709 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003710}
3711
3712bool is_dir(const char* pathname) {
3713 struct stat info;
3714 if (stat(pathname, &info) == -1) {
3715 return false;
3716 }
3717 return S_ISDIR(info.st_mode);
3718}
3719
3720time_t get_mtime(int fd, time_t default_mtime) {
3721 struct stat info;
3722 if (fstat(fd, &info) == -1) {
3723 return default_mtime;
3724 }
3725 return info.st_mtime;
3726}