blob: 942c16cd0a50162e5ac72b65256325f1fab7af36 [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
mhasankd451a472020-05-26 18:02:39 -07001370static void DumpstateLimitedOnly() {
1371 // Trimmed-down version of dumpstate to only include a whitelisted
1372 // set of logs (system log, event log, and system server / system app
1373 // crashes, and networking logs). See b/136273873 and b/138459828
1374 // for context.
1375 DurationReporter duration_reporter("DUMPSTATE");
1376 unsigned long timeout_ms;
1377 // calculate timeout
1378 timeout_ms = logcat_timeout({"main", "system", "crash"});
1379 RunCommand("SYSTEM LOG",
1380 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1381 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1382 timeout_ms = logcat_timeout({"events"});
1383 RunCommand(
1384 "EVENT LOG",
1385 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
1386 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
1387
1388 printf("========================================================\n");
1389 printf("== Networking Service\n");
1390 printf("========================================================\n");
1391
1392 RunDumpsys("DUMPSYS NETWORK_SERVICE_LIMITED", {"wifi", "-a"},
1393 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1394
1395 printf("========================================================\n");
1396 printf("== Dropbox crashes\n");
1397 printf("========================================================\n");
1398
1399 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1400 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1401
1402 printf("========================================================\n");
1403 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1404 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1405 printf("========================================================\n");
1406 printf("== dumpstate: done (id %d)\n", ds.id_);
1407 printf("========================================================\n");
1408}
1409
Nandana Dutt5c390032019-03-12 10:52:56 +00001410// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1411// via the consent they are shown. Ignores other errors that occur while running various
1412// commands. The consent checking is currently done around long running tasks, which happen to
1413// be distributed fairly evenly throughout the function.
1414static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001415 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001416
Nandana Dutt5c390032019-03-12 10:52:56 +00001417 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1418 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1419 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001420 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001421 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001422 DumpBlockStatFiles();
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001423 DumpFile("MEMORY INFO", "/proc/meminfo");
1424 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001425 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001426
1427 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1428
Sunny Goyal35949782019-11-19 15:54:36 -08001429 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpVisibleWindowViews);
1430
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001431 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1432 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1433 DumpFile("SLAB INFO", "/proc/slabinfo");
1434 DumpFile("ZONEINFO", "/proc/zoneinfo");
1435 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1436 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001437 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001438
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001439 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1440 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001441
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001442 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001443 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001444
1445 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1446 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001447
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001448 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001449
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001450 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001451 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001452 struct stat s;
1453 if (stat("/proc/modules", &s) != 0) {
1454 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1455 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001456 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001457 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001458
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001459 if (__android_logger_property_get_bool(
1460 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1461 DoKernelLogcat();
1462 } else {
1463 do_dmesg();
1464 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001465
Felipe Lemef0292972016-11-22 13:57:05 -08001466 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001467
1468 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1469
Jeff Brown1dc94e32014-09-11 14:15:27 -07001470 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001471 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001472
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001473 /* Dump Bluetooth HCI logs */
1474 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001475
Paul Chang0d2aad72020-02-13 20:04:03 +08001476 if (ds.options_->do_screenshot && !ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001477 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001478 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001479 }
1480
Felipe Lemee184f662016-10-27 10:04:47 -07001481 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001482
Narayan Kamath8f788292017-05-25 13:20:39 +01001483 // NOTE: tombstones are always added as separate entries in the zip archive
1484 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001485 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001486 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001487 if (!tombstones_dumped) {
1488 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001489 }
1490
Jayachandran Ca94c7172017-06-10 15:08:12 -07001491 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001492
Chenbo Feng276a3b62018-08-07 11:44:49 -07001493 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1494
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001495 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001496
Jayachandran Ca94c7172017-06-10 15:08:12 -07001497 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001498
1499 dump_route_tables();
1500
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001501 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1502 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1503 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001504
Nandana Dutt5c390032019-03-12 10:52:56 +00001505 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001506
Elliott Hughes23ccc622017-02-28 10:14:22 -08001507 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001508
Jin Qianf334d662017-10-10 14:41:37 -07001509 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001510
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001511 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001512
Colin Crossf45fa6b2012-03-26 12:38:26 -07001513 /* Binder state is expensive to look at as it uses a lot of memory. */
Hridya Valsaraju920ba712020-02-09 16:27:01 -08001514 std::string binder_logs_dir = access("/dev/binderfs/binder_logs", R_OK) ?
1515 "/sys/kernel/debug/binder" : "/dev/binderfs/binder_logs";
1516
1517 DumpFile("BINDER FAILED TRANSACTION LOG", binder_logs_dir + "/failed_transaction_log");
1518 DumpFile("BINDER TRANSACTION LOG", binder_logs_dir + "/transaction_log");
1519 DumpFile("BINDER TRANSACTIONS", binder_logs_dir + "/transactions");
1520 DumpFile("BINDER STATS", binder_logs_dir + "/stats");
1521 DumpFile("BINDER STATE", binder_logs_dir + "/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001522
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001523 /* Add window and surface trace files. */
1524 if (!PropertiesHelper::IsUserBuild()) {
1525 ds.AddDir(WMTRACE_DATA_DIR, false);
1526 }
1527
Yifan Hongd90cc652020-02-08 16:52:02 -08001528 ds.AddDir(SNAPSHOTCTL_LOG_DIR, false);
1529
Nandana Dutt5c390032019-03-12 10:52:56 +00001530 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001531
Steven Moreland7440ddb2016-12-15 16:13:39 -08001532 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001533 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1534 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001535 // su does not exist on user builds, so try running without it.
1536 // This way any implementations of vril-dump that do not require
1537 // root can run on user builds.
1538 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001539 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001540 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001541 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001542 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001543 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001544 }
1545
Felipe Lemed8b94e52016-12-08 10:21:44 -08001546 printf("========================================================\n");
1547 printf("== Android Framework Services\n");
1548 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001549
Nandana Dutt5c390032019-03-12 10:52:56 +00001550 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001551
Felipe Lemed8b94e52016-12-08 10:21:44 -08001552 printf("========================================================\n");
1553 printf("== Checkins\n");
1554 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001555
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001556 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001557
1558 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1559
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001560 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1561 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1562 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1563 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001564
Felipe Lemed8b94e52016-12-08 10:21:44 -08001565 printf("========================================================\n");
1566 printf("== Running Application Activities\n");
1567 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001568
Makoto Onuki60780982018-04-16 15:34:00 -07001569 // The following dumpsys internally collects output from running apps, so it can take a long
1570 // time. So let's extend the timeout.
1571
1572 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1573
1574 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001575
Felipe Lemed8b94e52016-12-08 10:21:44 -08001576 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001577 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001578 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001579
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001580 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001581 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001582
Felipe Lemed8b94e52016-12-08 10:21:44 -08001583 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001584 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001585 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001586
Makoto Onuki60780982018-04-16 15:34:00 -07001587 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1588 DUMPSYS_COMPONENTS_OPTIONS);
1589
1590 printf("========================================================\n");
1591 printf("== Running Application Providers (platform)\n");
1592 printf("========================================================\n");
1593
1594 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1595 DUMPSYS_COMPONENTS_OPTIONS);
1596
1597 printf("========================================================\n");
1598 printf("== Running Application Providers (non-platform)\n");
1599 printf("========================================================\n");
1600
1601 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1602 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001603
Adrian Roos8b397ab2017-04-04 16:35:44 -07001604 printf("========================================================\n");
1605 printf("== Dropbox crashes\n");
1606 printf("========================================================\n");
1607
1608 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1609 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1610
Felipe Lemed8b94e52016-12-08 10:21:44 -08001611 printf("========================================================\n");
1612 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1613 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1614 printf("========================================================\n");
1615 printf("== dumpstate: done (id %d)\n", ds.id_);
1616 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001617
1618 printf("========================================================\n");
1619 printf("== Obtaining statsd metadata\n");
1620 printf("========================================================\n");
1621 // This differs from the usual dumpsys stats, which is the stats report data.
1622 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Mike Ma5c267872019-08-21 11:31:34 -07001623
Kiyoung Kimc2d22ac2020-02-04 19:43:36 +09001624 // Add linker configuration directory
1625 ds.AddDir(LINKERCONFIG_DIR, true);
1626
Mike Ma5c267872019-08-21 11:31:34 -07001627 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(DumpIncidentReport);
1628
Nandana Dutt5c390032019-03-12 10:52:56 +00001629 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001630}
1631
Nandana Dutt5c390032019-03-12 10:52:56 +00001632/*
1633 * Dumps state for the default case; drops root after it's no longer necessary.
1634 *
1635 * Returns RunStatus::OK if everything went fine.
1636 * Returns RunStatus::ERROR if there was an error.
1637 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1638 * with the caller.
1639 */
Jichao Lie89d9c12019-11-21 19:02:51 -08001640Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
Nandana Duttdb379fa2019-10-09 16:54:41 +01001641 // Capture first logcat early on; useful to take a snapshot before dumpstate logs take over the
1642 // buffer.
1643 DoLogcat();
1644 // Capture timestamp after first logcat to use in next logcat
1645 time_t logcat_ts = time(nullptr);
1646
Nandana Dutt4be45d12018-09-26 15:04:23 +01001647 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001648 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001649
1650 /* Run some operations that require root. */
1651 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1652 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1653
1654 ds.AddDir(RECOVERY_DIR, true);
1655 ds.AddDir(RECOVERY_DATA_DIR, true);
1656 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1657 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1658 if (!PropertiesHelper::IsUserBuild()) {
1659 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1660 ds.AddDir(PROFILE_DATA_DIR_REF, true);
Calin Juravlef84d3692020-04-28 15:31:12 -07001661 ds.AddZipEntry(ZIP_ROOT_DIR + PACKAGE_DEX_USE_LIST, PACKAGE_DEX_USE_LIST);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001662 }
Jerry Changa1df8a92020-01-02 16:03:39 +08001663 ds.AddDir(PREREBOOT_DATA_DIR, false);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001664 add_mountinfo();
1665 DumpIpTablesAsRoot();
David Andersond9ba4752018-12-11 18:26:59 -08001666 DumpDynamicPartitionInfo();
Yifan Hong3945e1b2019-10-29 12:59:23 -07001667 ds.AddDir(OTA_METADATA_DIR, true);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001668
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001669 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001670 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1671
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001672 // Dump IPsec stats. No keys are exposed here.
1673 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1674
Nandana Dutt4be45d12018-09-26 15:04:23 +01001675 // Run ss as root so we can see socket marks.
1676 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1677
1678 // Run iotop as root to show top 100 IO threads
1679 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1680
Erick Reyese68df822019-02-11 14:46:36 -08001681 // Gather shared memory buffer info if the product implements it
1682 struct stat st;
1683 if (!stat("/product/bin/dmabuf_dump", &st)) {
1684 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1685 }
1686
Minchan Kim22c6a1e2019-09-30 15:58:10 -07001687 DumpFile("PSI cpu", "/proc/pressure/cpu");
1688 DumpFile("PSI memory", "/proc/pressure/memory");
1689 DumpFile("PSI io", "/proc/pressure/io");
1690
Nandana Dutt4be45d12018-09-26 15:04:23 +01001691 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001692 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001693 }
1694
Nandana Dutt5c390032019-03-12 10:52:56 +00001695 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttdb379fa2019-10-09 16:54:41 +01001696 Dumpstate::RunStatus status = dumpstate();
1697 // Capture logcat since the last time we did it.
1698 DoSystemLogcat(logcat_ts);
1699 return status;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001700}
1701
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001702// This method collects common dumpsys for telephony and wifi. Typically, wifi
1703// reports are fine to include all information, but telephony reports on user
1704// builds need to strip some content (see DumpstateTelephonyOnly).
1705static void DumpstateRadioCommon(bool include_sensitive_info = true) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001706 DumpIpTablesAsRoot();
1707
Jayachandran Cb4389d92019-07-08 09:46:05 -07001708 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1709
Jayachandran Ca94c7172017-06-10 15:08:12 -07001710 if (!DropRootUser()) {
1711 return;
1712 }
1713
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001714 // We need to be picky about some stuff for telephony reports on user builds.
1715 if (!include_sensitive_info) {
1716 // Only dump the radio log buffer (other buffers and dumps contain too much unrelated info).
1717 DoRadioLogcat();
1718 } else {
1719 // Contains various system properties and process startup info.
1720 do_dmesg();
1721 // Logs other than the radio buffer may contain package/component names and potential PII.
1722 DoLogcat();
1723 // Too broad for connectivity problems.
1724 DoKmsg();
1725 // Contains unrelated hardware info (camera, NFC, biometrics, ...).
1726 DumpHals();
1727 }
1728
Jayachandran Ca94c7172017-06-10 15:08:12 -07001729 DumpPacketStats();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001730 DumpIpAddrAndRules();
1731 dump_route_tables();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001732 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1733 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001734}
1735
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001736// We use "telephony" here for legacy reasons, though this now really means "connectivity" (cellular
1737// + wifi + networking). This method collects dumpsys for connectivity debugging only. General rules
1738// for what can be included on user builds: all reported information MUST directly relate to
1739// connectivity debugging or customer support and MUST NOT contain unrelated personally identifiable
1740// information. This information MUST NOT identify user-installed packages (UIDs are OK, package
1741// names are not), and MUST NOT contain logs of user application traffic.
1742// TODO(b/148168577) rename this and other related fields/methods to "connectivity" instead.
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001743static void DumpstateTelephonyOnly(const std::string& calling_package) {
mukesh agrawal253dad42018-01-23 21:59:59 -08001744 DurationReporter duration_reporter("DUMPSTATE");
Jichao Lie89d9c12019-11-21 19:02:51 -08001745
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001746 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001747
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001748 const bool include_sensitive_info = !PropertiesHelper::IsUserBuild();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001749
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001750 DumpstateRadioCommon(include_sensitive_info);
1751
1752 if (include_sensitive_info) {
1753 // Contains too much unrelated PII, and given the unstructured nature of sysprops, we can't
1754 // really cherrypick all of the connectivity-related ones. Apps generally have no business
1755 // reading these anyway, and there should be APIs to supply the info in a more app-friendly
1756 // way.
1757 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1758 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001759
1760 printf("========================================================\n");
1761 printf("== Android Framework Services\n");
1762 printf("========================================================\n");
1763
Vishnu Nair652cc802017-11-30 15:18:30 -08001764 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1765 SEC_TO_MSEC(10));
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08001766 if (include_sensitive_info) {
1767 // Carrier apps' services will be dumped below in dumpsys activity service all-non-platform.
1768 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1769 SEC_TO_MSEC(10));
1770 } else {
1771 // If the caller is a carrier app and has a carrier service, dump it here since we aren't
1772 // running dumpsys activity service all-non-platform below. Due to the increased output, we
1773 // give a higher timeout as well.
1774 RunDumpsys("DUMPSYS", {"carrier_config", "--requesting-package", calling_package},
1775 CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(30));
1776 }
1777 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001778 RunDumpsys("DUMPSYS", {"netpolicy"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1779 RunDumpsys("DUMPSYS", {"network_management"}, CommandOptions::WithTimeout(90).Build(),
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001780 SEC_TO_MSEC(10));
Hunter Knepshield0fe51b12020-03-05 16:58:20 -08001781 RunDumpsys("DUMPSYS", {"telephony.registry"}, CommandOptions::WithTimeout(90).Build(),
1782 SEC_TO_MSEC(10));
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001783 if (include_sensitive_info) {
1784 // Contains raw IP addresses, omit from reports on user builds.
1785 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
1786 // Contains raw destination IP/MAC addresses, omit from reports on user builds.
1787 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1788 SEC_TO_MSEC(10));
1789 // Contains package/component names, omit from reports on user builds.
1790 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1791 SEC_TO_MSEC(10));
1792 // Contains package names, but should be relatively simple to remove them (also contains
1793 // UIDs already), omit from reports on user builds.
1794 RunDumpsys("BATTERYSTATS", {"deviceidle"}, CommandOptions::WithTimeout(90).Build(),
1795 SEC_TO_MSEC(10));
1796 }
Jayachandran Ca94c7172017-06-10 15:08:12 -07001797
1798 printf("========================================================\n");
1799 printf("== Running Application Services\n");
1800 printf("========================================================\n");
1801
1802 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1803
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001804 if (include_sensitive_info) {
1805 printf("========================================================\n");
1806 printf("== Running Application Services (non-platform)\n");
1807 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001808
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001809 // Contains package/component names and potential PII, omit from reports on user builds.
1810 // To get dumps of the active CarrierService(s) on user builds, we supply an argument to the
1811 // carrier_config dumpsys instead.
1812 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1813 DUMPSYS_COMPONENTS_OPTIONS);
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001814
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001815 printf("========================================================\n");
1816 printf("== Checkins\n");
1817 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001818
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08001819 // Contains package/component names, omit from reports on user builds.
1820 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1821 }
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001822
1823 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001824 printf("== dumpstate: done (id %d)\n", ds.id_);
1825 printf("========================================================\n");
1826}
1827
mukesh agrawal253dad42018-01-23 21:59:59 -08001828// This method collects dumpsys for wifi debugging only
1829static void DumpstateWifiOnly() {
1830 DurationReporter duration_reporter("DUMPSTATE");
1831
1832 DumpstateRadioCommon();
1833
1834 printf("========================================================\n");
1835 printf("== Android Framework Services\n");
1836 printf("========================================================\n");
1837
1838 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1839 SEC_TO_MSEC(10));
1840 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1841 SEC_TO_MSEC(10));
1842
1843 printf("========================================================\n");
1844 printf("== dumpstate: done (id %d)\n", ds.id_);
1845 printf("========================================================\n");
1846}
1847
Nandana Duttcf419a72019-03-14 10:40:17 +00001848Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001849 DurationReporter duration_reporter("DUMP TRACES");
1850
1851 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1852 const size_t buf_size = temp_file_pattern.length() + 1;
1853 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1854 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1855
1856 // Create a new, empty file to receive all trace dumps.
1857 //
1858 // TODO: This can be simplified once we remove support for the old style
1859 // dumps. We can have a file descriptor passed in to dump_traces instead
1860 // of creating a file, closing it and then reopening it again.
1861 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1862 if (fd < 0) {
1863 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001864 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001865 }
1866
1867 // Nobody should have access to this temporary file except dumpstate, but we
1868 // temporarily grant 'read' to 'others' here because this file is created
1869 // when tombstoned is still running as root, but dumped after dropping. This
1870 // can go away once support for old style dumping has.
1871 const int chmod_ret = fchmod(fd, 0666);
1872 if (chmod_ret < 0) {
1873 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001874 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001875 }
1876
1877 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1878 if (proc.get() == nullptr) {
1879 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001880 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001881 }
1882
1883 // Number of times process dumping has timed out. If we encounter too many
1884 // failures, we'll give up.
1885 int timeout_failures = 0;
1886 bool dalvik_found = false;
1887
1888 const std::set<int> hal_pids = get_interesting_hal_pids();
1889
1890 struct dirent* d;
1891 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001892 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001893 int pid = atoi(d->d_name);
1894 if (pid <= 0) {
1895 continue;
1896 }
1897
1898 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1899 std::string exe;
1900 if (!android::base::Readlink(link_name, &exe)) {
1901 continue;
1902 }
1903
1904 bool is_java_process;
1905 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1906 // Don't bother dumping backtraces for the zygote.
1907 if (IsZygote(pid)) {
1908 continue;
1909 }
1910
1911 dalvik_found = true;
1912 is_java_process = true;
1913 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1914 is_java_process = false;
1915 } else {
1916 // Probably a native process we don't care about, continue.
1917 continue;
1918 }
1919
1920 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1921 if (timeout_failures == 3) {
1922 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1923 break;
1924 }
1925
1926 const uint64_t start = Nanotime();
1927 const int ret = dump_backtrace_to_file_timeout(
1928 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1929 is_java_process ? 5 : 20, fd);
1930
1931 if (ret == -1) {
1932 // For consistency, the header and footer to this message match those
1933 // dumped by debuggerd in the success case.
1934 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1935 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1936 dprintf(fd, "---- end %d ----", pid);
1937 timeout_failures++;
1938 continue;
1939 }
1940
1941 // We've successfully dumped stack traces, reset the failure count
1942 // and write a summary of the elapsed time to the file and continue with the
1943 // next process.
1944 timeout_failures = 0;
1945
1946 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1947 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1948 }
1949
1950 if (!dalvik_found) {
1951 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1952 }
1953
Nandana Duttcf419a72019-03-14 10:40:17 +00001954 *path = file_name_buf.release();
1955 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001956}
1957
Felipe Leme6f674ae2016-11-18 17:10:33 -08001958void Dumpstate::DumpstateBoard() {
1959 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001960 printf("========================================================\n");
1961 printf("== Board\n");
1962 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001963
Felipe Leme6f674ae2016-11-18 17:10:33 -08001964 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001965 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001966 return;
1967 }
1968
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001969 std::vector<std::string> paths;
1970 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001971 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001972 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1973 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001974 remover.emplace_back(android::base::make_scope_guard(
1975 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001976 }
Jie Song9fbfad02017-06-20 16:29:42 -07001977
Hunter Knepshield8540faf2020-02-04 19:47:20 -08001978 sp<IDumpstateDevice_1_0> dumpstate_device_1_0(IDumpstateDevice_1_0::getService());
1979 if (dumpstate_device_1_0 == nullptr) {
Wei Wang587eac92018-04-05 12:17:20 -07001980 MYLOGE("No IDumpstateDevice implementation\n");
1981 return;
1982 }
1983
1984 using ScopedNativeHandle =
1985 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1986 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1987 [](native_handle_t* handle) {
1988 native_handle_close(handle);
1989 native_handle_delete(handle);
1990 });
1991 if (handle == nullptr) {
1992 MYLOGE("Could not create native_handle\n");
1993 return;
1994 }
1995
Nandana Dutt5c390032019-03-12 10:52:56 +00001996 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001997 for (size_t i = 0; i < paths.size(); i++) {
1998 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1999
2000 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
2001 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
2002 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
2003 if (fd < 0) {
2004 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
2005 return;
2006 }
2007 handle.get()->data[i] = fd.release();
2008 }
2009
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002010 // Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
2011 // of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
2012 // will kill the HAL and grab whatever it dumped in time.
2013 constexpr size_t timeout_sec = 30;
2014 // Prefer version 1.1 if available. New devices launching with R are no longer allowed to
2015 // implement just 1.0.
2016 const char* descriptor_to_kill;
2017 using DumpstateBoardTask = std::packaged_task<bool()>;
2018 DumpstateBoardTask dumpstate_board_task;
2019 sp<IDumpstateDevice_1_1> dumpstate_device_1_1(
2020 IDumpstateDevice_1_1::castFrom(dumpstate_device_1_0));
2021 if (dumpstate_device_1_1 != nullptr) {
2022 MYLOGI("Using IDumpstateDevice v1.1");
2023 descriptor_to_kill = IDumpstateDevice_1_1::descriptor;
2024 dumpstate_board_task = DumpstateBoardTask([this, dumpstate_device_1_1, &handle]() -> bool {
2025 ::android::hardware::Return<DumpstateStatus> status =
2026 dumpstate_device_1_1->dumpstateBoard_1_1(handle.get(), options_->dumpstate_hal_mode,
2027 SEC_TO_MSEC(timeout_sec));
2028 if (!status.isOk()) {
2029 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
2030 return false;
2031 } else if (status != DumpstateStatus::OK) {
2032 MYLOGE("dumpstateBoard failed with DumpstateStatus::%s\n", toString(status).c_str());
2033 return false;
2034 }
2035 return true;
2036 });
2037 } else {
2038 MYLOGI("Using IDumpstateDevice v1.0");
2039 descriptor_to_kill = IDumpstateDevice_1_0::descriptor;
2040 dumpstate_board_task = DumpstateBoardTask([dumpstate_device_1_0, &handle]() -> bool {
2041 ::android::hardware::Return<void> status =
2042 dumpstate_device_1_0->dumpstateBoard(handle.get());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002043 if (!status.isOk()) {
2044 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07002045 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002046 }
Wei Wang587eac92018-04-05 12:17:20 -07002047 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002048 });
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002049 }
2050 auto result = dumpstate_board_task.get_future();
2051 std::thread(std::move(dumpstate_board_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07002052
Wei Wang587eac92018-04-05 12:17:20 -07002053 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
2054 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002055 if (!android::base::SetProperty(
2056 "ctl.interface_restart",
2057 android::base::StringPrintf("%s/default", descriptor_to_kill))) {
Wei Wang587eac92018-04-05 12:17:20 -07002058 MYLOGE("Couldn't restart dumpstate HAL\n");
2059 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002060 }
Wei Wang587eac92018-04-05 12:17:20 -07002061 // Wait some time for init to kill dumpstate vendor HAL
2062 constexpr size_t killing_timeout_sec = 10;
2063 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
2064 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
2065 "there might be racing in content\n", killing_timeout_sec);
2066 }
2067
2068 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
2069 for (size_t i = 0; i < paths.size(); i++) {
2070 struct stat s;
2071 if (fstat(handle.get()->data[i], &s) == -1) {
2072 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
2073 strerror(errno));
2074 file_sizes[i] = -1;
2075 continue;
2076 }
2077 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002078 }
2079
2080 for (size_t i = 0; i < paths.size(); i++) {
2081 if (file_sizes[i] == -1) {
2082 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002083 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002084 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07002085 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002086 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07002087 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07002088 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002089 printf("*** See %s entry ***\n", kDumpstateBoardFiles[i].c_str());
Jie Song9fbfad02017-06-20 16:29:42 -07002090 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08002091}
2092
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002093static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002094 fprintf(stderr,
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002095 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-d] [-p] "
mhasankd451a472020-05-26 18:02:39 -07002096 "[-z] [-s] [-S] [-q] [-P] [-R] [-L] [-V version]\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002097 " -h: display this help message\n"
2098 " -b: play sound file instead of vibrate, at beginning of job\n"
2099 " -e: play sound file instead of vibrate, at end of job\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002100 " -d: append date to filename\n"
2101 " -p: capture screenshot to filename.png\n"
2102 " -z: generate zipped file\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002103 " -s: write output to control socket (for init)\n"
Abhijeet Kaurbb55a3b2019-06-13 18:07:25 +01002104 " -S: write file location to control socket (for init; requires -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002105 " -q: disable vibrate\n"
Abhijeet Kaure370d682019-10-01 16:49:30 +01002106 " -P: send broadcast when started and do progress updates\n"
2107 " -R: take bugreport in remote mode (requires -z and -d, shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00002108 " -w: start binder service and make it wait for a call to startBugreport\n"
mhasankd451a472020-05-26 18:02:39 -07002109 " -L: output limited information that is safe for submission in feedback reports\n"
Felipe Lemed071c682016-10-20 16:48:00 -07002110 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002111}
2112
Wei Liuf87959e2016-08-26 14:51:42 -07002113static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07002114 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07002115}
2116
Felipe Leme1d486fe2016-10-14 18:06:47 -07002117bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002118 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07002119 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002120 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002121 // Final timestamp
2122 char date[80];
2123 time_t the_real_now_please_stand_up = time(nullptr);
2124 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002125 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002126 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07002127
Felipe Leme9a523ae2016-10-20 15:10:33 -07002128 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002129 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08002130 return false;
2131 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002132 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002133 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08002134 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08002135 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08002136
Felipe Leme0f3fb202016-06-10 17:10:53 -07002137 // Add log file (which contains stderr output) to zip...
2138 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002139 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07002140 MYLOGE("Failed to add dumpstate log to .zip file\n");
2141 return false;
2142 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002143 // TODO: Should truncate the existing file.
2144 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00002145 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
2146 return false;
2147 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07002148 fprintf(stderr, "\n");
2149
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002150 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07002151 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002152 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002153 return false;
2154 }
2155
Felipe Leme1d486fe2016-10-14 18:06:47 -07002156 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
2157 ds.zip_file.reset(nullptr);
2158
Felipe Lemee9d2c542016-11-15 11:48:26 -08002159 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002160 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07002161
Felipe Leme1e9edc62015-12-21 16:02:13 -08002162 return true;
2163}
Felipe Leme6e01fa62015-11-11 19:35:14 -08002164
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002165static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2166 // clang-format off
2167 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2168 "--receiver-foreground", "--receiver-include-background", "-a", action};
2169 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002170
2171 am.insert(am.end(), args.begin(), args.end());
2172
Felipe Leme8d2410e2017-02-08 09:46:08 -08002173 RunCommand("", am,
2174 CommandOptions::WithTimeout(20)
2175 .Log("Sending broadcast: '%s'\n")
2176 .Always()
2177 .DropRoot()
2178 .RedirectStderr()
2179 .Build());
2180}
2181
Felipe Leme35b8cf12017-02-10 15:47:29 -08002182static void Vibrate(int duration_ms) {
2183 // clang-format off
Chris Fries0c3de872019-09-14 15:49:41 +00002184 RunCommand("", {"cmd", "vibrator", "vibrate", "-f", std::to_string(duration_ms), "dumpstate"},
Felipe Leme35b8cf12017-02-10 15:47:29 -08002185 CommandOptions::WithTimeout(10)
2186 .Log("Vibrate: '%s'\n")
2187 .Always()
2188 .Build());
2189 // clang-format on
2190}
2191
Nandana Dutt979388e2018-11-30 16:48:55 +00002192static void MaybeResolveSymlink(std::string* path) {
2193 std::string resolved_path;
2194 if (android::base::Readlink(*path, &resolved_path)) {
2195 *path = resolved_path;
2196 }
2197}
2198
Nandana Dutt4be45d12018-09-26 15:04:23 +01002199/*
2200 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2201 * if we are writing zip files and adds the version file.
2202 */
2203static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002204 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2205
Nandana Dutt4be45d12018-09-26 15:04:23 +01002206 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2207 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002208 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002209 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002210 char date[80];
2211 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2212 ds.name_ = date;
2213 } else {
2214 ds.name_ = "undated";
2215 }
2216
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002217 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002218 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002219 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002220 ds.base_name_ += "-wifi";
2221 }
2222
Paul Chang0d2aad72020-02-13 20:04:03 +08002223 if (ds.options_->do_screenshot) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002224 ds.screenshot_path_ = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002225 }
2226 ds.tmp_path_ = ds.GetPath(".tmp");
2227 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2228
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002229 std::string destination = ds.CalledByApi()
Nandana Dutt54dbd672019-01-11 12:58:05 +00002230 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002231 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002232 MYLOGD(
Nandana Dutt235c6672019-11-14 15:22:32 +00002233 "Bugreport dir: [%s] "
2234 "Base name: [%s] "
2235 "Suffix: [%s] "
2236 "Log path: [%s] "
2237 "Temporary path: [%s] "
2238 "Screenshot path: [%s]\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002239 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2240 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002241
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002242 if (ds.options_->do_zip_file) {
Nandana Dutt9d17b942020-03-26 10:02:59 +00002243 ds.path_ = ds.GetPath(ds.CalledByApi() ? "-zip.tmp" : ".zip");
Nandana Dutt4be45d12018-09-26 15:04:23 +01002244 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2245 create_parent_dirs(ds.path_.c_str());
2246 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2247 if (ds.zip_file == nullptr) {
2248 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2249 } else {
2250 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2251 }
2252 ds.AddTextZipEntry("version.txt", ds.version_);
2253 }
2254}
2255
2256/*
Abhijeet Kaure370d682019-10-01 16:49:30 +01002257 * Finalizes writing to the file by zipping the tmp file to the final location,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002258 * printing zipped file status, etc.
2259 */
2260static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002261 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002262 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002263 if (!ds.FinishZipFile()) {
2264 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2265 do_text_file = true;
2266 } else {
2267 do_text_file = false;
Nandana Dutt4be45d12018-09-26 15:04:23 +01002268 }
2269 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002270 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002271 if (do_text_file) {
2272 dprintf(ds.control_socket_fd_,
2273 "FAIL:could not create zip file, check %s "
2274 "for more details\n",
2275 ds.log_path_.c_str());
2276 } else {
2277 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2278 }
2279 }
2280}
2281
Nandana Dutt4be45d12018-09-26 15:04:23 +01002282
Nandana Dutt58d72e22018-11-16 10:30:48 +00002283static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2284 switch (mode) {
2285 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2286 return "BUGREPORT_FULL";
2287 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2288 return "BUGREPORT_INTERACTIVE";
2289 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2290 return "BUGREPORT_REMOTE";
2291 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2292 return "BUGREPORT_WEAR";
2293 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2294 return "BUGREPORT_TELEPHONY";
2295 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2296 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002297 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2298 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002299 }
2300}
2301
Paul Changf59c2b72020-03-10 02:08:55 +08002302static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options,
2303 bool is_screenshot_requested) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002304 // Modify com.android.shell.BugreportProgressService#isDefaultScreenshotRequired as well for
2305 // default system screenshots.
Abhijeet Kaure370d682019-10-01 16:49:30 +01002306 options->bugreport_mode = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002307 switch (mode) {
2308 case Dumpstate::BugreportMode::BUGREPORT_FULL:
Paul Changf59c2b72020-03-10 02:08:55 +08002309 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002310 options->dumpstate_hal_mode = DumpstateMode::FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002311 break;
2312 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002313 // Currently, the dumpstate binder is only used by Shell to update progress.
2314 options->do_start_service = true;
2315 options->do_progress_updates = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002316 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002317 options->dumpstate_hal_mode = DumpstateMode::INTERACTIVE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002318 break;
2319 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002320 options->do_vibrate = false;
2321 options->is_remote_mode = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002322 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002323 options->dumpstate_hal_mode = DumpstateMode::REMOTE;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002324 break;
2325 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002326 options->do_start_service = true;
2327 options->do_progress_updates = true;
2328 options->do_zip_file = true;
Paul Changf59c2b72020-03-10 02:08:55 +08002329 options->do_screenshot = is_screenshot_requested;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002330 options->dumpstate_hal_mode = DumpstateMode::WEAR;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002331 break;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002332 // TODO(b/148168577) rename TELEPHONY everywhere to CONNECTIVITY.
Nandana Dutt58d72e22018-11-16 10:30:48 +00002333 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002334 options->telephony_only = true;
Hunter Knepshield820f9bc2020-02-05 20:10:53 -08002335 options->do_progress_updates = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002336 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002337 options->dumpstate_hal_mode = DumpstateMode::CONNECTIVITY;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002338 break;
2339 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002340 options->wifi_only = true;
2341 options->do_zip_file = true;
Paul Chang0d2aad72020-02-13 20:04:03 +08002342 options->do_screenshot = false;
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002343 options->dumpstate_hal_mode = DumpstateMode::WIFI;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002344 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002345 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2346 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002347 }
2348}
2349
Nandana Dutt58d72e22018-11-16 10:30:48 +00002350static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
Nandana Dutt235c6672019-11-14 15:22:32 +00002351 MYLOGI(
Paul Chang0d2aad72020-02-13 20:04:03 +08002352 "do_zip_file: %d do_vibrate: %d use_socket: %d use_control_socket: %d do_screenshot: %d "
Nandana Dutt235c6672019-11-14 15:22:32 +00002353 "is_remote_mode: %d show_header_only: %d do_start_service: %d telephony_only: %d "
Hunter Knepshield8540faf2020-02-04 19:47:20 -08002354 "wifi_only: %d do_progress_updates: %d fd: %d bugreport_mode: %s dumpstate_hal_mode: %s "
mhasankd451a472020-05-26 18:02:39 -07002355 "limited_only: %d args: %s\n",
Nandana Dutt235c6672019-11-14 15:22:32 +00002356 options.do_zip_file, options.do_vibrate, options.use_socket, options.use_control_socket,
Paul Chang0d2aad72020-02-13 20:04:03 +08002357 options.do_screenshot, options.is_remote_mode, options.show_header_only,
mhasankd451a472020-05-26 18:02:39 -07002358 options.do_start_service, options.telephony_only, options.wifi_only,
2359 options.do_progress_updates, options.bugreport_fd.get(), options.bugreport_mode.c_str(),
2360 toString(options.dumpstate_hal_mode).c_str(), options.limited_only, options.args.c_str());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002361}
2362
Nandana Dutt54dbd672019-01-11 12:58:05 +00002363void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2364 const android::base::unique_fd& bugreport_fd_in,
Paul Changf59c2b72020-03-10 02:08:55 +08002365 const android::base::unique_fd& screenshot_fd_in,
2366 bool is_screenshot_requested) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002367 // In the new API world, date is always added; output is always a zip file.
2368 // TODO(111441001): remove these options once they are obsolete.
2369 do_add_date = true;
2370 do_zip_file = true;
2371
Nandana Dutt54dbd672019-01-11 12:58:05 +00002372 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2373 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2374 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002375
Paul Changf59c2b72020-03-10 02:08:55 +08002376 SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002377}
2378
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002379Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2380 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002381 int c;
mhasankd451a472020-05-26 18:02:39 -07002382 while ((c = getopt(argc, argv, "dho:svqzpLPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002383 switch (c) {
2384 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002385 case 'd': do_add_date = true; break;
2386 case 'z': do_zip_file = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002387 case 's': use_socket = true; break;
2388 case 'S': use_control_socket = true; break;
2389 case 'v': show_header_only = true; break;
2390 case 'q': do_vibrate = false; break;
Paul Chang0d2aad72020-02-13 20:04:03 +08002391 case 'p': do_screenshot = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002392 case 'P': do_progress_updates = true; break;
2393 case 'R': is_remote_mode = true; break;
mhasankd451a472020-05-26 18:02:39 -07002394 case 'L': limited_only = true; break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002395 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002396 case 'w':
2397 // This was already processed
2398 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002399 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002400 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002401 break;
2402 default:
2403 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002404 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002405 break;
2406 // clang-format on
2407 }
2408 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002409
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002410 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002411 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002412 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002413 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002414 }
2415 }
2416
2417 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2418 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002419
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002420 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002421}
2422
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002423bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002424 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002425 return false;
2426 }
2427
Abhijeet Kaure370d682019-10-01 16:49:30 +01002428 if ((do_zip_file || do_add_date || do_progress_updates) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002429 return false;
2430 }
2431
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002432 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002433 return false;
2434 }
2435
Abhijeet Kaure370d682019-10-01 16:49:30 +01002436 if (is_remote_mode && (do_progress_updates || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002437 return false;
2438 }
2439 return true;
2440}
2441
Nandana Dutt197661d2018-11-16 16:40:21 +00002442void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2443 options_ = std::move(options);
2444}
2445
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002446void Dumpstate::Initialize() {
2447 /* gets the sequential id */
2448 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
2449 id_ = ++last_id;
2450 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2451}
2452
Nandana Duttd2f5f082019-01-18 17:13:52 +00002453Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2454 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002455 if (listener_ != nullptr) {
2456 switch (status) {
2457 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002458 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002459 break;
2460 case Dumpstate::RunStatus::HELP:
2461 break;
2462 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002463 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002464 break;
2465 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002466 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2467 break;
2468 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2469 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2470 break;
2471 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2472 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002473 break;
2474 }
2475 }
2476 return status;
2477}
2478
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002479void Dumpstate::Cancel() {
2480 CleanupTmpFiles();
2481 android::os::UnlinkAndLogOnError(log_path_);
2482 for (int i = 0; i < NUM_OF_DUMPS; i++) {
2483 android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
2484 kDumpstateBoardFiles[i]);
2485 }
2486 tombstone_data_.clear();
2487 anr_data_.clear();
2488}
2489
Nandana Dutt979388e2018-11-30 16:48:55 +00002490/*
2491 * Dumps relevant information to a bugreport based on the given options.
2492 *
2493 * The bugreport can be dumped to a file or streamed to a socket.
2494 *
2495 * How dumping to file works:
2496 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2497 * stderr is redirected a log file.
2498 *
2499 * The temporary bugreport is then populated via printfs, dumping contents of files and
2500 * output of commands to stdout.
2501 *
2502 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2503 * text file.
2504 *
2505 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2506 * gets added to the archive.
2507 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002508 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2509 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002510 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002511Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2512 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002513 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002514 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002515 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002516 return RunStatus::INVALID_INPUT;
2517 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002518 /* set as high priority, and protect from OOM killer */
2519 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002520
Felipe Lemed071c682016-10-20 16:48:00 -07002521 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002522 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002523 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002524 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002525 } else {
2526 /* fallback to kernels <= 2.6.35 */
2527 oom_adj = fopen("/proc/self/oom_adj", "we");
2528 if (oom_adj) {
2529 fputs("-17", oom_adj);
2530 fclose(oom_adj);
2531 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002532 }
2533
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002534 if (version_ == VERSION_DEFAULT) {
2535 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002536 }
2537
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002538 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002539 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002540 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002541 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002542 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002543 }
2544
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002545 if (options_->show_header_only) {
2546 PrintHeader();
2547 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002548 }
2549
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002550 MYLOGD("dumpstate calling_uid = %d ; calling package = %s \n",
2551 calling_uid, calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002552
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002553 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002554 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002555
2556 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002557 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002558 is_redirecting
2559 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2560 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002561 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002562
Sahana Raof35ed432019-07-12 10:47:52 +01002563 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
2564 MYLOGE("Failed to acquire wake lock: %s\n", strerror(errno));
2565 } else {
2566 // Wake lock will be released automatically on process death
2567 MYLOGD("Wake lock acquired.\n");
2568 }
2569
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002570 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002571
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002572 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002573 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002574 MYLOGI("Starting 'dumpstate' service\n");
2575 android::status_t ret;
2576 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2577 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2578 }
2579 }
2580
Felipe Lemef0292972016-11-22 13:57:05 -08002581 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002582 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2583 }
2584
Nandana Dutt235c6672019-11-14 15:22:32 +00002585 MYLOGI("dumpstate info: id=%d, args='%s', bugreport_mode= %s bugreport format version: %s\n",
2586 id_, options_->args.c_str(), options_->bugreport_mode.c_str(), version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002587
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002588 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002589
Christopher Ferrised9354f2014-10-01 17:35:01 -07002590 // If we are going to use a socket, do it as early as possible
2591 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002592 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002593 if (!redirect_to_socket(stdout, "dumpstate")) {
2594 return ERROR;
2595 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002596 }
2597
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002598 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002599 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002600 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002601 if (control_socket_fd_ == -1) {
2602 return ERROR;
2603 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002604 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002605 }
2606
Felipe Leme71bbfc52015-11-23 14:14:51 -08002607 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002608 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002609
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002610 if (options_->do_progress_updates) {
Abhijeet Kaure370d682019-10-01 16:49:30 +01002611 // clang-format off
2612 std::vector<std::string> am_args = {
2613 "--receiver-permission", "android.permission.DUMP",
2614 };
2615 // clang-format on
2616 // Send STARTED broadcast for apps that listen to bugreport generation events
2617 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002618 if (options_->use_control_socket) {
2619 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002620 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002621 }
2622 }
2623
Nick Kralevichf3599b32016-01-25 15:05:16 -08002624 /* read /proc/cmdline before dropping root */
2625 FILE *cmdline = fopen("/proc/cmdline", "re");
2626 if (cmdline) {
2627 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2628 fclose(cmdline);
2629 }
2630
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002631 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002632 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002633 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002634
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002635 if (options_->do_zip_file && zip_file != nullptr) {
2636 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2637 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002638 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002639 }
2640 }
2641
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002642 int dup_stdout_fd;
2643 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002644 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002645 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002646 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002647 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2648 return ERROR;
2649 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002650 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2651 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2652 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002653 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002654
2655 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2656 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002657 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002658 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002659 /* TODO: rather than generating a text file now and zipping it later,
2660 it would be more efficient to redirect stdout to the zip entry
2661 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002662 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2663 return ERROR;
2664 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002665 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002666 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002667 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002668 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002669 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002670
2671 // Don't buffer stdout
2672 setvbuf(stdout, nullptr, _IONBF, 0);
2673
Felipe Leme608385d2016-02-01 10:35:38 -08002674 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2675 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002676 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002677 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002678
mhasankd451a472020-05-26 18:02:39 -07002679 // TODO(b/158737089) reduce code repetition in if branches
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002680 if (options_->telephony_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002681 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002682 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002683 MaybeCheckUserConsent(calling_uid, calling_package);
Hunter Knepshield0cc6c212020-01-07 16:57:10 -08002684 DumpstateTelephonyOnly(calling_package);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002685 DumpstateBoard();
2686 } else if (options_->wifi_only) {
Paul Chang0d2aad72020-02-13 20:04:03 +08002687 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002688 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002689 MaybeCheckUserConsent(calling_uid, calling_package);
mukesh agrawal253dad42018-01-23 21:59:59 -08002690 DumpstateWifiOnly();
mhasankd451a472020-05-26 18:02:39 -07002691 } else if (options_->limited_only) {
2692 MaybeTakeEarlyScreenshot();
2693 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
2694 MaybeCheckUserConsent(calling_uid, calling_package);
2695 DumpstateLimitedOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002696 } else {
Paul Chang0d2aad72020-02-13 20:04:03 +08002697 // Invoke critical dumpsys first to preserve system state, before doing anything else.
Jichao Lie89d9c12019-11-21 19:02:51 -08002698 RunDumpsysCritical();
2699
Paul Chang0d2aad72020-02-13 20:04:03 +08002700 // Take screenshot and get consent only after critical dumpsys has finished.
2701 MaybeTakeEarlyScreenshot();
Paul Changc490e662020-04-11 18:14:09 +08002702 onUiIntensiveBugreportDumpsFinished(calling_uid, calling_package);
Jichao Lie89d9c12019-11-21 19:02:51 -08002703 MaybeCheckUserConsent(calling_uid, calling_package);
2704
Nandana Dutt4be45d12018-09-26 15:04:23 +01002705 // Dump state for the default case. This also drops root.
Jichao Lie89d9c12019-11-21 19:02:51 -08002706 RunStatus s = DumpstateDefaultAfterCritical();
Nandana Dutt5c390032019-03-12 10:52:56 +00002707 if (s != RunStatus::OK) {
Nandana Duttaac6f582019-07-26 14:32:47 +01002708 if (s == RunStatus::USER_CONSENT_DENIED) {
Nandana Dutt5c390032019-03-12 10:52:56 +00002709 HandleUserConsentDenied();
2710 }
2711 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002712 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002713 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002714
Felipe Leme55b42a62015-11-10 17:39:08 -08002715 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002716 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002717 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002718 }
2719
Abhijeet Kaure370d682019-10-01 16:49:30 +01002720 // Zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002721 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002722 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002723 }
2724
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002725 // Share the final file with the caller if the user has consented or Shell is the caller.
Nandana Duttd2f5f082019-01-18 17:13:52 +00002726 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
Abhijeet Kaure370d682019-10-01 16:49:30 +01002727 if (CalledByApi()) {
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002728 status = CopyBugreportIfUserConsented(calling_uid);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002729 if (status != Dumpstate::RunStatus::OK &&
2730 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2731 // Do an early return if there were errors. We make an exception for consent
2732 // timing out because it's possible the user got distracted. In this case the
2733 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002734 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002735 return status;
2736 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002737 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2738 MYLOGI(
2739 "Did not receive user consent yet."
2740 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002741 const String16 incidentcompanion("incidentcompanion");
2742 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2743 if (ics != nullptr) {
2744 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2745 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2746 consent_callback_.get());
2747 } else {
2748 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2749 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002750 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002751 }
2752
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002753 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002754 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002755 for (int i = 0; i < 3; i++) {
2756 Vibrate(75);
2757 usleep((75 + 50) * 1000);
2758 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002759 }
2760
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002761 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2762 progress_->GetInitialMax());
2763 progress_->Save();
2764 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002765
Felipe Leme107a05f2016-03-08 15:11:15 -08002766 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002767 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002768 }
2769
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002770 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002771 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002772 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002773 }
2774
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002775 tombstone_data_.clear();
2776 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002777
Nandana Duttd2f5f082019-01-18 17:13:52 +00002778 return (consent_callback_ != nullptr &&
2779 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2780 ? USER_CONSENT_TIMED_OUT
2781 : RunStatus::OK;
2782}
2783
Paul Chang0d2aad72020-02-13 20:04:03 +08002784void Dumpstate::MaybeTakeEarlyScreenshot() {
2785 if (!options_->do_screenshot || !do_early_screenshot_) {
2786 return;
2787 }
2788
2789 TakeScreenshot();
2790}
2791
Paul Changc490e662020-04-11 18:14:09 +08002792void Dumpstate::onUiIntensiveBugreportDumpsFinished(int32_t calling_uid,
2793 const std::string& calling_package) {
2794 if (calling_uid == AID_SHELL || !CalledByApi()) {
2795 return;
2796 }
2797 if (listener_ != nullptr) {
2798 // Let listener know ui intensive bugreport dumps are finished, then it can do event
2799 // handling if required.
2800 android::String16 package(calling_package.c_str());
2801 listener_->onUiIntensiveBugreportDumpsFinished(package);
2802 }
2803}
2804
Jichao Lie89d9c12019-11-21 19:02:51 -08002805void Dumpstate::MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package) {
2806 if (calling_uid == AID_SHELL || !CalledByApi()) {
2807 // No need to get consent for shell triggered dumpstates, or not through
2808 // bugreporting API (i.e. no fd to copy back).
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002809 return;
2810 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002811 consent_callback_ = new ConsentCallback();
2812 const String16 incidentcompanion("incidentcompanion");
2813 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
Jichao Lie89d9c12019-11-21 19:02:51 -08002814 android::String16 package(calling_package.c_str());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002815 if (ics != nullptr) {
2816 MYLOGD("Checking user consent via incidentcompanion service\n");
2817 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Jichao Lie89d9c12019-11-21 19:02:51 -08002818 calling_uid, package, String16(), String16(),
Joe Onorato1c36d752019-03-17 18:26:43 -07002819 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002820 } else {
2821 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2822 }
2823}
2824
Nandana Dutt5c390032019-03-12 10:52:56 +00002825bool Dumpstate::IsUserConsentDenied() const {
2826 return ds.consent_callback_ != nullptr &&
2827 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2828}
2829
Abhijeet Kaur359b1ff2019-07-26 16:01:36 +01002830bool Dumpstate::CalledByApi() const {
2831 return ds.options_->bugreport_fd.get() != -1 ? true : false;
2832}
2833
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002834void Dumpstate::CleanupTmpFiles() {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002835 android::os::UnlinkAndLogOnError(tmp_path_);
2836 android::os::UnlinkAndLogOnError(screenshot_path_);
2837 android::os::UnlinkAndLogOnError(path_);
2838}
2839
2840Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2841 MYLOGD("User denied consent; deleting files and returning\n");
Nandana Dutt8ae16e62020-03-27 10:20:22 +00002842 CleanupTmpFiles();
Nandana Duttd2f5f082019-01-18 17:13:52 +00002843 return USER_CONSENT_DENIED;
2844}
2845
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002846Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented(int32_t calling_uid) {
Nandana Duttd2f5f082019-01-18 17:13:52 +00002847 // If the caller has asked to copy the bugreport over to their directory, we need explicit
Abhijeet Kaur3172b532019-10-15 15:07:03 +01002848 // user consent (unless the caller is Shell).
2849 UserConsentResult consent_result;
2850 if (calling_uid == AID_SHELL) {
2851 consent_result = UserConsentResult::APPROVED;
2852 } else {
2853 consent_result = consent_callback_->getResult();
2854 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002855 if (consent_result == UserConsentResult::UNAVAILABLE) {
2856 // User has not responded yet.
2857 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
Hunter Knepshield70610fa2020-01-03 15:27:33 -08002858 // Telephony is a fast report type, particularly on user builds where information may be
2859 // more aggressively limited. To give the user time to read the consent dialog, increase the
2860 // timeout.
2861 uint64_t timeout_ms = options_->telephony_only ? TELEPHONY_REPORT_USER_CONSENT_TIMEOUT_MS
2862 : USER_CONSENT_TIMEOUT_MS;
2863 if (elapsed_ms < timeout_ms) {
2864 uint delay_seconds = (timeout_ms - elapsed_ms) / 1000;
Nandana Duttd2f5f082019-01-18 17:13:52 +00002865 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2866 sleep(delay_seconds);
2867 }
2868 consent_result = consent_callback_->getResult();
2869 }
2870 if (consent_result == UserConsentResult::DENIED) {
2871 // User has explicitly denied sharing with the app. To be safe delete the
2872 // internal bugreport & tmp files.
2873 return HandleUserConsentDenied();
2874 }
2875 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002876 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2877 if (copy_succeeded) {
2878 android::os::UnlinkAndLogOnError(path_);
Abhijeet Kaur9ce94672020-04-01 17:22:36 +01002879 if (options_->do_screenshot &&
2880 options_->screenshot_fd.get() != -1 &&
2881 !options_->is_screenshot_copied) {
2882 copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2883 options_->screenshot_fd.get());
2884 options_->is_screenshot_copied = copy_succeeded;
2885 if (copy_succeeded) {
2886 android::os::UnlinkAndLogOnError(screenshot_path_);
2887 }
2888 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002889 }
2890 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2891 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2892 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2893 // Since we do not have user consent to share the bugreport it does not get
2894 // copied over to the calling app but remains in the internal directory from
2895 // where the user can manually pull it.
2896 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2897 }
2898 // Unknown result; must be a programming error.
2899 MYLOGE("Unknown user consent result:%d\n", consent_result);
2900 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002901}
2902
Nandana Duttf02564e2019-02-15 15:24:24 +00002903Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002904 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2905 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2906 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002907 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002908 // When directly running dumpstate binary, the output is not expected to be written
2909 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002910 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002911
2912 // calling_uid and calling_package are for user consent to share the bugreport with
Abhijeet Kaura407fb82020-03-27 12:51:12 +00002913 // an app; they are irrelevant here because bugreport is triggered via command line.
2914 // Update Last ID before calling Run().
2915 Initialize();
Nandana Duttf02564e2019-02-15 15:24:24 +00002916 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002917 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002918 return status;
2919}
2920
2921/* Main entry point for dumpstate binary. */
2922int run_main(int argc, char* argv[]) {
2923 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002924
2925 switch (status) {
2926 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002927 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002928 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002929 ShowUsage();
2930 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002931 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002932 fprintf(stderr, "Invalid combination of args\n");
2933 ShowUsage();
2934 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002935 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002936 FALLTHROUGH_INTENDED;
2937 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2938 FALLTHROUGH_INTENDED;
2939 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002940 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002941 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002942}
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002943
2944// TODO(111441001): Default DumpOptions to sensible values.
2945Dumpstate::Dumpstate(const std::string& version)
2946 : pid_(getpid()),
2947 options_(new Dumpstate::DumpOptions()),
Nandana Dutt402a8392019-06-14 14:25:13 +01002948 last_reported_percent_progress_(0),
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002949 version_(version),
2950 now_(time(nullptr)) {
2951}
2952
2953Dumpstate& Dumpstate::GetInstance() {
2954 static Dumpstate singleton_(android::base::GetProperty("dumpstate.version", VERSION_CURRENT));
2955 return singleton_;
2956}
2957
Nandana Dutt8d945c02019-08-14 13:30:07 +01002958DurationReporter::DurationReporter(const std::string& title, bool logcat_only, bool verbose)
2959 : title_(title), logcat_only_(logcat_only), verbose_(verbose) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002960 if (!title_.empty()) {
2961 started_ = Nanotime();
2962 }
2963}
2964
2965DurationReporter::~DurationReporter() {
2966 if (!title_.empty()) {
2967 float elapsed = (float)(Nanotime() - started_) / NANOS_PER_SEC;
chenqiwuaf8b2d92019-12-12 18:53:51 +08002968 if (elapsed >= .5f || verbose_) {
2969 MYLOGD("Duration of '%s': %.2fs\n", title_.c_str(), elapsed);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002970 }
chenqiwuaf8b2d92019-12-12 18:53:51 +08002971 if (!logcat_only_) {
2972 // Use "Yoda grammar" to make it easier to grep|sort sections.
2973 printf("------ %.3fs was the duration of '%s' ------\n", elapsed, title_.c_str());
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002974 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01002975 }
2976}
2977
2978const int32_t Progress::kDefaultMax = 5000;
2979
2980Progress::Progress(const std::string& path) : Progress(Progress::kDefaultMax, 1.1, path) {
2981}
2982
2983Progress::Progress(int32_t initial_max, int32_t progress, float growth_factor)
2984 : Progress(initial_max, growth_factor, "") {
2985 progress_ = progress;
2986}
2987
2988Progress::Progress(int32_t initial_max, float growth_factor, const std::string& path)
2989 : initial_max_(initial_max),
2990 progress_(0),
2991 max_(initial_max),
2992 growth_factor_(growth_factor),
2993 n_runs_(0),
2994 average_max_(0),
2995 path_(path) {
2996 if (!path_.empty()) {
2997 Load();
2998 }
2999}
3000
3001void Progress::Load() {
3002 MYLOGD("Loading stats from %s\n", path_.c_str());
3003 std::string content;
3004 if (!android::base::ReadFileToString(path_, &content)) {
3005 MYLOGI("Could not read stats from %s; using max of %d\n", path_.c_str(), max_);
3006 return;
3007 }
3008 if (content.empty()) {
3009 MYLOGE("No stats (empty file) on %s; using max of %d\n", path_.c_str(), max_);
3010 return;
3011 }
3012 std::vector<std::string> lines = android::base::Split(content, "\n");
3013
3014 if (lines.size() < 1) {
3015 MYLOGE("Invalid stats on file %s: not enough lines (%d). Using max of %d\n", path_.c_str(),
3016 (int)lines.size(), max_);
3017 return;
3018 }
3019 char* ptr;
3020 n_runs_ = strtol(lines[0].c_str(), &ptr, 10);
3021 average_max_ = strtol(ptr, nullptr, 10);
3022 if (n_runs_ <= 0 || average_max_ <= 0 || n_runs_ > STATS_MAX_N_RUNS ||
3023 average_max_ > STATS_MAX_AVERAGE) {
3024 MYLOGE("Invalid stats line on file %s: %s\n", path_.c_str(), lines[0].c_str());
3025 initial_max_ = Progress::kDefaultMax;
3026 } else {
3027 initial_max_ = average_max_;
3028 }
3029 max_ = initial_max_;
3030
3031 MYLOGI("Average max progress: %d in %d runs; estimated max: %d\n", average_max_, n_runs_, max_);
3032}
3033
3034void Progress::Save() {
3035 int32_t total = n_runs_ * average_max_ + progress_;
3036 int32_t runs = n_runs_ + 1;
3037 int32_t average = floor(((float)total) / runs);
3038 MYLOGI("Saving stats (total=%d, runs=%d, average=%d) on %s\n", total, runs, average,
3039 path_.c_str());
3040 if (path_.empty()) {
3041 return;
3042 }
3043
3044 std::string content = android::base::StringPrintf("%d %d\n", runs, average);
3045 if (!android::base::WriteStringToFile(content, path_)) {
3046 MYLOGE("Could not save stats on %s\n", path_.c_str());
3047 }
3048}
3049
3050int32_t Progress::Get() const {
3051 return progress_;
3052}
3053
3054bool Progress::Inc(int32_t delta_sec) {
3055 bool changed = false;
3056 if (delta_sec >= 0) {
3057 progress_ += delta_sec;
3058 if (progress_ > max_) {
3059 int32_t old_max = max_;
3060 max_ = floor((float)progress_ * growth_factor_);
3061 MYLOGD("Adjusting max progress from %d to %d\n", old_max, max_);
3062 changed = true;
3063 }
3064 }
3065 return changed;
3066}
3067
3068int32_t Progress::GetMax() const {
3069 return max_;
3070}
3071
3072int32_t Progress::GetInitialMax() const {
3073 return initial_max_;
3074}
3075
3076void Progress::Dump(int fd, const std::string& prefix) const {
3077 const char* pr = prefix.c_str();
3078 dprintf(fd, "%sprogress: %d\n", pr, progress_);
3079 dprintf(fd, "%smax: %d\n", pr, max_);
3080 dprintf(fd, "%sinitial_max: %d\n", pr, initial_max_);
3081 dprintf(fd, "%sgrowth_factor: %0.2f\n", pr, growth_factor_);
3082 dprintf(fd, "%spath: %s\n", pr, path_.c_str());
3083 dprintf(fd, "%sn_runs: %d\n", pr, n_runs_);
3084 dprintf(fd, "%saverage_max: %d\n", pr, average_max_);
3085}
3086
3087bool Dumpstate::IsZipping() const {
3088 return zip_writer_ != nullptr;
3089}
3090
3091std::string Dumpstate::GetPath(const std::string& suffix) const {
3092 return GetPath(bugreport_internal_dir_, suffix);
3093}
3094
3095std::string Dumpstate::GetPath(const std::string& directory, const std::string& suffix) const {
3096 return android::base::StringPrintf("%s/%s-%s%s", directory.c_str(), base_name_.c_str(),
3097 name_.c_str(), suffix.c_str());
3098}
3099
3100void Dumpstate::SetProgress(std::unique_ptr<Progress> progress) {
3101 progress_ = std::move(progress);
3102}
3103
3104void for_each_userid(void (*func)(int), const char *header) {
3105 std::string title = header == nullptr ? "for_each_userid" : android::base::StringPrintf(
3106 "for_each_userid(%s)", header);
3107 DurationReporter duration_reporter(title);
3108 if (PropertiesHelper::IsDryRun()) return;
3109
3110 DIR *d;
3111 struct dirent *de;
3112
3113 if (header) printf("\n------ %s ------\n", header);
3114 func(0);
3115
3116 if (!(d = opendir("/data/system/users"))) {
3117 printf("Failed to open /data/system/users (%s)\n", strerror(errno));
3118 return;
3119 }
3120
3121 while ((de = readdir(d))) {
3122 int userid;
3123 if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
3124 continue;
3125 }
3126 func(userid);
3127 }
3128
3129 closedir(d);
3130}
3131
3132static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
3133 DIR *d;
3134 struct dirent *de;
3135
3136 if (!(d = opendir("/proc"))) {
3137 printf("Failed to open /proc (%s)\n", strerror(errno));
3138 return;
3139 }
3140
3141 if (header) printf("\n------ %s ------\n", header);
3142 while ((de = readdir(d))) {
3143 if (ds.IsUserConsentDenied()) {
3144 MYLOGE(
3145 "Returning early because user denied consent to share bugreport with calling app.");
3146 closedir(d);
3147 return;
3148 }
3149 int pid;
3150 int fd;
3151 char cmdpath[255];
3152 char cmdline[255];
3153
3154 if (!(pid = atoi(de->d_name))) {
3155 continue;
3156 }
3157
3158 memset(cmdline, 0, sizeof(cmdline));
3159
3160 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
3161 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3162 TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
3163 close(fd);
3164 if (cmdline[0]) {
3165 helper(pid, cmdline, arg);
3166 continue;
3167 }
3168 }
3169
3170 // if no cmdline, a kernel thread has comm
3171 snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
3172 if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
3173 TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
3174 close(fd);
3175 if (cmdline[1]) {
3176 cmdline[0] = '[';
3177 size_t len = strcspn(cmdline, "\f\b\r\n");
3178 cmdline[len] = ']';
3179 cmdline[len+1] = '\0';
3180 }
3181 }
3182 if (!cmdline[0]) {
3183 strcpy(cmdline, "N/A");
3184 }
3185 helper(pid, cmdline, arg);
3186 }
3187
3188 closedir(d);
3189}
3190
3191static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
3192 for_each_pid_func *func = (for_each_pid_func*) arg;
3193 func(pid, cmdline);
3194}
3195
3196void for_each_pid(for_each_pid_func func, const char *header) {
3197 std::string title = header == nullptr ? "for_each_pid"
3198 : android::base::StringPrintf("for_each_pid(%s)", header);
3199 DurationReporter duration_reporter(title);
3200 if (PropertiesHelper::IsDryRun()) return;
3201
3202 __for_each_pid(for_each_pid_helper, header, (void *) func);
3203}
3204
3205static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
3206 DIR *d;
3207 struct dirent *de;
3208 char taskpath[255];
3209 for_each_tid_func *func = (for_each_tid_func *) arg;
3210
3211 snprintf(taskpath, sizeof(taskpath), "/proc/%d/task", pid);
3212
3213 if (!(d = opendir(taskpath))) {
3214 printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
3215 return;
3216 }
3217
3218 func(pid, pid, cmdline);
3219
3220 while ((de = readdir(d))) {
3221 if (ds.IsUserConsentDenied()) {
3222 MYLOGE(
3223 "Returning early because user denied consent to share bugreport with calling app.");
3224 closedir(d);
3225 return;
3226 }
3227 int tid;
3228 int fd;
3229 char commpath[255];
3230 char comm[255];
3231
3232 if (!(tid = atoi(de->d_name))) {
3233 continue;
3234 }
3235
3236 if (tid == pid)
3237 continue;
3238
3239 snprintf(commpath, sizeof(commpath), "/proc/%d/comm", tid);
3240 memset(comm, 0, sizeof(comm));
3241 if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
3242 strcpy(comm, "N/A");
3243 } else {
3244 char *c;
3245 TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
3246 close(fd);
3247
3248 c = strrchr(comm, '\n');
3249 if (c) {
3250 *c = '\0';
3251 }
3252 }
3253 func(pid, tid, comm);
3254 }
3255
3256 closedir(d);
3257}
3258
3259void for_each_tid(for_each_tid_func func, const char *header) {
3260 std::string title = header == nullptr ? "for_each_tid"
3261 : android::base::StringPrintf("for_each_tid(%s)", header);
3262 DurationReporter duration_reporter(title);
3263
3264 if (PropertiesHelper::IsDryRun()) return;
3265
3266 __for_each_pid(for_each_tid_helper, header, (void *) func);
3267}
3268
3269void show_wchan(int pid, int tid, const char *name) {
3270 if (PropertiesHelper::IsDryRun()) return;
3271
3272 char path[255];
3273 char buffer[255];
3274 int fd, ret, save_errno;
3275 char name_buffer[255];
3276
3277 memset(buffer, 0, sizeof(buffer));
3278
3279 snprintf(path, sizeof(path), "/proc/%d/wchan", tid);
3280 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3281 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3282 return;
3283 }
3284
3285 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3286 save_errno = errno;
3287 close(fd);
3288
3289 if (ret < 0) {
3290 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3291 return;
3292 }
3293
3294 snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
3295 pid == tid ? 0 : 3, "", name);
3296
3297 printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
3298
3299 return;
3300}
3301
3302// print time in centiseconds
3303static void snprcent(char *buffer, size_t len, size_t spc,
3304 unsigned long long time) {
3305 static long hz; // cache discovered hz
3306
3307 if (hz <= 0) {
3308 hz = sysconf(_SC_CLK_TCK);
3309 if (hz <= 0) {
3310 hz = 1000;
3311 }
3312 }
3313
3314 // convert to centiseconds
3315 time = (time * 100 + (hz / 2)) / hz;
3316
3317 char str[16];
3318
3319 snprintf(str, sizeof(str), " %llu.%02u",
3320 time / 100, (unsigned)(time % 100));
3321 size_t offset = strlen(buffer);
3322 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3323 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3324}
3325
3326// print permille as a percent
3327static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
3328 char str[16];
3329
3330 snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
3331 size_t offset = strlen(buffer);
3332 snprintf(buffer + offset, (len > offset) ? len - offset : 0,
3333 "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
3334}
3335
3336void show_showtime(int pid, const char *name) {
3337 if (PropertiesHelper::IsDryRun()) return;
3338
3339 char path[255];
3340 char buffer[1023];
3341 int fd, ret, save_errno;
3342
3343 memset(buffer, 0, sizeof(buffer));
3344
3345 snprintf(path, sizeof(path), "/proc/%d/stat", pid);
3346 if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
3347 printf("Failed to open '%s' (%s)\n", path, strerror(errno));
3348 return;
3349 }
3350
3351 ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3352 save_errno = errno;
3353 close(fd);
3354
3355 if (ret < 0) {
3356 printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
3357 return;
3358 }
3359
3360 // field 14 is utime
3361 // field 15 is stime
3362 // field 42 is iotime
3363 unsigned long long utime = 0, stime = 0, iotime = 0;
3364 if (sscanf(buffer,
3365 "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
3366 "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
3367 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
3368 "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
3369 &utime, &stime, &iotime) != 3) {
3370 return;
3371 }
3372
3373 unsigned long long total = utime + stime;
3374 if (!total) {
3375 return;
3376 }
3377
3378 unsigned permille = (iotime * 1000 + (total / 2)) / total;
3379 if (permille > 1000) {
3380 permille = 1000;
3381 }
3382
3383 // try to beautify and stabilize columns at <80 characters
3384 snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
3385 if ((name[0] != '[') || utime) {
3386 snprcent(buffer, sizeof(buffer), 57, utime);
3387 }
3388 snprcent(buffer, sizeof(buffer), 65, stime);
3389 if ((name[0] != '[') || iotime) {
3390 snprcent(buffer, sizeof(buffer), 73, iotime);
3391 }
3392 if (iotime) {
3393 snprdec(buffer, sizeof(buffer), 79, permille);
3394 }
3395 puts(buffer); // adds a trailing newline
3396
3397 return;
3398}
3399
3400void do_dmesg() {
3401 const char *title = "KERNEL LOG (dmesg)";
3402 DurationReporter duration_reporter(title);
3403 printf("------ %s ------\n", title);
3404
3405 if (PropertiesHelper::IsDryRun()) return;
3406
3407 /* Get size of kernel buffer */
3408 int size = klogctl(KLOG_SIZE_BUFFER, nullptr, 0);
3409 if (size <= 0) {
3410 printf("Unexpected klogctl return value: %d\n\n", size);
3411 return;
3412 }
3413 char *buf = (char *) malloc(size + 1);
3414 if (buf == nullptr) {
3415 printf("memory allocation failed\n\n");
3416 return;
3417 }
3418 int retval = klogctl(KLOG_READ_ALL, buf, size);
3419 if (retval < 0) {
3420 printf("klogctl failure\n\n");
3421 free(buf);
3422 return;
3423 }
3424 buf[retval] = '\0';
3425 printf("%s\n\n", buf);
3426 free(buf);
3427 return;
3428}
3429
3430void do_showmap(int pid, const char *name) {
3431 char title[255];
3432 char arg[255];
3433
3434 snprintf(title, sizeof(title), "SHOW MAP %d (%s)", pid, name);
3435 snprintf(arg, sizeof(arg), "%d", pid);
3436 RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT);
3437}
3438
3439int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
3440 DurationReporter duration_reporter(title);
3441
3442 int status = DumpFileToFd(STDOUT_FILENO, title, path);
3443
3444 UpdateProgress(WEIGHT_FILE);
3445
3446 return status;
3447}
3448
3449int read_file_as_long(const char *path, long int *output) {
3450 int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
3451 if (fd < 0) {
3452 int err = errno;
3453 MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
3454 return -1;
3455 }
3456 char buffer[50];
3457 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
3458 if (bytes_read == -1) {
3459 MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
3460 return -2;
3461 }
3462 if (bytes_read == 0) {
3463 MYLOGE("File %s is empty\n", path);
3464 return -3;
3465 }
3466 *output = atoi(buffer);
3467 return 0;
3468}
3469
3470/* calls skip to gate calling dump_from_fd recursively
3471 * in the specified directory. dump_from_fd defaults to
3472 * dump_file_from_fd above when set to NULL. skip defaults
3473 * to false when set to NULL. dump_from_fd will always be
3474 * called with title NULL.
3475 */
3476int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
3477 int (*dump_from_fd)(const char* title, const char* path, int fd)) {
3478 DurationReporter duration_reporter(title);
3479 DIR *dirp;
3480 struct dirent *d;
3481 char *newpath = nullptr;
3482 const char *slash = "/";
3483 int retval = 0;
3484
3485 if (!title.empty()) {
3486 printf("------ %s (%s) ------\n", title.c_str(), dir);
3487 }
3488 if (PropertiesHelper::IsDryRun()) return 0;
3489
3490 if (dir[strlen(dir) - 1] == '/') {
3491 ++slash;
3492 }
3493 dirp = opendir(dir);
3494 if (dirp == nullptr) {
3495 retval = -errno;
3496 MYLOGE("%s: %s\n", dir, strerror(errno));
3497 return retval;
3498 }
3499
3500 if (!dump_from_fd) {
3501 dump_from_fd = dump_file_from_fd;
3502 }
3503 for (; ((d = readdir(dirp))); free(newpath), newpath = nullptr) {
3504 if ((d->d_name[0] == '.')
3505 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
3506 || (d->d_name[1] == '\0'))) {
3507 continue;
3508 }
3509 asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
3510 (d->d_type == DT_DIR) ? "/" : "");
3511 if (!newpath) {
3512 retval = -errno;
3513 continue;
3514 }
3515 if (skip && (*skip)(newpath)) {
3516 continue;
3517 }
3518 if (d->d_type == DT_DIR) {
3519 int ret = dump_files("", newpath, skip, dump_from_fd);
3520 if (ret < 0) {
3521 retval = ret;
3522 }
3523 continue;
3524 }
3525 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
3526 if (fd.get() < 0) {
3527 retval = -1;
3528 printf("*** %s: %s\n", newpath, strerror(errno));
3529 continue;
3530 }
3531 (*dump_from_fd)(nullptr, newpath, fd.get());
3532 }
3533 closedir(dirp);
3534 if (!title.empty()) {
3535 printf("\n");
3536 }
3537 return retval;
3538}
3539
3540/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
3541 * it's possible to avoid issues where opening the file itself can get
3542 * stuck.
3543 */
3544int dump_file_from_fd(const char *title, const char *path, int fd) {
3545 if (PropertiesHelper::IsDryRun()) return 0;
3546
3547 int flags = fcntl(fd, F_GETFL);
3548 if (flags == -1) {
3549 printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
3550 return -1;
3551 } else if (!(flags & O_NONBLOCK)) {
3552 printf("*** %s: fd must have O_NONBLOCK set.\n", path);
3553 return -1;
3554 }
3555 return DumpFileFromFdToFd(title, path, fd, STDOUT_FILENO, PropertiesHelper::IsDryRun());
3556}
3557
3558int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Nandana Dutt8d945c02019-08-14 13:30:07 +01003559 const CommandOptions& options, bool verbose_duration) {
3560 DurationReporter duration_reporter(title, false /* logcat_only */, verbose_duration);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003561
3562 int status = RunCommandToFd(STDOUT_FILENO, title, full_command, options);
3563
3564 /* TODO: for now we're simplifying the progress calculation by using the
3565 * timeout as the weight. It's a good approximation for most cases, except when calling dumpsys,
3566 * where its weight should be much higher proportionally to its timeout.
3567 * Ideally, it should use a options.EstimatedDuration() instead...*/
3568 UpdateProgress(options.Timeout());
3569
3570 return status;
3571}
3572
3573void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args,
3574 const CommandOptions& options, long dumpsysTimeoutMs) {
3575 long timeout_ms = dumpsysTimeoutMs > 0 ? dumpsysTimeoutMs : options.TimeoutInMs();
3576 std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-T", std::to_string(timeout_ms)};
3577 dumpsys.insert(dumpsys.end(), dumpsys_args.begin(), dumpsys_args.end());
3578 RunCommand(title, dumpsys, options);
3579}
3580
3581int open_socket(const char *service) {
3582 int s = android_get_control_socket(service);
3583 if (s < 0) {
3584 MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
3585 return -1;
3586 }
3587 fcntl(s, F_SETFD, FD_CLOEXEC);
3588
3589 // Set backlog to 0 to make sure that queue size will be minimum.
3590 // In Linux, because the minimum queue will be 1, connect() will be blocked
3591 // if the other clients already called connect() and the connection request was not accepted.
3592 if (listen(s, 0) < 0) {
3593 MYLOGE("listen(control socket): %s\n", strerror(errno));
3594 return -1;
3595 }
3596
3597 struct sockaddr addr;
3598 socklen_t alen = sizeof(addr);
Abhijeet Kaur2113cae2019-09-13 09:24:15 +01003599 int fd = accept4(s, &addr, &alen, SOCK_CLOEXEC);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003600
3601 // Close socket just after accept(), to make sure that connect() by client will get error
3602 // when the socket is used by the other services.
3603 // There is still a race condition possibility between accept and close, but there is no way
3604 // to close-on-accept atomically.
3605 // See detail; b/123306389#comment25
3606 close(s);
3607
3608 if (fd < 0) {
3609 MYLOGE("accept(control socket): %s\n", strerror(errno));
3610 return -1;
3611 }
3612
3613 return fd;
3614}
3615
3616/* redirect output to a service control socket */
3617bool redirect_to_socket(FILE* redirect, const char* service) {
3618 int fd = open_socket(service);
3619 if (fd == -1) {
3620 return false;
3621 }
3622 fflush(redirect);
3623 // TODO: handle dup2 failure
3624 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3625 close(fd);
3626 return true;
3627}
3628
3629// TODO: should call is_valid_output_file and/or be merged into it.
3630void create_parent_dirs(const char *path) {
3631 char *chp = const_cast<char *> (path);
3632
3633 /* skip initial slash */
3634 if (chp[0] == '/')
3635 chp++;
3636
3637 /* create leading directories, if necessary */
3638 struct stat dir_stat;
3639 while (chp && chp[0]) {
3640 chp = strchr(chp, '/');
3641 if (chp) {
3642 *chp = 0;
3643 if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
3644 MYLOGI("Creating directory %s\n", path);
3645 if (mkdir(path, 0770)) { /* drwxrwx--- */
3646 MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
3647 } else if (chown(path, AID_SHELL, AID_SHELL)) {
3648 MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
3649 }
3650 }
3651 *chp++ = '/';
3652 }
3653 }
3654}
3655
3656bool _redirect_to_file(FILE* redirect, char* path, int truncate_flag) {
3657 create_parent_dirs(path);
3658
3659 int fd = TEMP_FAILURE_RETRY(open(path,
3660 O_WRONLY | O_CREAT | truncate_flag | O_CLOEXEC | O_NOFOLLOW,
3661 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
3662 if (fd < 0) {
3663 MYLOGE("%s: %s\n", path, strerror(errno));
3664 return false;
3665 }
3666
3667 TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
3668 close(fd);
3669 return true;
3670}
3671
3672bool redirect_to_file(FILE* redirect, char* path) {
3673 return _redirect_to_file(redirect, path, O_TRUNC);
3674}
3675
3676bool redirect_to_existing_file(FILE* redirect, char* path) {
3677 return _redirect_to_file(redirect, path, O_APPEND);
3678}
3679
3680void dump_route_tables() {
3681 DurationReporter duration_reporter("DUMP ROUTE TABLES");
3682 if (PropertiesHelper::IsDryRun()) return;
3683 const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
3684 ds.DumpFile("RT_TABLES", RT_TABLES_PATH);
3685 FILE* fp = fopen(RT_TABLES_PATH, "re");
3686 if (!fp) {
3687 printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
3688 return;
3689 }
3690 char table[16];
3691 // Each line has an integer (the table number), a space, and a string (the table name). We only
3692 // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
3693 // Add a fixed max limit so this doesn't go awry.
3694 for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
3695 RunCommand("ROUTE TABLE IPv4", {"ip", "-4", "route", "show", "table", table});
3696 RunCommand("ROUTE TABLE IPv6", {"ip", "-6", "route", "show", "table", table});
3697 }
3698 fclose(fp);
3699}
3700
3701// TODO: make this function thread safe if sections are generated in parallel.
3702void Dumpstate::UpdateProgress(int32_t delta_sec) {
3703 if (progress_ == nullptr) {
3704 MYLOGE("UpdateProgress: progress_ not set\n");
3705 return;
3706 }
3707
3708 // Always update progess so stats can be tuned...
Nandana Dutt402a8392019-06-14 14:25:13 +01003709 progress_->Inc(delta_sec);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003710
3711 // ...but only notifiy listeners when necessary.
3712 if (!options_->do_progress_updates) return;
3713
3714 int progress = progress_->Get();
3715 int max = progress_->GetMax();
Nandana Dutt402a8392019-06-14 14:25:13 +01003716 int percent = 100 * progress / max;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003717
Nandana Dutt402a8392019-06-14 14:25:13 +01003718 if (last_reported_percent_progress_ > 0 && percent <= last_reported_percent_progress_) {
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003719 return;
3720 }
Nandana Dutt402a8392019-06-14 14:25:13 +01003721 last_reported_percent_progress_ = percent;
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003722
3723 if (control_socket_fd_ >= 0) {
3724 dprintf(control_socket_fd_, "PROGRESS:%d/%d\n", progress, max);
3725 fsync(control_socket_fd_);
3726 }
3727
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003728 if (listener_ != nullptr) {
Nandana Dutt235c6672019-11-14 15:22:32 +00003729 if (percent % 10 == 0) {
3730 // We don't want to spam logcat, so only log multiples of 10.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003731 MYLOGD("Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003732 } else {
3733 // stderr is ignored on normal invocations, but useful when calling
3734 // /system/bin/dumpstate directly for debuggging.
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01003735 fprintf(stderr, "Setting progress: %d/%d (%d%%)\n", progress, max, percent);
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003736 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003737
3738 listener_->onProgress(percent);
3739 }
3740}
3741
3742void Dumpstate::TakeScreenshot(const std::string& path) {
3743 const std::string& real_path = path.empty() ? screenshot_path_ : path;
3744 int status =
3745 RunCommand("", {"/system/bin/screencap", "-p", real_path},
3746 CommandOptions::WithTimeout(10).Always().DropRoot().RedirectStderr().Build());
3747 if (status == 0) {
3748 MYLOGD("Screenshot saved on %s\n", real_path.c_str());
3749 } else {
3750 MYLOGE("Failed to take screenshot on %s\n", real_path.c_str());
3751 }
Paul Chang0d2aad72020-02-13 20:04:03 +08003752 if (listener_ != nullptr) {
3753 // Show a visual indication to indicate screenshot is taken via
3754 // IDumpstateListener.onScreenshotTaken()
3755 listener_->onScreenshotTaken(status == 0);
3756 }
Abhijeet Kaurcf234e82019-07-01 14:53:55 +01003757}
3758
3759bool is_dir(const char* pathname) {
3760 struct stat info;
3761 if (stat(pathname, &info) == -1) {
3762 return false;
3763 }
3764 return S_ISDIR(info.st_mode);
3765}
3766
3767time_t get_mtime(int fd, time_t default_mtime) {
3768 struct stat info;
3769 if (fstat(fd, &info) == -1) {
3770 return default_mtime;
3771 }
3772 return info.st_mtime;
3773}