blob: 704c5f2e4739f419a6f017d308a99faec38a69cc [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>
Felipe Lemead5f6c42015-11-30 14:26:46 -080022#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070023#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070024#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080028#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070029#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <sys/resource.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/wait.h>
34#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070035
36#include <chrono>
37#include <functional>
38#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010039#include <memory>
40#include <regex>
41#include <set>
42#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070043#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010044#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070045
Felipe Leme96c2bbb2016-09-26 09:21:21 -070046#include <android-base/file.h>
47#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070048#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080049#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070050#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070051#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080052#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080053#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000054#include <android/os/IIncidentCompanion.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080055#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070056#include <cutils/properties.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000057#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080058#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000059#include <dumputils/dump_utils.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080060#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070061#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070062#include <private/android_filesystem_config.h>
63#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080064#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070065#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080066#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080067#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070068#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070069#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080070
Steven Morelandcb7ef822016-11-29 13:20:37 -080071using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080072using ::std::literals::chrono_literals::operator""ms;
73using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080074
Felipe Leme47e9be22016-12-21 15:37:07 -080075// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080076using android::defaultServiceManager;
77using android::Dumpsys;
78using android::INVALID_OPERATION;
79using android::IServiceManager;
80using android::OK;
81using android::sp;
82using android::status_t;
83using android::String16;
84using android::String8;
85using android::TIMED_OUT;
86using android::UNKNOWN_ERROR;
87using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +000088using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +000089using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -080090using android::os::dumpstate::CommandOptions;
91using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080092using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080093using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080094using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080095
Nandana Duttd2f5f082019-01-18 17:13:52 +000096typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
97
Colin Crossf45fa6b2012-03-26 12:38:26 -070098/* read before root is shed */
99static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700100static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000101static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700102
Felipe Leme1d486fe2016-10-14 18:06:47 -0700103// TODO: variables and functions below should be part of dumpstate object
104
Felipe Leme635ca312016-01-05 14:23:02 -0800105static std::set<std::string> mount_points;
106void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800107
Todd Poynor2a83daa2013-11-22 15:44:22 -0800108#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700109#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700110#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800111
Felipe Lemee82a27d2016-01-05 13:35:44 -0800112#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700113#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700114#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700115#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100116#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
117#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800118#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900119#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800120#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700121
Narayan Kamath8f788292017-05-25 13:20:39 +0100122// TODO(narayan): Since this information has to be kept in sync
123// with tombstoned, we should just put it in a common header.
124//
125// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100126static const std::string TOMBSTONE_DIR = "/data/tombstones/";
127static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
128static const std::string ANR_DIR = "/data/anr/";
129static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700130
Felipe Lemee844a9d2016-09-21 15:01:39 -0700131// TODO: temporary variables and functions used during C++ refactoring
132static Dumpstate& ds = Dumpstate::GetInstance();
Nandana Dutt979388e2018-11-30 16:48:55 +0000133
Nandana Dutt5c390032019-03-12 10:52:56 +0000134#define RETURN_IF_USER_DENIED_CONSENT() \
135 if (ds.IsUserConsentDenied()) { \
136 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
137 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
138 }
139
140// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
141// if consent is found to be denied.
142#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
143 RETURN_IF_USER_DENIED_CONSENT(); \
144 func_ptr(__VA_ARGS__); \
145 RETURN_IF_USER_DENIED_CONSENT();
146
Nandana Dutt979388e2018-11-30 16:48:55 +0000147namespace android {
148namespace os {
149namespace {
150
151static int Open(std::string path, int flags, mode_t mode = 0) {
152 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
153 if (fd == -1) {
154 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
155 }
156 return fd;
157}
158
Nandana Dutt979388e2018-11-30 16:48:55 +0000159
160static int OpenForRead(std::string path) {
161 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
162}
163
164bool CopyFile(int in_fd, int out_fd) {
165 char buf[4096];
166 ssize_t byte_count;
167 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
168 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
169 return false;
170 }
171 }
172 return (byte_count != -1);
173}
174
175static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000176 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000177
178 // Obtain a handle to the source file.
179 android::base::unique_fd in_fd(OpenForRead(input_file));
180 if (out_fd != -1 && in_fd.get() != -1) {
181 if (CopyFile(in_fd.get(), out_fd)) {
182 return true;
183 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000184 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000185 }
186 return false;
187}
188
Nandana Duttd2f5f082019-01-18 17:13:52 +0000189static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000190 if (unlink(file.c_str())) {
191 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000192 return false;
193 }
194 return true;
195}
Nandana Dutt979388e2018-11-30 16:48:55 +0000196
197} // namespace
198} // namespace os
199} // namespace android
200
Felipe Leme678727a2016-09-21 17:22:11 -0700201static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
202 const CommandOptions& options = CommandOptions::DEFAULT) {
203 return ds.RunCommand(title, fullCommand, options);
204}
205static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800206 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800207 long dumpsysTimeoutMs = 0) {
208 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700209}
210static int DumpFile(const std::string& title, const std::string& path) {
211 return ds.DumpFile(title, path);
212}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800213
Felipe Lemee844a9d2016-09-21 15:01:39 -0700214// Relative directory (inside the zip) for all files copied as-is into the bugreport.
215static const std::string ZIP_ROOT_DIR = "FS";
216
Vishnu Naire97d6122018-01-18 13:58:56 -0800217static const std::string kProtoPath = "proto/";
218static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700219static const std::string kDumpstateBoardFiles[] = {
220 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700221 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700222};
223static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
224
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700225static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700226static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700227static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700228static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
229static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700230
Felipe Lemef0292972016-11-22 13:57:05 -0800231static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
232
Narayan Kamath8f788292017-05-25 13:20:39 +0100233/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100234 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
235 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
236 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700237 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100238 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700239static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
240 const std::string& file_prefix,
241 bool limit_by_mtime,
242 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100243 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
244
Narayan Kamathbd863722017-06-01 18:50:12 +0100245 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100246
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700247 if (dump_dir == nullptr) {
248 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700249 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700250 }
251
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700252 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100253 struct dirent* entry = nullptr;
254 while ((entry = readdir(dump_dir.get()))) {
255 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100256 continue;
257 }
258
Narayan Kamathbd863722017-06-01 18:50:12 +0100259 const std::string base_name(entry->d_name);
260 if (base_name.find(file_prefix) != 0) {
261 continue;
262 }
263
264 const std::string abs_path = dir_path + base_name;
265 android::base::unique_fd fd(
266 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
267 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700268 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100269 break;
270 }
271
272 struct stat st = {};
273 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700274 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100275 continue;
276 }
277
Narayan Kamath3f31b632018-02-22 19:42:36 +0000278 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100279 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100280 continue;
281 }
282
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700283 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700284 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100285
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700286 // Sort in descending modification time so that we only keep the newest
287 // reports if |limit_by_count| is true.
288 std::sort(dump_data.begin(), dump_data.end(),
289 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100290
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700291 if (limit_by_count && dump_data.size() > 10) {
292 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700293 }
294
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700295 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100296}
297
Narayan Kamathbd863722017-06-01 18:50:12 +0100298static bool AddDumps(const std::vector<DumpData>::const_iterator start,
299 const std::vector<DumpData>::const_iterator end,
300 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100301 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100302 for (auto it = start; it != end; ++it) {
303 const std::string& name = it->name;
304 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100305 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100306
307 // Seek to the beginning of the file before dumping any data. A given
308 // DumpData entry might be dumped multiple times in the report.
309 //
310 // For example, the most recent ANR entry is dumped to the body of the
311 // main entry and it also shows up as a separate entry in the bugreport
312 // ZIP file.
313 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
314 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
315 strerror(errno));
316 }
317
Narayan Kamath8f788292017-05-25 13:20:39 +0100318 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800319 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100320 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100321 }
322 } else {
323 dump_file_from_fd(type_name, name.c_str(), fd);
324 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100325 }
326
327 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700328}
329
Felipe Leme635ca312016-01-05 14:23:02 -0800330// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700331void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800332 char path[PATH_MAX];
333
334 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
335 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700336 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800337 char linkname[PATH_MAX];
338 ssize_t r = readlink(path, linkname, PATH_MAX);
339 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800340 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800341 return;
342 }
343 linkname[r] = '\0';
344
345 if (mount_points.find(linkname) == mount_points.end()) {
346 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700347 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700348 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800349 mount_points.insert(linkname);
350 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800351 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800352 }
353 }
354}
355
356void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700357 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700358 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800359 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800360 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700361 for_each_pid(do_mountinfo, nullptr);
362 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800363}
364
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700365static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
366{
367 DIR *d;
368 struct dirent *de;
369 char path[PATH_MAX];
370
371 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700372 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700373 return;
374 }
375
376 while ((de = readdir(d))) {
377 if (de->d_type != DT_LNK) {
378 continue;
379 }
380 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700381 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700382 }
383
384 closedir(d);
385}
386
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700387
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700388
389// dump anrd's trace and add to the zip file.
390// 1. check if anrd is running on this device.
391// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
392// 3. wait until the trace generation completes and add to the zip file.
393static bool dump_anrd_trace() {
394 unsigned int pid;
395 char buf[50], path[PATH_MAX];
396 struct dirent *trace;
397 struct stat st;
398 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700399 int retry = 5;
400 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700401 long long cur_size = 0;
402 const char *trace_path = "/data/misc/anrd/";
403
Felipe Leme1d486fe2016-10-14 18:06:47 -0700404 if (!ds.IsZipping()) {
405 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700406 return false;
407 }
408
409 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700410 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700411
412 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700413 if (stat(trace_path, &st) == 0) {
414 old_mtime = st.st_mtime;
415 } else {
416 MYLOGE("Failed to find: %s\n", trace_path);
417 return false;
418 }
419
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700420 // send SIGUSR1 to the anrd to generate a trace.
421 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700422 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700423 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700424 MYLOGE("anrd signal timed out. Please manually collect trace\n");
425 return false;
426 }
427
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700428 while (retry-- > 0 && old_mtime == st.st_mtime) {
429 sleep(1);
430 stat(trace_path, &st);
431 }
432
433 if (retry < 0 && old_mtime == st.st_mtime) {
434 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
435 return false;
436 }
437
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700438 // identify the trace file by its creation time.
439 if (!(trace_dir = opendir(trace_path))) {
440 MYLOGE("Can't open trace file under %s\n", trace_path);
441 }
442 while ((trace = readdir(trace_dir))) {
443 if (strcmp(trace->d_name, ".") == 0
444 || strcmp(trace->d_name, "..") == 0) {
445 continue;
446 }
447 sprintf(path, "%s%s", trace_path, trace->d_name);
448 if (stat(path, &st) == 0) {
449 if (st.st_ctime > max_ctime) {
450 max_ctime = st.st_ctime;
451 sprintf(buf, "%s", trace->d_name);
452 }
453 }
454 }
455 closedir(trace_dir);
456
457 // Wait until the dump completes by checking the size of the trace.
458 if (max_ctime > 0) {
459 sprintf(path, "%s%s", trace_path, buf);
460 while(true) {
461 sleep(1);
462 if (stat(path, &st) == 0) {
463 if (st.st_size == cur_size) {
464 break;
465 } else if (st.st_size > cur_size) {
466 cur_size = st.st_size;
467 } else {
468 return false;
469 }
470 } else {
471 MYLOGE("Cant stat() %s anymore\n", path);
472 return false;
473 }
474 }
475 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700476 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700477 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
478 } else {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000479 android::os::UnlinkAndLogOnError(path);
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700480 return true;
481 }
482 } else {
483 MYLOGE("Can't stats any trace file under %s\n", trace_path);
484 }
485 }
486 return false;
487}
488
Mark Salyzyn326842f2015-04-30 09:49:41 -0700489static bool skip_not_stat(const char *path) {
490 static const char stat[] = "/stat";
491 size_t len = strlen(path);
492 if (path[len - 1] == '/') { /* Directory? */
493 return false;
494 }
495 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
496}
497
Felipe Leme4c2d6632016-09-28 14:32:00 -0700498static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800499 return false;
500}
501
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700502unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700503
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800504//
505// stat offsets
506// Name units description
507// ---- ----- -----------
508// read I/Os requests number of read I/Os processed
509#define __STAT_READ_IOS 0
510// read merges requests number of read I/Os merged with in-queue I/O
511#define __STAT_READ_MERGES 1
512// read sectors sectors number of sectors read
513#define __STAT_READ_SECTORS 2
514// read ticks milliseconds total wait time for read requests
515#define __STAT_READ_TICKS 3
516// write I/Os requests number of write I/Os processed
517#define __STAT_WRITE_IOS 4
518// write merges requests number of write I/Os merged with in-queue I/O
519#define __STAT_WRITE_MERGES 5
520// write sectors sectors number of sectors written
521#define __STAT_WRITE_SECTORS 6
522// write ticks milliseconds total wait time for write requests
523#define __STAT_WRITE_TICKS 7
524// in_flight requests number of I/Os currently in flight
525#define __STAT_IN_FLIGHT 8
526// io_ticks milliseconds total time this block device has been active
527#define __STAT_IO_TICKS 9
528// time_in_queue milliseconds total wait time for all requests
529#define __STAT_IN_QUEUE 10
530#define __STAT_NUMBER_FIELD 11
531//
532// read I/Os, write I/Os
533// =====================
534//
535// These values increment when an I/O request completes.
536//
537// read merges, write merges
538// =========================
539//
540// These values increment when an I/O request is merged with an
541// already-queued I/O request.
542//
543// read sectors, write sectors
544// ===========================
545//
546// These values count the number of sectors read from or written to this
547// block device. The "sectors" in question are the standard UNIX 512-byte
548// sectors, not any device- or filesystem-specific block size. The
549// counters are incremented when the I/O completes.
550#define SECTOR_SIZE 512
551//
552// read ticks, write ticks
553// =======================
554//
555// These values count the number of milliseconds that I/O requests have
556// waited on this block device. If there are multiple I/O requests waiting,
557// these values will increase at a rate greater than 1000/second; for
558// example, if 60 read requests wait for an average of 30 ms, the read_ticks
559// field will increase by 60*30 = 1800.
560//
561// in_flight
562// =========
563//
564// This value counts the number of I/O requests that have been issued to
565// the device driver but have not yet completed. It does not include I/O
566// requests that are in the queue but not yet issued to the device driver.
567//
568// io_ticks
569// ========
570//
571// This value counts the number of milliseconds during which the device has
572// had I/O requests queued.
573//
574// time_in_queue
575// =============
576//
577// This value counts the number of milliseconds that I/O requests have waited
578// on this block device. If there are multiple I/O requests waiting, this
579// value will increase as the product of the number of milliseconds times the
580// number of requests waiting (see "read ticks" above for an example).
581#define S_TO_MS 1000
582//
583
Mark Salyzyn326842f2015-04-30 09:49:41 -0700584static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800585 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700586 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700587 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700588 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700589 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700590 getline(&buffer, &i, fp);
591 fclose(fp);
592 if (!buffer) {
593 return -errno;
594 }
595 i = strlen(buffer);
596 while ((i > 0) && (buffer[i - 1] == '\n')) {
597 buffer[--i] = '\0';
598 }
599 if (!*buffer) {
600 free(buffer);
601 return 0;
602 }
603 z = true;
604 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800605 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700606 if (fields[i] != 0) {
607 z = false;
608 }
609 }
610 if (z) { /* never accessed */
611 free(buffer);
612 return 0;
613 }
614
Wei Wang509bb5d2017-06-09 14:42:12 -0700615 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
616 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700617 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700618
619 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
620 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
621 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700622 free(buffer);
623
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800624 if (fields[__STAT_IO_TICKS]) {
625 unsigned long read_perf = 0;
626 unsigned long read_ios = 0;
627 if (fields[__STAT_READ_TICKS]) {
628 unsigned long long divisor = fields[__STAT_READ_TICKS]
629 * fields[__STAT_IO_TICKS];
630 read_perf = ((unsigned long long)SECTOR_SIZE
631 * fields[__STAT_READ_SECTORS]
632 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
633 / divisor;
634 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
635 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
636 / divisor;
637 }
638
639 unsigned long write_perf = 0;
640 unsigned long write_ios = 0;
641 if (fields[__STAT_WRITE_TICKS]) {
642 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
643 * fields[__STAT_IO_TICKS];
644 write_perf = ((unsigned long long)SECTOR_SIZE
645 * fields[__STAT_WRITE_SECTORS]
646 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
647 / divisor;
648 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
649 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
650 / divisor;
651 }
652
653 unsigned queue = (fields[__STAT_IN_QUEUE]
654 + (fields[__STAT_IO_TICKS] >> 1))
655 / fields[__STAT_IO_TICKS];
656
657 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700658 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 -0800659 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700660 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 -0800661 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800662 }
663
664 /* bugreport timeout factor adjustment */
665 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
666 worst_write_perf = write_perf;
667 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700668 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700669 return 0;
670}
671
Yao Chenbe3bbc12018-01-17 16:31:10 -0800672static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
673
674/* timeout in ms to read a list of buffers */
675static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
676 unsigned long timeout_ms = 0;
677 for (const auto& buffer : buffers) {
678 log_id_t id = android_name_to_log_id(buffer.c_str());
679 unsigned long property_size = __android_logger_get_buffer_size(id);
680 /* Engineering margin is ten-fold our guess */
681 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
682 }
683 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700684}
685
Nandana Duttd2f5f082019-01-18 17:13:52 +0000686Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
687}
688
689android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
690 std::lock_guard<std::mutex> lock(lock_);
691 result_ = APPROVED;
692 MYLOGD("User approved consent to share bugreport\n");
693 return android::binder::Status::ok();
694}
695
696android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
697 std::lock_guard<std::mutex> lock(lock_);
698 result_ = DENIED;
699 MYLOGW("User denied consent to share bugreport\n");
700 return android::binder::Status::ok();
701}
702
703UserConsentResult Dumpstate::ConsentCallback::getResult() {
704 std::lock_guard<std::mutex> lock(lock_);
705 return result_;
706}
707
708uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
709 return Nanotime() - start_time_;
710}
711
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700712void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700713 std::string build, fingerprint, radio, bootloader, network;
714 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700715
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700716 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
717 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700718 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
719 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
720 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700721 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700722
Felipe Lemed8b94e52016-12-08 10:21:44 -0800723 printf("========================================================\n");
724 printf("== dumpstate: %s\n", date);
725 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700726
Felipe Lemed8b94e52016-12-08 10:21:44 -0800727 printf("\n");
728 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700729 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800730 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
731 printf("Bootloader: %s\n", bootloader.c_str());
732 printf("Radio: %s\n", radio.c_str());
733 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700734
Felipe Lemed8b94e52016-12-08 10:21:44 -0800735 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800736 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800737 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800738 printf("Uptime: ");
739 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
740 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800741 printf("Bugreport format version: %s\n", version_.c_str());
742 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100743 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800744 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800745}
746
Felipe Leme24b66ee2016-06-16 10:55:26 -0700747// List of file extensions that can cause a zip file attachment to be rejected by some email
748// service providers.
749static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
750 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
751 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
752 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
753};
754
Vishnu Naire97d6122018-01-18 13:58:56 -0800755status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
756 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700757 if (!IsZipping()) {
758 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
759 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800760 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800761 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700762 std::string valid_name = entry_name;
763
764 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700765 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700766 if (idx != std::string::npos) {
767 std::string extension = entry_name.substr(idx);
768 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
769 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
770 valid_name = entry_name + ".renamed";
771 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
772 }
773 }
774
Felipe Leme6fe9db62016-02-12 09:04:16 -0800775 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
776 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700777 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
778 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700779 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700780 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700781 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800782 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800783 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000784 bool finished_entry = false;
785 auto finish_entry = [this, &finished_entry] {
786 if (!finished_entry) {
787 // This should only be called when we're going to return an earlier error,
788 // which would've been logged. This may imply the file is already corrupt
789 // and any further logging from FinishEntry is more likely to mislead than
790 // not.
791 this->zip_writer_->FinishEntry();
792 }
793 };
794 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800795 auto start = std::chrono::steady_clock::now();
796 auto end = start + timeout;
797 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800798
Felipe Leme770410d2016-01-26 17:07:14 -0800799 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800800 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800801 if (timeout.count() > 0) {
802 // lambda to recalculate the timeout.
803 auto time_left_ms = [end]() {
804 auto now = std::chrono::steady_clock::now();
805 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
806 return std::max(diff.count(), 0LL);
807 };
808
809 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
810 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000811 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
812 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800813 return -errno;
814 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000815 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800816 entry_name.c_str(), strerror(errno), timeout.count());
817 return TIMED_OUT;
818 }
819 }
820
Zach Riggle22200402016-08-18 01:01:24 -0400821 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800822 if (bytes_read == 0) {
823 break;
824 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800825 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800826 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800827 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700828 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800829 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700830 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800831 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800832 }
833 }
834
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700835 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000836 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700837 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700838 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800839 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800840 }
841
Vishnu Naire97d6122018-01-18 13:58:56 -0800842 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800843}
844
Felipe Leme1d486fe2016-10-14 18:06:47 -0700845bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
846 android::base::unique_fd fd(
847 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700848 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800849 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800850 return false;
851 }
852
Vishnu Naire97d6122018-01-18 13:58:56 -0800853 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800854}
855
856/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700857static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800858 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800859}
860
Felipe Leme1d486fe2016-10-14 18:06:47 -0700861void Dumpstate::AddDir(const std::string& dir, bool recursive) {
862 if (!IsZipping()) {
863 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800864 return;
865 }
Felipe Leme678727a2016-09-21 17:22:11 -0700866 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800867 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700868 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800869}
870
Felipe Leme1d486fe2016-10-14 18:06:47 -0700871bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
872 if (!IsZipping()) {
873 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
874 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800875 return false;
876 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800877 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700878 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700879 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700880 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700881 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800882 return false;
883 }
884
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700885 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700886 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700887 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700888 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800889 return false;
890 }
891
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700892 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700893 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700894 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800895 return false;
896 }
897
898 return true;
899}
900
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800901static void DoKmsg() {
902 struct stat st;
903 if (!stat(PSTORE_LAST_KMSG, &st)) {
904 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
905 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
906 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
907 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
908 } else {
909 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
910 DumpFile("LAST KMSG", "/proc/last_kmsg");
911 }
912}
913
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800914static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800915 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800916 RunCommand(
917 "KERNEL LOG",
918 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
919 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
920}
921
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800922static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800923 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800924 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
925 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800926 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100927 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800928 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
929 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800930 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800931 RunCommand(
932 "EVENT LOG",
933 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
934 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800935 timeout_ms = logcat_timeout({"stats"});
936 RunCommand(
937 "STATS LOG",
938 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
939 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
940 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800941 RunCommand(
942 "RADIO LOG",
943 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
944 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800945
946 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
947
948 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800949 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
950 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800951}
952
Jayachandran Ca94c7172017-06-10 15:08:12 -0700953static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700954 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
955 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900956 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700957 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900958 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
959 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
960 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
961 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700962}
963
Narayan Kamath8f788292017-05-25 13:20:39 +0100964static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
965 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
966 anr_traces_dir.c_str());
967
968 // If we're here, dump_traces_path will always be a temporary file
969 // (created with mkostemp or similar) that contains dumps taken earlier
970 // on in the process.
971 if (dump_traces_path != nullptr) {
972 if (add_to_zip) {
973 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
974 } else {
975 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
976 dump_traces_path);
977 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
978 }
979
980 const int ret = unlink(dump_traces_path);
981 if (ret == -1) {
982 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
983 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700984 }
985 }
986
Narayan Kamathbd863722017-06-01 18:50:12 +0100987 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700988 if (ds.anr_data_.size() > 0) {
989 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +0100990 "VM TRACES AT LAST ANR", add_to_zip);
991
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100992 // The "last" ANR will always be included as separate entry in the zip file. In addition,
993 // it will be present in the body of the main entry if |add_to_zip| == false.
994 //
995 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700996 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100997 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100998 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100999 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1000 }
1001}
1002
1003static void AddAnrTraceFiles() {
1004 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1005
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001006 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001007
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001008 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001009
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001010 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1011
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001012 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001013 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001014 int i = 0;
1015 while (true) {
1016 const std::string slow_trace_path =
1017 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1018 if (stat(slow_trace_path.c_str(), &st)) {
1019 // No traces file at this index, done with the files.
1020 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001021 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001022 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1023 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001024 }
1025}
1026
Wei Wang509bb5d2017-06-09 14:42:12 -07001027static void DumpBlockStatFiles() {
1028 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001029
Wei Wang1dc1ef52017-06-12 11:28:37 -07001030 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1031
1032 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001033 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1034 return;
1035 }
1036
1037 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001038 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001039 if ((d->d_name[0] == '.')
1040 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1041 || (d->d_name[1] == '\0'))) {
1042 continue;
1043 }
1044 const std::string new_path =
1045 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1046 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1047 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1048 printf("\n");
1049 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001050 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001051}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001052
1053static void DumpPacketStats() {
1054 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1055 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1056 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1057 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1058 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1059}
1060
1061static void DumpIpAddrAndRules() {
1062 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1063 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1064 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1065 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1066 RunCommand("IP RULES", {"ip", "rule", "show"});
1067 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1068}
1069
Nandana Dutt5c390032019-03-12 10:52:56 +00001070static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1071 std::chrono::milliseconds timeout,
1072 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001073 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001074 sp<android::IServiceManager> sm = defaultServiceManager();
1075 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001076 Vector<String16> args;
1077 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001078 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1079 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001080 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001081 std::string path(title);
1082 path.append(" - ").append(String8(service).c_str());
1083 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1084 size_t bytes_written = 0;
1085 status_t status = dumpsys.startDumpThread(service, args);
1086 if (status == OK) {
1087 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1088 std::chrono::duration<double> elapsed_seconds;
1089 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1090 /* as_proto = */ false, elapsed_seconds, bytes_written);
1091 section_reporter.setSize(bytes_written);
1092 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1093 bool dump_complete = (status == OK);
1094 dumpsys.stopDumpThread(dump_complete);
1095 }
1096 section_reporter.setStatus(status);
1097
1098 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1099 std::chrono::steady_clock::now() - start);
1100 if (elapsed_duration > timeout) {
1101 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1102 elapsed_duration.count());
1103 break;
1104 }
1105 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001106 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001107}
1108
Vishnu Nair64afc022018-02-01 15:29:34 -08001109static void RunDumpsysText(const std::string& title, int priority,
1110 std::chrono::milliseconds timeout,
1111 std::chrono::milliseconds service_timeout) {
1112 DurationReporter duration_reporter(title);
1113 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1114 fsync(STDOUT_FILENO);
1115 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1116}
1117
1118/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001119static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1120 std::chrono::milliseconds timeout,
1121 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001122 DurationReporter duration_reporter(title);
1123 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1124 fsync(STDOUT_FILENO);
1125 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1126 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001127
1128 RETURN_IF_USER_DENIED_CONSENT();
1129
1130 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1131 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001132}
1133
Nandana Dutt5c390032019-03-12 10:52:56 +00001134static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1135 std::chrono::milliseconds timeout,
1136 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001137 if (!ds.IsZipping()) {
1138 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001139 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001140 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001141 sp<android::IServiceManager> sm = defaultServiceManager();
1142 Dumpsys dumpsys(sm.get());
1143 Vector<String16> args;
1144 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1145 DurationReporter duration_reporter(title);
1146
1147 auto start = std::chrono::steady_clock::now();
1148 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1149 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001150 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001151 std::string path(kProtoPath);
1152 path.append(String8(service).c_str());
1153 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1154 path.append("_CRITICAL");
1155 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1156 path.append("_HIGH");
1157 }
1158 path.append(kProtoExt);
1159 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1160 status_t status = dumpsys.startDumpThread(service, args);
1161 if (status == OK) {
1162 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1163 bool dumpTerminated = (status == OK);
1164 dumpsys.stopDumpThread(dumpTerminated);
1165 }
1166 ZipWriter::FileEntry file_entry;
1167 ds.zip_writer_->GetLastEntry(&file_entry);
1168 section_reporter.setSize(file_entry.compressed_size);
1169 section_reporter.setStatus(status);
1170
1171 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1172 std::chrono::steady_clock::now() - start);
1173 if (elapsed_duration > timeout) {
1174 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1175 elapsed_duration.count());
1176 break;
1177 }
1178 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001179 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001180}
1181
Nandana Dutta7db6342018-11-21 14:53:34 +00001182// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001183static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001184 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1185 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001186
1187 RETURN_IF_USER_DENIED_CONSENT();
1188
1189 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1190 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001191}
1192
1193// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001194static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001195 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1196 // high priority. Reduce timeout once they are able to dump in a shorter time or
1197 // moved to a parallel task.
1198 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1199 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001200
1201 RETURN_IF_USER_DENIED_CONSENT();
1202
1203 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1204 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001205}
1206
1207// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001208static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001209 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001210
1211 RETURN_IF_USER_DENIED_CONSENT();
1212
1213 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1214 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001215}
1216
Steven Moreland44cd9482018-01-04 16:24:13 -08001217static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001218 if (!ds.IsZipping()) {
1219 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1220 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1221 return;
1222 }
1223 DurationReporter duration_reporter("DUMP HALS");
1224 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1225 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1226
Steven Moreland44cd9482018-01-04 16:24:13 -08001227 using android::hidl::manager::V1_0::IServiceManager;
1228 using android::hardware::defaultServiceManager;
1229
1230 sp<IServiceManager> sm = defaultServiceManager();
1231 if (sm == nullptr) {
1232 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1233 return;
1234 }
1235
1236 auto ret = sm->list([&](const auto& interfaces) {
1237 for (const std::string& interface : interfaces) {
1238 std::string cleanName = interface;
1239 std::replace_if(cleanName.begin(),
1240 cleanName.end(),
1241 [](char c) {
1242 return !isalnum(c) &&
1243 std::string("@-_:.").find(c) == std::string::npos;
1244 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001245 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001246
1247 {
1248 auto fd = android::base::unique_fd(
1249 TEMP_FAILURE_RETRY(open(path.c_str(),
1250 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1251 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1252 if (fd < 0) {
1253 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1254 continue;
1255 }
1256 RunCommandToFd(fd,
1257 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001258 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001259 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1260
1261 bool empty = 0 == lseek(fd, 0, SEEK_END);
1262 if (!empty) {
1263 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1264 }
1265 }
1266
1267 unlink(path.c_str());
1268 }
1269 });
1270
1271 if (!ret.isOk()) {
1272 MYLOGE("Could not list hals from hwservicemanager.\n");
1273 }
1274}
1275
Nandana Dutt5c390032019-03-12 10:52:56 +00001276// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1277// via the consent they are shown. Ignores other errors that occur while running various
1278// commands. The consent checking is currently done around long running tasks, which happen to
1279// be distributed fairly evenly throughout the function.
1280static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001281 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001282
Nandana Dutt5c390032019-03-12 10:52:56 +00001283 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1284 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1285 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001286 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001287 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001288 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001289 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001290 DumpFile("MEMORY INFO", "/proc/meminfo");
1291 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001292 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001293
1294 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1295
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001296 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1297 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1298 DumpFile("SLAB INFO", "/proc/slabinfo");
1299 DumpFile("ZONEINFO", "/proc/zoneinfo");
1300 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1301 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1302 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001303
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001304 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1305 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1306 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001307
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001308 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001309 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001310
1311 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1312 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001313
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001314 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001315
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001316 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001317 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001318 struct stat s;
1319 if (stat("/proc/modules", &s) != 0) {
1320 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1321 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001322 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001323 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001324
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001325 if (__android_logger_property_get_bool(
1326 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1327 DoKernelLogcat();
1328 } else {
1329 do_dmesg();
1330 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001331
Felipe Lemef0292972016-11-22 13:57:05 -08001332 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001333
1334 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1335
Jeff Brown1dc94e32014-09-11 14:15:27 -07001336 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001337 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001338
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001339 /* Dump Bluetooth HCI logs */
1340 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001341
Felipe Leme9a523ae2016-10-20 15:10:33 -07001342 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001343 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001344 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001345 }
1346
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001347 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001348
Felipe Lemee184f662016-10-27 10:04:47 -07001349 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001350
Narayan Kamath8f788292017-05-25 13:20:39 +01001351 // NOTE: tombstones are always added as separate entries in the zip archive
1352 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001353 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001354 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001355 if (!tombstones_dumped) {
1356 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001357 }
1358
Jayachandran Ca94c7172017-06-10 15:08:12 -07001359 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001360
Chenbo Feng276a3b62018-08-07 11:44:49 -07001361 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1362
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001363 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001364
Jayachandran Ca94c7172017-06-10 15:08:12 -07001365 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001366
1367 dump_route_tables();
1368
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001369 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1370 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1371 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001372
Nandana Dutt5c390032019-03-12 10:52:56 +00001373 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001374
Elliott Hughes23ccc622017-02-28 10:14:22 -08001375 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001376
Jin Qianf334d662017-10-10 14:41:37 -07001377 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001378
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001379 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001380
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001381 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001382
Colin Crossf45fa6b2012-03-26 12:38:26 -07001383 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001384 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1385 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1386 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1387 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1388 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001389
Nataniel Borgesbc73f522019-01-25 16:37:16 -08001390 RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001391 /* Add window and surface trace files. */
1392 if (!PropertiesHelper::IsUserBuild()) {
1393 ds.AddDir(WMTRACE_DATA_DIR, false);
1394 }
1395
Nandana Dutt5c390032019-03-12 10:52:56 +00001396 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001397
Steven Moreland7440ddb2016-12-15 16:13:39 -08001398 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001399 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1400 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001401 // su does not exist on user builds, so try running without it.
1402 // This way any implementations of vril-dump that do not require
1403 // root can run on user builds.
1404 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001405 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001406 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001407 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001408 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001409 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001410 }
1411
Felipe Lemed8b94e52016-12-08 10:21:44 -08001412 printf("========================================================\n");
1413 printf("== Android Framework Services\n");
1414 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001415
Nandana Dutt5c390032019-03-12 10:52:56 +00001416 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001417
Felipe Lemed8b94e52016-12-08 10:21:44 -08001418 printf("========================================================\n");
1419 printf("== Checkins\n");
1420 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001421
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001422 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001423
1424 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1425
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001426 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1427 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1428 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1429 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001430
Felipe Lemed8b94e52016-12-08 10:21:44 -08001431 printf("========================================================\n");
1432 printf("== Running Application Activities\n");
1433 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001434
Makoto Onuki60780982018-04-16 15:34:00 -07001435 // The following dumpsys internally collects output from running apps, so it can take a long
1436 // time. So let's extend the timeout.
1437
1438 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1439
1440 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001441
Felipe Lemed8b94e52016-12-08 10:21:44 -08001442 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001443 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001444 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001445
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001446 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001447 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001448
Felipe Lemed8b94e52016-12-08 10:21:44 -08001449 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001450 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001451 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001452
Makoto Onuki60780982018-04-16 15:34:00 -07001453 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1454 DUMPSYS_COMPONENTS_OPTIONS);
1455
1456 printf("========================================================\n");
1457 printf("== Running Application Providers (platform)\n");
1458 printf("========================================================\n");
1459
1460 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1461 DUMPSYS_COMPONENTS_OPTIONS);
1462
1463 printf("========================================================\n");
1464 printf("== Running Application Providers (non-platform)\n");
1465 printf("========================================================\n");
1466
1467 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1468 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001469
Adrian Roos8b397ab2017-04-04 16:35:44 -07001470 printf("========================================================\n");
1471 printf("== Dropbox crashes\n");
1472 printf("========================================================\n");
1473
1474 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1475 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1476
Felipe Lemed8b94e52016-12-08 10:21:44 -08001477 printf("========================================================\n");
1478 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1479 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1480 printf("========================================================\n");
1481 printf("== dumpstate: done (id %d)\n", ds.id_);
1482 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001483
1484 printf("========================================================\n");
1485 printf("== Obtaining statsd metadata\n");
1486 printf("========================================================\n");
1487 // This differs from the usual dumpsys stats, which is the stats report data.
1488 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001489 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001490}
1491
Nandana Dutt5c390032019-03-12 10:52:56 +00001492/*
1493 * Dumps state for the default case; drops root after it's no longer necessary.
1494 *
1495 * Returns RunStatus::OK if everything went fine.
1496 * Returns RunStatus::ERROR if there was an error.
1497 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1498 * with the caller.
1499 */
1500static Dumpstate::RunStatus DumpstateDefault() {
Primiano Tucci2d7f5c22019-01-17 15:51:14 +00001501 // Try to dump anrd trace if the daemon is running.
1502 dump_anrd_trace();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001503
1504 // Invoking the following dumpsys calls before dump_traces() to try and
1505 // keep the system stats as close to its initial state as possible.
Nandana Dutt5c390032019-03-12 10:52:56 +00001506 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001507
1508 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Dutt5c390032019-03-12 10:52:56 +00001509 // TODO(128270426): Refactor to take output argument and wrap in
1510 // RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK.
Nandana Duttfaafd522019-03-11 09:23:09 +00001511 dump_traces_path = ds.DumpTraces();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001512
1513 /* Run some operations that require root. */
1514 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1515 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1516
1517 ds.AddDir(RECOVERY_DIR, true);
1518 ds.AddDir(RECOVERY_DATA_DIR, true);
1519 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1520 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1521 if (!PropertiesHelper::IsUserBuild()) {
1522 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1523 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1524 }
1525 add_mountinfo();
1526 DumpIpTablesAsRoot();
1527
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001528 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001529 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1530
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001531 // Dump IPsec stats. No keys are exposed here.
1532 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1533
Nandana Dutt4be45d12018-09-26 15:04:23 +01001534 // Run ss as root so we can see socket marks.
1535 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1536
1537 // Run iotop as root to show top 100 IO threads
1538 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1539
Erick Reyese68df822019-02-11 14:46:36 -08001540 // Gather shared memory buffer info if the product implements it
1541 struct stat st;
1542 if (!stat("/product/bin/dmabuf_dump", &st)) {
1543 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1544 }
1545
Nandana Dutt4be45d12018-09-26 15:04:23 +01001546 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001547 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001548 }
1549
Nandana Dutt5c390032019-03-12 10:52:56 +00001550 RETURN_IF_USER_DENIED_CONSENT();
1551 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001552}
1553
mukesh agrawal253dad42018-01-23 21:59:59 -08001554// This method collects common dumpsys for telephony and wifi
1555static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001556 DumpIpTablesAsRoot();
1557
1558 if (!DropRootUser()) {
1559 return;
1560 }
1561
1562 do_dmesg();
1563 DoLogcat();
1564 DumpPacketStats();
1565 DoKmsg();
1566 DumpIpAddrAndRules();
1567 dump_route_tables();
1568
1569 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1570 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001571}
1572
1573// This method collects dumpsys for telephony debugging only
1574static void DumpstateTelephonyOnly() {
1575 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001576 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001577
1578 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001579
1580 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1581
1582 printf("========================================================\n");
1583 printf("== Android Framework Services\n");
1584 printf("========================================================\n");
1585
Vishnu Nair652cc802017-11-30 15:18:30 -08001586 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1587 SEC_TO_MSEC(10));
1588 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1589 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001590 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1591 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001592 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1593 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001594
1595 printf("========================================================\n");
1596 printf("== Running Application Services\n");
1597 printf("========================================================\n");
1598
1599 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1600
1601 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001602 printf("== Running Application Services (non-platform)\n");
1603 printf("========================================================\n");
1604
1605 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1606 DUMPSYS_COMPONENTS_OPTIONS);
1607
1608 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001609 printf("== Checkins\n");
1610 printf("========================================================\n");
1611
1612 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1613
1614 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001615 printf("== dumpstate: done (id %d)\n", ds.id_);
1616 printf("========================================================\n");
1617}
1618
mukesh agrawal253dad42018-01-23 21:59:59 -08001619// This method collects dumpsys for wifi debugging only
1620static void DumpstateWifiOnly() {
1621 DurationReporter duration_reporter("DUMPSTATE");
1622
1623 DumpstateRadioCommon();
1624
1625 printf("========================================================\n");
1626 printf("== Android Framework Services\n");
1627 printf("========================================================\n");
1628
1629 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1630 SEC_TO_MSEC(10));
1631 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1632 SEC_TO_MSEC(10));
1633
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001634 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001635
mukesh agrawal253dad42018-01-23 21:59:59 -08001636 printf("========================================================\n");
1637 printf("== dumpstate: done (id %d)\n", ds.id_);
1638 printf("========================================================\n");
1639}
1640
Nandana Duttfaafd522019-03-11 09:23:09 +00001641const char* Dumpstate::DumpTraces() {
1642 DurationReporter duration_reporter("DUMP TRACES");
1643
1644 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1645 const size_t buf_size = temp_file_pattern.length() + 1;
1646 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1647 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1648
1649 // Create a new, empty file to receive all trace dumps.
1650 //
1651 // TODO: This can be simplified once we remove support for the old style
1652 // dumps. We can have a file descriptor passed in to dump_traces instead
1653 // of creating a file, closing it and then reopening it again.
1654 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1655 if (fd < 0) {
1656 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
1657 return nullptr;
1658 }
1659
1660 // Nobody should have access to this temporary file except dumpstate, but we
1661 // temporarily grant 'read' to 'others' here because this file is created
1662 // when tombstoned is still running as root, but dumped after dropping. This
1663 // can go away once support for old style dumping has.
1664 const int chmod_ret = fchmod(fd, 0666);
1665 if (chmod_ret < 0) {
1666 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
1667 return nullptr;
1668 }
1669
1670 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1671 if (proc.get() == nullptr) {
1672 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
1673 return nullptr;
1674 }
1675
1676 // Number of times process dumping has timed out. If we encounter too many
1677 // failures, we'll give up.
1678 int timeout_failures = 0;
1679 bool dalvik_found = false;
1680
1681 const std::set<int> hal_pids = get_interesting_hal_pids();
1682
1683 struct dirent* d;
1684 while ((d = readdir(proc.get()))) {
1685 int pid = atoi(d->d_name);
1686 if (pid <= 0) {
1687 continue;
1688 }
1689
1690 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1691 std::string exe;
1692 if (!android::base::Readlink(link_name, &exe)) {
1693 continue;
1694 }
1695
1696 bool is_java_process;
1697 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1698 // Don't bother dumping backtraces for the zygote.
1699 if (IsZygote(pid)) {
1700 continue;
1701 }
1702
1703 dalvik_found = true;
1704 is_java_process = true;
1705 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1706 is_java_process = false;
1707 } else {
1708 // Probably a native process we don't care about, continue.
1709 continue;
1710 }
1711
1712 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1713 if (timeout_failures == 3) {
1714 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1715 break;
1716 }
1717
1718 const uint64_t start = Nanotime();
1719 const int ret = dump_backtrace_to_file_timeout(
1720 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1721 is_java_process ? 5 : 20, fd);
1722
1723 if (ret == -1) {
1724 // For consistency, the header and footer to this message match those
1725 // dumped by debuggerd in the success case.
1726 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1727 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1728 dprintf(fd, "---- end %d ----", pid);
1729 timeout_failures++;
1730 continue;
1731 }
1732
1733 // We've successfully dumped stack traces, reset the failure count
1734 // and write a summary of the elapsed time to the file and continue with the
1735 // next process.
1736 timeout_failures = 0;
1737
1738 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1739 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1740 }
1741
1742 if (!dalvik_found) {
1743 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1744 }
1745
1746 return file_name_buf.release();
1747}
1748
Felipe Leme6f674ae2016-11-18 17:10:33 -08001749void Dumpstate::DumpstateBoard() {
1750 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001751 printf("========================================================\n");
1752 printf("== Board\n");
1753 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001754
Felipe Leme6f674ae2016-11-18 17:10:33 -08001755 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001756 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001757 return;
1758 }
1759
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001760 std::vector<std::string> paths;
1761 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001762 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001763 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1764 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001765 remover.emplace_back(android::base::make_scope_guard(
1766 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001767 }
Jie Song9fbfad02017-06-20 16:29:42 -07001768
Wei Wang587eac92018-04-05 12:17:20 -07001769 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1770 if (dumpstate_device == nullptr) {
1771 MYLOGE("No IDumpstateDevice implementation\n");
1772 return;
1773 }
1774
1775 using ScopedNativeHandle =
1776 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1777 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1778 [](native_handle_t* handle) {
1779 native_handle_close(handle);
1780 native_handle_delete(handle);
1781 });
1782 if (handle == nullptr) {
1783 MYLOGE("Could not create native_handle\n");
1784 return;
1785 }
1786
Nandana Dutt5c390032019-03-12 10:52:56 +00001787 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001788 for (size_t i = 0; i < paths.size(); i++) {
1789 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1790
1791 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1792 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1793 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1794 if (fd < 0) {
1795 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1796 return;
1797 }
1798 handle.get()->data[i] = fd.release();
1799 }
1800
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001801 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001802 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1803 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1804 // and grab whatever dumped
1805 std::packaged_task<bool()>
1806 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001807 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1808 if (!status.isOk()) {
1809 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001810 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001811 }
Wei Wang587eac92018-04-05 12:17:20 -07001812 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001813 });
Wei Wang587eac92018-04-05 12:17:20 -07001814
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001815 auto result = dumpstate_task.get_future();
1816 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001817
1818 constexpr size_t timeout_sec = 30;
1819 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1820 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1821 if (!android::base::SetProperty("ctl.interface_restart",
1822 android::base::StringPrintf("%s/default",
1823 IDumpstateDevice::descriptor))) {
1824 MYLOGE("Couldn't restart dumpstate HAL\n");
1825 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001826 }
Wei Wang587eac92018-04-05 12:17:20 -07001827 // Wait some time for init to kill dumpstate vendor HAL
1828 constexpr size_t killing_timeout_sec = 10;
1829 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1830 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1831 "there might be racing in content\n", killing_timeout_sec);
1832 }
1833
1834 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1835 for (size_t i = 0; i < paths.size(); i++) {
1836 struct stat s;
1837 if (fstat(handle.get()->data[i], &s) == -1) {
1838 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1839 strerror(errno));
1840 file_sizes[i] = -1;
1841 continue;
1842 }
1843 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001844 }
1845
1846 for (size_t i = 0; i < paths.size(); i++) {
1847 if (file_sizes[i] == -1) {
1848 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001849 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001850 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001851 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001852 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001853 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001854 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001855 }
1856
Felipe Lemed8b94e52016-12-08 10:21:44 -08001857 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001858}
1859
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001860static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001861 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001862 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001863 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1864 " -h: display this help message\n"
1865 " -b: play sound file instead of vibrate, at beginning of job\n"
1866 " -e: play sound file instead of vibrate, at end of job\n"
1867 " -o: write to file (instead of stdout)\n"
1868 " -d: append date to filename (requires -o)\n"
1869 " -p: capture screenshot to filename.png (requires -o)\n"
1870 " -z: generate zipped file (requires -o)\n"
1871 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001872 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001873 " -q: disable vibrate\n"
1874 " -B: send broadcast when finished (requires -o)\n"
1875 " -P: send broadcast when started and update system properties on "
1876 "progress (requires -o and -B)\n"
1877 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1878 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001879 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001880 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001881}
1882
Wei Liuf87959e2016-08-26 14:51:42 -07001883static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001884 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001885}
1886
Felipe Leme1d486fe2016-10-14 18:06:47 -07001887bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001888 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001889 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001890 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001891 // Final timestamp
1892 char date[80];
1893 time_t the_real_now_please_stand_up = time(nullptr);
1894 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001895 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001896 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001897
Felipe Leme9a523ae2016-10-20 15:10:33 -07001898 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001899 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001900 return false;
1901 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001902 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001903 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001904 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001905 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001906
Felipe Leme0f3fb202016-06-10 17:10:53 -07001907 // Add log file (which contains stderr output) to zip...
1908 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001909 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001910 MYLOGE("Failed to add dumpstate log to .zip file\n");
1911 return false;
1912 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001913 // TODO: Should truncate the existing file.
1914 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001915 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1916 return false;
1917 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001918 fprintf(stderr, "\n");
1919
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001920 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001921 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001922 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001923 return false;
1924 }
1925
Felipe Leme1d486fe2016-10-14 18:06:47 -07001926 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1927 ds.zip_file.reset(nullptr);
1928
Felipe Lemee9d2c542016-11-15 11:48:26 -08001929 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001930 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001931
Felipe Leme1e9edc62015-12-21 16:02:13 -08001932 return true;
1933}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001934
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001935static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001936 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1937 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001938 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001939 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001940 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001941 }
1942
1943 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001944 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001945
1946 std::vector<uint8_t> buffer(65536);
1947 while (1) {
1948 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1949 if (bytes_read == 0) {
1950 break;
1951 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001952 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001953 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001954 }
1955
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001956 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001957 }
1958
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001959 uint8_t hash[SHA256_DIGEST_LENGTH];
1960 SHA256_Final(hash, &ctx);
1961
1962 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1963 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001964 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001965 }
1966 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1967 return std::string(hash_buffer);
1968}
1969
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001970static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1971 // clang-format off
1972 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1973 "--receiver-foreground", "--receiver-include-background", "-a", action};
1974 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001975
1976 am.insert(am.end(), args.begin(), args.end());
1977
Felipe Leme8d2410e2017-02-08 09:46:08 -08001978 RunCommand("", am,
1979 CommandOptions::WithTimeout(20)
1980 .Log("Sending broadcast: '%s'\n")
1981 .Always()
1982 .DropRoot()
1983 .RedirectStderr()
1984 .Build());
1985}
1986
Felipe Leme35b8cf12017-02-10 15:47:29 -08001987static void Vibrate(int duration_ms) {
1988 // clang-format off
1989 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1990 CommandOptions::WithTimeout(10)
1991 .Log("Vibrate: '%s'\n")
1992 .Always()
1993 .Build());
1994 // clang-format on
1995}
1996
Nandana Dutt979388e2018-11-30 16:48:55 +00001997static void MaybeResolveSymlink(std::string* path) {
1998 std::string resolved_path;
1999 if (android::base::Readlink(*path, &resolved_path)) {
2000 *path = resolved_path;
2001 }
2002}
2003
Nandana Dutt4be45d12018-09-26 15:04:23 +01002004/*
2005 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2006 * if we are writing zip files and adds the version file.
2007 */
2008static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002009 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2010
Nandana Dutt4be45d12018-09-26 15:04:23 +01002011 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2012 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002013 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002014 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002015 char date[80];
2016 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2017 ds.name_ = date;
2018 } else {
2019 ds.name_ = "undated";
2020 }
2021
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002022 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002023 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002024 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002025 ds.base_name_ += "-wifi";
2026 }
2027
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002028 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002029 ds.screenshot_path_ = ds.GetPath(".png");
2030 }
2031 ds.tmp_path_ = ds.GetPath(".tmp");
2032 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2033
Nandana Dutt54dbd672019-01-11 12:58:05 +00002034 std::string destination = ds.options_->bugreport_fd.get() != -1
2035 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002036 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002037 MYLOGD(
2038 "Bugreport dir: %s\n"
2039 "Base name: %s\n"
2040 "Suffix: %s\n"
2041 "Log path: %s\n"
2042 "Temporary path: %s\n"
2043 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002044 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2045 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002046
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002047 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002048 ds.path_ = ds.GetPath(".zip");
2049 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2050 create_parent_dirs(ds.path_.c_str());
2051 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2052 if (ds.zip_file == nullptr) {
2053 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2054 } else {
2055 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2056 }
2057 ds.AddTextZipEntry("version.txt", ds.version_);
2058 }
2059}
2060
2061/*
2062 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2063 * printing zipped file status, etc.
2064 */
2065static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002066 /* check if user changed the suffix using system properties */
2067 std::string name =
2068 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2069 bool change_suffix = false;
2070 if (!name.empty()) {
2071 /* must whitelist which characters are allowed, otherwise it could cross directories */
2072 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2073 if (std::regex_match(name.c_str(), valid_regex)) {
2074 change_suffix = true;
2075 } else {
2076 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2077 }
2078 }
2079 if (change_suffix) {
2080 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2081 ds.name_ = name;
2082 if (!ds.screenshot_path_.empty()) {
2083 std::string new_screenshot_path = ds.GetPath(".png");
2084 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2085 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2086 new_screenshot_path.c_str(), strerror(errno));
2087 } else {
2088 ds.screenshot_path_ = new_screenshot_path;
2089 }
2090 }
2091 }
2092
2093 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002094 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002095 if (!ds.FinishZipFile()) {
2096 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2097 do_text_file = true;
2098 } else {
2099 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002100 // If the user has changed the suffix, we need to change the zip file name.
2101 std::string new_path = ds.GetPath(".zip");
2102 if (ds.path_ != new_path) {
2103 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2104 if (rename(ds.path_.c_str(), new_path.c_str())) {
2105 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2106 strerror(errno));
2107 } else {
2108 ds.path_ = new_path;
2109 }
2110 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002111 }
2112 }
2113 if (do_text_file) {
2114 ds.path_ = ds.GetPath(".txt");
2115 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2116 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2117 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2118 ds.path_.clear();
2119 }
2120 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002121 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002122 if (do_text_file) {
2123 dprintf(ds.control_socket_fd_,
2124 "FAIL:could not create zip file, check %s "
2125 "for more details\n",
2126 ds.log_path_.c_str());
2127 } else {
2128 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2129 }
2130 }
2131}
2132
2133/* Broadcasts that we are done with the bugreport */
2134static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002135 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002136 if (!ds.path_.empty()) {
2137 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002138 // clang-format off
2139
2140 std::vector<std::string> am_args = {
2141 "--receiver-permission", "android.permission.DUMP",
2142 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2143 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2144 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002145 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002146 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2147 };
2148 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002149 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002150 am_args.push_back("--es");
2151 am_args.push_back("android.intent.extra.SCREENSHOT");
2152 am_args.push_back(ds.screenshot_path_);
2153 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002154 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002155 am_args.push_back("--es");
2156 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002157 am_args.push_back(ds.options_->notification_title);
2158 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002159 am_args.push_back("--es");
2160 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002161 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002162 }
2163 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002164 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002165 am_args.push_back("--es");
2166 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002167 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002168 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2169 } else {
2170 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2171 }
2172 } else {
2173 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2174 }
2175}
2176
Nandana Dutt58d72e22018-11-16 10:30:48 +00002177static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2178 switch (mode) {
2179 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2180 return "BUGREPORT_FULL";
2181 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2182 return "BUGREPORT_INTERACTIVE";
2183 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2184 return "BUGREPORT_REMOTE";
2185 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2186 return "BUGREPORT_WEAR";
2187 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2188 return "BUGREPORT_TELEPHONY";
2189 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2190 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002191 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2192 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002193 }
2194}
2195
2196static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002197 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002198 switch (mode) {
2199 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2200 options->do_broadcast = true;
2201 options->do_fb = true;
2202 break;
2203 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002204 // Currently, the dumpstate binder is only used by Shell to update progress.
2205 options->do_start_service = true;
2206 options->do_progress_updates = true;
2207 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002208 options->do_broadcast = true;
2209 break;
2210 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002211 options->do_vibrate = false;
2212 options->is_remote_mode = true;
2213 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002214 options->do_broadcast = true;
2215 break;
2216 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002217 options->do_start_service = true;
2218 options->do_progress_updates = true;
2219 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002220 options->do_fb = true;
2221 options->do_broadcast = true;
2222 break;
2223 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002224 options->telephony_only = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002225 options->do_fb = true;
2226 options->do_broadcast = true;
2227 break;
2228 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002229 options->wifi_only = true;
2230 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002231 options->do_fb = true;
2232 options->do_broadcast = true;
2233 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002234 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2235 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002236 }
2237}
2238
2239static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002240 // If the system property is not set, it's assumed to be a default bugreport.
2241 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002242
2243 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2244 if (!extra_options.empty()) {
2245 // Framework uses a system property to override some command-line args.
2246 // Currently, it contains the type of the requested bugreport.
2247 if (extra_options == "bugreportplus") {
2248 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002249 } else if (extra_options == "bugreportfull") {
2250 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002251 } else if (extra_options == "bugreportremote") {
2252 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2253 } else if (extra_options == "bugreportwear") {
2254 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2255 } else if (extra_options == "bugreporttelephony") {
2256 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2257 } else if (extra_options == "bugreportwifi") {
2258 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002259 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002260 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002261 }
2262 // Reset the property
2263 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2264 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002265 return mode;
2266}
2267
2268// TODO: Move away from system properties when we have options passed via binder calls.
2269/* Sets runtime options from the system properties and then clears those properties. */
2270static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2271 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2272 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002273
2274 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2275 if (!options->notification_title.empty()) {
2276 // Reset the property
2277 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2278
Nandana Duttdd8cca32018-11-14 10:10:29 +00002279 options->notification_description =
2280 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002281 if (!options->notification_description.empty()) {
2282 // Reset the property
2283 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2284 }
2285 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2286 options->notification_description.c_str());
2287 }
2288}
2289
Nandana Dutt58d72e22018-11-16 10:30:48 +00002290static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2291 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2292 MYLOGI("do_add_date: %d\n", options.do_add_date);
2293 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2294 MYLOGI("use_socket: %d\n", options.use_socket);
2295 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2296 MYLOGI("do_fb: %d\n", options.do_fb);
2297 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2298 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2299 MYLOGI("show_header_only: %d\n", options.show_header_only);
2300 MYLOGI("do_start_service: %d\n", options.do_start_service);
2301 MYLOGI("telephony_only: %d\n", options.telephony_only);
2302 MYLOGI("wifi_only: %d\n", options.wifi_only);
2303 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002304 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002305 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2306 MYLOGI("args: %s\n", options.args.c_str());
2307 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2308 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2309}
2310
Nandana Dutt54dbd672019-01-11 12:58:05 +00002311void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2312 const android::base::unique_fd& bugreport_fd_in,
2313 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002314 // In the new API world, date is always added; output is always a zip file.
2315 // TODO(111441001): remove these options once they are obsolete.
2316 do_add_date = true;
2317 do_zip_file = true;
2318
Nandana Dutt54dbd672019-01-11 12:58:05 +00002319 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2320 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2321 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002322
2323 extra_options = ModeToString(bugreport_mode);
2324 SetOptionsFromMode(bugreport_mode, this);
2325}
2326
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002327Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2328 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002329 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002330 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002331 switch (c) {
2332 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002333 case 'd': do_add_date = true; break;
2334 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002335 // o=use_outfile not supported anymore.
2336 // TODO(b/111441001): Remove when all callers have migrated.
2337 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002338 case 's': use_socket = true; break;
2339 case 'S': use_control_socket = true; break;
2340 case 'v': show_header_only = true; break;
2341 case 'q': do_vibrate = false; break;
2342 case 'p': do_fb = true; break;
2343 case 'P': do_progress_updates = true; break;
2344 case 'R': is_remote_mode = true; break;
2345 case 'B': do_broadcast = true; break;
2346 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002347 case 'w':
2348 // This was already processed
2349 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002350 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002351 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002352 break;
2353 default:
2354 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002355 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002356 break;
2357 // clang-format on
2358 }
2359 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002360
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002361 // TODO: use helper function to convert argv into a string
2362 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002363 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002364 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002365 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002366 }
2367 }
2368
2369 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2370 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002371
2372 SetOptionsFromProperties(this);
2373 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002374}
2375
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002376bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002377 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002378 return false;
2379 }
2380
Nandana Dutt9a76d202019-01-21 15:56:48 +00002381 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002382 return false;
2383 }
2384
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002385 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002386 return false;
2387 }
2388
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002389 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002390 return false;
2391 }
2392
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002393 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002394 return false;
2395 }
2396 return true;
2397}
2398
Nandana Dutt197661d2018-11-16 16:40:21 +00002399void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2400 options_ = std::move(options);
2401}
2402
Nandana Duttd2f5f082019-01-18 17:13:52 +00002403Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2404 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002405 if (listener_ != nullptr) {
2406 switch (status) {
2407 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002408 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002409 break;
2410 case Dumpstate::RunStatus::HELP:
2411 break;
2412 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002413 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002414 break;
2415 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002416 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2417 break;
2418 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2419 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2420 break;
2421 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2422 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002423 break;
2424 }
2425 }
2426 return status;
2427}
2428
Nandana Dutt979388e2018-11-30 16:48:55 +00002429/*
2430 * Dumps relevant information to a bugreport based on the given options.
2431 *
2432 * The bugreport can be dumped to a file or streamed to a socket.
2433 *
2434 * How dumping to file works:
2435 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2436 * stderr is redirected a log file.
2437 *
2438 * The temporary bugreport is then populated via printfs, dumping contents of files and
2439 * output of commands to stdout.
2440 *
2441 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2442 * text file.
2443 *
2444 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2445 * gets added to the archive.
2446 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002447 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2448 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002449 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002450Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2451 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002452 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002453 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002454 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002455 return RunStatus::INVALID_INPUT;
2456 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002457 /* set as high priority, and protect from OOM killer */
2458 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002459
Felipe Lemed071c682016-10-20 16:48:00 -07002460 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002461 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002462 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002463 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002464 } else {
2465 /* fallback to kernels <= 2.6.35 */
2466 oom_adj = fopen("/proc/self/oom_adj", "we");
2467 if (oom_adj) {
2468 fputs("-17", oom_adj);
2469 fclose(oom_adj);
2470 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002471 }
2472
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002473 if (version_ == VERSION_DEFAULT) {
2474 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002475 }
2476
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002477 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002478 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002479 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002480 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002481 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002482 }
2483
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002484 if (options_->show_header_only) {
2485 PrintHeader();
2486 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002487 }
2488
Nandana Duttd2f5f082019-01-18 17:13:52 +00002489 if (options_->bugreport_fd.get() != -1) {
2490 // If the output needs to be copied over to the caller's fd, get user consent.
2491 android::String16 package(calling_package.c_str());
2492 CheckUserConsent(calling_uid, package);
2493 }
2494
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002495 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002496 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002497
2498 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002499 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002500 is_redirecting
2501 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2502 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002503 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002504
Felipe Lemed071c682016-10-20 16:48:00 -07002505 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002506 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002507 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002508 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2509
2510 MYLOGI("begin\n");
2511
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002512 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002513
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002514 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002515 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002516 MYLOGI("Starting 'dumpstate' service\n");
2517 android::status_t ret;
2518 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2519 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2520 }
2521 }
2522
Felipe Lemef0292972016-11-22 13:57:05 -08002523 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002524 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2525 }
2526
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002527 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2528 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002529
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002530 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002531
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002532 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002533
Christopher Ferrised9354f2014-10-01 17:35:01 -07002534 // If we are going to use a socket, do it as early as possible
2535 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002536 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002537 if (!redirect_to_socket(stdout, "dumpstate")) {
2538 return ERROR;
2539 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002540 }
2541
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002542 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002543 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002544 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002545 if (control_socket_fd_ == -1) {
2546 return ERROR;
2547 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002548 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002549 }
2550
Felipe Leme71bbfc52015-11-23 14:14:51 -08002551 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002552 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002553
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002554 if (options_->do_progress_updates) {
2555 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002556 // clang-format off
2557 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002558 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002559 "--es", "android.intent.extra.NAME", name_,
2560 "--ei", "android.intent.extra.ID", std::to_string(id_),
2561 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2562 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002563 };
2564 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002565 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002566 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002567 if (options_->use_control_socket) {
2568 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002569 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002570 }
2571 }
2572
Nick Kralevichf3599b32016-01-25 15:05:16 -08002573 /* read /proc/cmdline before dropping root */
2574 FILE *cmdline = fopen("/proc/cmdline", "re");
2575 if (cmdline) {
2576 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2577 fclose(cmdline);
2578 }
2579
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002580 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002581 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002582 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002583
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002584 if (options_->do_fb && do_early_screenshot_) {
2585 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002586 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002587 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002588 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002589 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002590 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002591 }
2592 }
2593
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002594 if (options_->do_zip_file && zip_file != nullptr) {
2595 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2596 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002597 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002598 }
2599 }
2600
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002601 int dup_stdout_fd;
2602 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002603 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002604 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002605 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002606 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2607 return ERROR;
2608 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002609 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2610 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2611 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002612 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002613
2614 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2615 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002616 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002617 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002618 /* TODO: rather than generating a text file now and zipping it later,
2619 it would be more efficient to redirect stdout to the zip entry
2620 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002621 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2622 return ERROR;
2623 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002624 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002625 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002626 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002627 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002628 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002629
2630 // Don't buffer stdout
2631 setvbuf(stdout, nullptr, _IONBF, 0);
2632
Felipe Leme608385d2016-02-01 10:35:38 -08002633 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2634 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002635 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002636 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002637
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002638 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002639 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002640 DumpstateBoard();
2641 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002642 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002643 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002644 // Dump state for the default case. This also drops root.
Nandana Dutt5c390032019-03-12 10:52:56 +00002645 RunStatus s = DumpstateDefault();
2646 if (s != RunStatus::OK) {
2647 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2648 HandleUserConsentDenied();
2649 }
2650 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002651 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002652 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002653
Felipe Leme55b42a62015-11-10 17:39:08 -08002654 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002655 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002656 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002657 }
2658
Nandana Duttd2f5f082019-01-18 17:13:52 +00002659 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002660 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002661 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002662 }
2663
Nandana Duttd2f5f082019-01-18 17:13:52 +00002664 // Share the final file with the caller if the user has consented.
2665 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2666 if (options_->bugreport_fd.get() != -1) {
2667 status = CopyBugreportIfUserConsented();
2668 if (status != Dumpstate::RunStatus::OK &&
2669 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2670 // Do an early return if there were errors. We make an exception for consent
2671 // timing out because it's possible the user got distracted. In this case the
2672 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002673 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002674 return status;
2675 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002676 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002677 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2678 options_->screenshot_fd.get());
2679 if (copy_succeeded) {
2680 android::os::UnlinkAndLogOnError(screenshot_path_);
2681 }
2682 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002683 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2684 MYLOGI(
2685 "Did not receive user consent yet."
2686 " Will not copy the bugreport artifacts to caller.\n");
Nandana Dutt5c390032019-03-12 10:52:56 +00002687 // TODO(b/111441001): cancel outstanding requests
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002688 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002689 }
2690
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002691 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002692 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002693 for (int i = 0; i < 3; i++) {
2694 Vibrate(75);
2695 usleep((75 + 50) * 1000);
2696 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002697 }
2698
Jeff Brown1dc94e32014-09-11 14:15:27 -07002699 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002700 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002701 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002702 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002703 }
2704
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002705 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2706 progress_->GetInitialMax());
2707 progress_->Save();
2708 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002709
Felipe Leme107a05f2016-03-08 15:11:15 -08002710 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002711 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002712 }
2713
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002714 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002715 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002716 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002717 }
2718
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002719 tombstone_data_.clear();
2720 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002721
Nandana Duttd2f5f082019-01-18 17:13:52 +00002722 return (consent_callback_ != nullptr &&
2723 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2724 ? USER_CONSENT_TIMED_OUT
2725 : RunStatus::OK;
2726}
2727
2728void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2729 consent_callback_ = new ConsentCallback();
2730 const String16 incidentcompanion("incidentcompanion");
2731 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2732 if (ics != nullptr) {
2733 MYLOGD("Checking user consent via incidentcompanion service\n");
2734 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2735 calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
2736 consent_callback_.get());
2737 } else {
2738 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2739 }
2740}
2741
Nandana Dutt5c390032019-03-12 10:52:56 +00002742bool Dumpstate::IsUserConsentDenied() const {
2743 return ds.consent_callback_ != nullptr &&
2744 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2745}
2746
Nandana Duttd2f5f082019-01-18 17:13:52 +00002747void Dumpstate::CleanupFiles() {
2748 android::os::UnlinkAndLogOnError(tmp_path_);
2749 android::os::UnlinkAndLogOnError(screenshot_path_);
2750 android::os::UnlinkAndLogOnError(path_);
2751}
2752
2753Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2754 MYLOGD("User denied consent; deleting files and returning\n");
2755 CleanupFiles();
2756 return USER_CONSENT_DENIED;
2757}
2758
2759Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2760 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2761 // user consent.
2762 UserConsentResult consent_result = consent_callback_->getResult();
2763 if (consent_result == UserConsentResult::UNAVAILABLE) {
2764 // User has not responded yet.
2765 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2766 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2767 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2768 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2769 sleep(delay_seconds);
2770 }
2771 consent_result = consent_callback_->getResult();
2772 }
2773 if (consent_result == UserConsentResult::DENIED) {
2774 // User has explicitly denied sharing with the app. To be safe delete the
2775 // internal bugreport & tmp files.
2776 return HandleUserConsentDenied();
2777 }
2778 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002779 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2780 if (copy_succeeded) {
2781 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002782 }
2783 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2784 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2785 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2786 // Since we do not have user consent to share the bugreport it does not get
2787 // copied over to the calling app but remains in the internal directory from
2788 // where the user can manually pull it.
2789 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2790 }
2791 // Unknown result; must be a programming error.
2792 MYLOGE("Unknown user consent result:%d\n", consent_result);
2793 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002794}
2795
Nandana Duttf02564e2019-02-15 15:24:24 +00002796Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002797 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2798 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2799 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002800 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002801 // When directly running dumpstate binary, the output is not expected to be written
2802 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002803 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002804
2805 // calling_uid and calling_package are for user consent to share the bugreport with
2806 // an app; they are irrelvant here because bugreport is only written to a local
2807 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002808 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002809 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002810 return status;
2811}
2812
2813/* Main entry point for dumpstate binary. */
2814int run_main(int argc, char* argv[]) {
2815 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002816
2817 switch (status) {
2818 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002819 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002820 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002821 ShowUsage();
2822 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002823 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002824 fprintf(stderr, "Invalid combination of args\n");
2825 ShowUsage();
2826 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002827 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002828 FALLTHROUGH_INTENDED;
2829 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2830 FALLTHROUGH_INTENDED;
2831 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002832 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002833 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002834}