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