blob: 12de2d2c3ccb11d970b7a8c2dbd97b7f706ec5e2 [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
Nandana Duttcf419a72019-03-14 10:40:17 +00001504 // Invoking the following dumpsys calls before DumpTraces() to try and
Nandana Dutt4be45d12018-09-26 15:04:23 +01001505 // 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 Duttcf419a72019-03-14 10:40:17 +00001509 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001510
1511 /* Run some operations that require root. */
1512 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1513 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1514
1515 ds.AddDir(RECOVERY_DIR, true);
1516 ds.AddDir(RECOVERY_DATA_DIR, true);
1517 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1518 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1519 if (!PropertiesHelper::IsUserBuild()) {
1520 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1521 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1522 }
1523 add_mountinfo();
1524 DumpIpTablesAsRoot();
1525
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001526 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001527 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1528
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001529 // Dump IPsec stats. No keys are exposed here.
1530 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1531
Nandana Dutt4be45d12018-09-26 15:04:23 +01001532 // Run ss as root so we can see socket marks.
1533 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1534
1535 // Run iotop as root to show top 100 IO threads
1536 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1537
Erick Reyese68df822019-02-11 14:46:36 -08001538 // Gather shared memory buffer info if the product implements it
1539 struct stat st;
1540 if (!stat("/product/bin/dmabuf_dump", &st)) {
1541 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1542 }
1543
Nandana Dutt4be45d12018-09-26 15:04:23 +01001544 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001545 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001546 }
1547
Nandana Dutt5c390032019-03-12 10:52:56 +00001548 RETURN_IF_USER_DENIED_CONSENT();
1549 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001550}
1551
mukesh agrawal253dad42018-01-23 21:59:59 -08001552// This method collects common dumpsys for telephony and wifi
1553static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001554 DumpIpTablesAsRoot();
1555
1556 if (!DropRootUser()) {
1557 return;
1558 }
1559
1560 do_dmesg();
1561 DoLogcat();
1562 DumpPacketStats();
1563 DoKmsg();
1564 DumpIpAddrAndRules();
1565 dump_route_tables();
1566
1567 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1568 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001569}
1570
1571// This method collects dumpsys for telephony debugging only
1572static void DumpstateTelephonyOnly() {
1573 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001574 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001575
1576 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001577
1578 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1579
1580 printf("========================================================\n");
1581 printf("== Android Framework Services\n");
1582 printf("========================================================\n");
1583
Vishnu Nair652cc802017-11-30 15:18:30 -08001584 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1585 SEC_TO_MSEC(10));
Chiachang Wang85e0db32019-03-25 08:59:55 +08001586 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1587 SEC_TO_MSEC(10));
1588 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Vishnu Nair652cc802017-11-30 15:18:30 -08001589 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1590 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001591 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1592 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001593 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1594 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001595
1596 printf("========================================================\n");
1597 printf("== Running Application Services\n");
1598 printf("========================================================\n");
1599
1600 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1601
1602 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001603 printf("== Running Application Services (non-platform)\n");
1604 printf("========================================================\n");
1605
1606 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1607 DUMPSYS_COMPONENTS_OPTIONS);
1608
1609 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001610 printf("== Checkins\n");
1611 printf("========================================================\n");
1612
1613 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1614
1615 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001616 printf("== dumpstate: done (id %d)\n", ds.id_);
1617 printf("========================================================\n");
1618}
1619
mukesh agrawal253dad42018-01-23 21:59:59 -08001620// This method collects dumpsys for wifi debugging only
1621static void DumpstateWifiOnly() {
1622 DurationReporter duration_reporter("DUMPSTATE");
1623
1624 DumpstateRadioCommon();
1625
1626 printf("========================================================\n");
1627 printf("== Android Framework Services\n");
1628 printf("========================================================\n");
1629
1630 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1631 SEC_TO_MSEC(10));
1632 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1633 SEC_TO_MSEC(10));
1634
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001635 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001636
mukesh agrawal253dad42018-01-23 21:59:59 -08001637 printf("========================================================\n");
1638 printf("== dumpstate: done (id %d)\n", ds.id_);
1639 printf("========================================================\n");
1640}
1641
Nandana Duttcf419a72019-03-14 10:40:17 +00001642Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001643 DurationReporter duration_reporter("DUMP TRACES");
1644
1645 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1646 const size_t buf_size = temp_file_pattern.length() + 1;
1647 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1648 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1649
1650 // Create a new, empty file to receive all trace dumps.
1651 //
1652 // TODO: This can be simplified once we remove support for the old style
1653 // dumps. We can have a file descriptor passed in to dump_traces instead
1654 // of creating a file, closing it and then reopening it again.
1655 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1656 if (fd < 0) {
1657 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001658 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001659 }
1660
1661 // Nobody should have access to this temporary file except dumpstate, but we
1662 // temporarily grant 'read' to 'others' here because this file is created
1663 // when tombstoned is still running as root, but dumped after dropping. This
1664 // can go away once support for old style dumping has.
1665 const int chmod_ret = fchmod(fd, 0666);
1666 if (chmod_ret < 0) {
1667 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001668 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001669 }
1670
1671 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1672 if (proc.get() == nullptr) {
1673 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001674 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001675 }
1676
1677 // Number of times process dumping has timed out. If we encounter too many
1678 // failures, we'll give up.
1679 int timeout_failures = 0;
1680 bool dalvik_found = false;
1681
1682 const std::set<int> hal_pids = get_interesting_hal_pids();
1683
1684 struct dirent* d;
1685 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001686 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001687 int pid = atoi(d->d_name);
1688 if (pid <= 0) {
1689 continue;
1690 }
1691
1692 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1693 std::string exe;
1694 if (!android::base::Readlink(link_name, &exe)) {
1695 continue;
1696 }
1697
1698 bool is_java_process;
1699 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1700 // Don't bother dumping backtraces for the zygote.
1701 if (IsZygote(pid)) {
1702 continue;
1703 }
1704
1705 dalvik_found = true;
1706 is_java_process = true;
1707 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1708 is_java_process = false;
1709 } else {
1710 // Probably a native process we don't care about, continue.
1711 continue;
1712 }
1713
1714 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1715 if (timeout_failures == 3) {
1716 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1717 break;
1718 }
1719
1720 const uint64_t start = Nanotime();
1721 const int ret = dump_backtrace_to_file_timeout(
1722 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1723 is_java_process ? 5 : 20, fd);
1724
1725 if (ret == -1) {
1726 // For consistency, the header and footer to this message match those
1727 // dumped by debuggerd in the success case.
1728 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1729 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1730 dprintf(fd, "---- end %d ----", pid);
1731 timeout_failures++;
1732 continue;
1733 }
1734
1735 // We've successfully dumped stack traces, reset the failure count
1736 // and write a summary of the elapsed time to the file and continue with the
1737 // next process.
1738 timeout_failures = 0;
1739
1740 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1741 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1742 }
1743
1744 if (!dalvik_found) {
1745 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1746 }
1747
Nandana Duttcf419a72019-03-14 10:40:17 +00001748 *path = file_name_buf.release();
1749 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001750}
1751
Felipe Leme6f674ae2016-11-18 17:10:33 -08001752void Dumpstate::DumpstateBoard() {
1753 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001754 printf("========================================================\n");
1755 printf("== Board\n");
1756 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001757
Felipe Leme6f674ae2016-11-18 17:10:33 -08001758 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001759 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001760 return;
1761 }
1762
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001763 std::vector<std::string> paths;
1764 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001765 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001766 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1767 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001768 remover.emplace_back(android::base::make_scope_guard(
1769 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001770 }
Jie Song9fbfad02017-06-20 16:29:42 -07001771
Wei Wang587eac92018-04-05 12:17:20 -07001772 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1773 if (dumpstate_device == nullptr) {
1774 MYLOGE("No IDumpstateDevice implementation\n");
1775 return;
1776 }
1777
1778 using ScopedNativeHandle =
1779 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1780 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1781 [](native_handle_t* handle) {
1782 native_handle_close(handle);
1783 native_handle_delete(handle);
1784 });
1785 if (handle == nullptr) {
1786 MYLOGE("Could not create native_handle\n");
1787 return;
1788 }
1789
Nandana Dutt5c390032019-03-12 10:52:56 +00001790 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001791 for (size_t i = 0; i < paths.size(); i++) {
1792 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1793
1794 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1795 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1796 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1797 if (fd < 0) {
1798 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1799 return;
1800 }
1801 handle.get()->data[i] = fd.release();
1802 }
1803
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001804 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001805 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1806 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1807 // and grab whatever dumped
1808 std::packaged_task<bool()>
1809 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001810 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1811 if (!status.isOk()) {
1812 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001813 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001814 }
Wei Wang587eac92018-04-05 12:17:20 -07001815 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001816 });
Wei Wang587eac92018-04-05 12:17:20 -07001817
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001818 auto result = dumpstate_task.get_future();
1819 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001820
1821 constexpr size_t timeout_sec = 30;
1822 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1823 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1824 if (!android::base::SetProperty("ctl.interface_restart",
1825 android::base::StringPrintf("%s/default",
1826 IDumpstateDevice::descriptor))) {
1827 MYLOGE("Couldn't restart dumpstate HAL\n");
1828 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001829 }
Wei Wang587eac92018-04-05 12:17:20 -07001830 // Wait some time for init to kill dumpstate vendor HAL
1831 constexpr size_t killing_timeout_sec = 10;
1832 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1833 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1834 "there might be racing in content\n", killing_timeout_sec);
1835 }
1836
1837 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1838 for (size_t i = 0; i < paths.size(); i++) {
1839 struct stat s;
1840 if (fstat(handle.get()->data[i], &s) == -1) {
1841 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1842 strerror(errno));
1843 file_sizes[i] = -1;
1844 continue;
1845 }
1846 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001847 }
1848
1849 for (size_t i = 0; i < paths.size(); i++) {
1850 if (file_sizes[i] == -1) {
1851 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001852 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001853 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001854 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001855 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001856 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001857 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001858 }
1859
Felipe Lemed8b94e52016-12-08 10:21:44 -08001860 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001861}
1862
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001863static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001864 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001865 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001866 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1867 " -h: display this help message\n"
1868 " -b: play sound file instead of vibrate, at beginning of job\n"
1869 " -e: play sound file instead of vibrate, at end of job\n"
1870 " -o: write to file (instead of stdout)\n"
1871 " -d: append date to filename (requires -o)\n"
1872 " -p: capture screenshot to filename.png (requires -o)\n"
1873 " -z: generate zipped file (requires -o)\n"
1874 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001875 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001876 " -q: disable vibrate\n"
1877 " -B: send broadcast when finished (requires -o)\n"
1878 " -P: send broadcast when started and update system properties on "
1879 "progress (requires -o and -B)\n"
1880 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1881 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001882 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001883 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001884}
1885
Wei Liuf87959e2016-08-26 14:51:42 -07001886static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001887 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001888}
1889
Felipe Leme1d486fe2016-10-14 18:06:47 -07001890bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001891 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001892 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001893 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001894 // Final timestamp
1895 char date[80];
1896 time_t the_real_now_please_stand_up = time(nullptr);
1897 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001898 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001899 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001900
Felipe Leme9a523ae2016-10-20 15:10:33 -07001901 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001902 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001903 return false;
1904 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001905 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001906 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001907 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001908 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001909
Felipe Leme0f3fb202016-06-10 17:10:53 -07001910 // Add log file (which contains stderr output) to zip...
1911 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001912 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001913 MYLOGE("Failed to add dumpstate log to .zip file\n");
1914 return false;
1915 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001916 // TODO: Should truncate the existing file.
1917 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001918 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1919 return false;
1920 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001921 fprintf(stderr, "\n");
1922
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001923 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001924 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001925 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001926 return false;
1927 }
1928
Felipe Leme1d486fe2016-10-14 18:06:47 -07001929 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1930 ds.zip_file.reset(nullptr);
1931
Felipe Lemee9d2c542016-11-15 11:48:26 -08001932 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001933 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001934
Felipe Leme1e9edc62015-12-21 16:02:13 -08001935 return true;
1936}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001937
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001938static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001939 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1940 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001941 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001942 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001943 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001944 }
1945
1946 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001947 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001948
1949 std::vector<uint8_t> buffer(65536);
1950 while (1) {
1951 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1952 if (bytes_read == 0) {
1953 break;
1954 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001955 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001956 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001957 }
1958
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001959 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001960 }
1961
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001962 uint8_t hash[SHA256_DIGEST_LENGTH];
1963 SHA256_Final(hash, &ctx);
1964
1965 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1966 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001967 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001968 }
1969 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1970 return std::string(hash_buffer);
1971}
1972
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001973static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1974 // clang-format off
1975 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1976 "--receiver-foreground", "--receiver-include-background", "-a", action};
1977 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001978
1979 am.insert(am.end(), args.begin(), args.end());
1980
Felipe Leme8d2410e2017-02-08 09:46:08 -08001981 RunCommand("", am,
1982 CommandOptions::WithTimeout(20)
1983 .Log("Sending broadcast: '%s'\n")
1984 .Always()
1985 .DropRoot()
1986 .RedirectStderr()
1987 .Build());
1988}
1989
Felipe Leme35b8cf12017-02-10 15:47:29 -08001990static void Vibrate(int duration_ms) {
1991 // clang-format off
1992 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1993 CommandOptions::WithTimeout(10)
1994 .Log("Vibrate: '%s'\n")
1995 .Always()
1996 .Build());
1997 // clang-format on
1998}
1999
Nandana Dutt979388e2018-11-30 16:48:55 +00002000static void MaybeResolveSymlink(std::string* path) {
2001 std::string resolved_path;
2002 if (android::base::Readlink(*path, &resolved_path)) {
2003 *path = resolved_path;
2004 }
2005}
2006
Nandana Dutt4be45d12018-09-26 15:04:23 +01002007/*
2008 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2009 * if we are writing zip files and adds the version file.
2010 */
2011static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002012 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2013
Nandana Dutt4be45d12018-09-26 15:04:23 +01002014 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2015 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002016 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002017 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002018 char date[80];
2019 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2020 ds.name_ = date;
2021 } else {
2022 ds.name_ = "undated";
2023 }
2024
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002025 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002026 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002027 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002028 ds.base_name_ += "-wifi";
2029 }
2030
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002031 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002032 ds.screenshot_path_ = ds.GetPath(".png");
2033 }
2034 ds.tmp_path_ = ds.GetPath(".tmp");
2035 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2036
Nandana Dutt54dbd672019-01-11 12:58:05 +00002037 std::string destination = ds.options_->bugreport_fd.get() != -1
2038 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002039 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002040 MYLOGD(
2041 "Bugreport dir: %s\n"
2042 "Base name: %s\n"
2043 "Suffix: %s\n"
2044 "Log path: %s\n"
2045 "Temporary path: %s\n"
2046 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002047 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2048 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002049
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002050 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002051 ds.path_ = ds.GetPath(".zip");
2052 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2053 create_parent_dirs(ds.path_.c_str());
2054 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2055 if (ds.zip_file == nullptr) {
2056 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2057 } else {
2058 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2059 }
2060 ds.AddTextZipEntry("version.txt", ds.version_);
2061 }
2062}
2063
2064/*
2065 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2066 * printing zipped file status, etc.
2067 */
2068static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002069 /* check if user changed the suffix using system properties */
2070 std::string name =
2071 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2072 bool change_suffix = false;
2073 if (!name.empty()) {
2074 /* must whitelist which characters are allowed, otherwise it could cross directories */
2075 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2076 if (std::regex_match(name.c_str(), valid_regex)) {
2077 change_suffix = true;
2078 } else {
2079 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2080 }
2081 }
2082 if (change_suffix) {
2083 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2084 ds.name_ = name;
2085 if (!ds.screenshot_path_.empty()) {
2086 std::string new_screenshot_path = ds.GetPath(".png");
2087 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2088 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2089 new_screenshot_path.c_str(), strerror(errno));
2090 } else {
2091 ds.screenshot_path_ = new_screenshot_path;
2092 }
2093 }
2094 }
2095
2096 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002097 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002098 if (!ds.FinishZipFile()) {
2099 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2100 do_text_file = true;
2101 } else {
2102 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002103 // If the user has changed the suffix, we need to change the zip file name.
2104 std::string new_path = ds.GetPath(".zip");
2105 if (ds.path_ != new_path) {
2106 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2107 if (rename(ds.path_.c_str(), new_path.c_str())) {
2108 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2109 strerror(errno));
2110 } else {
2111 ds.path_ = new_path;
2112 }
2113 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002114 }
2115 }
2116 if (do_text_file) {
2117 ds.path_ = ds.GetPath(".txt");
2118 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2119 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2120 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2121 ds.path_.clear();
2122 }
2123 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002124 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002125 if (do_text_file) {
2126 dprintf(ds.control_socket_fd_,
2127 "FAIL:could not create zip file, check %s "
2128 "for more details\n",
2129 ds.log_path_.c_str());
2130 } else {
2131 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2132 }
2133 }
2134}
2135
2136/* Broadcasts that we are done with the bugreport */
2137static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002138 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002139 if (!ds.path_.empty()) {
2140 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002141 // clang-format off
2142
2143 std::vector<std::string> am_args = {
2144 "--receiver-permission", "android.permission.DUMP",
2145 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2146 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2147 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002148 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002149 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2150 };
2151 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002152 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002153 am_args.push_back("--es");
2154 am_args.push_back("android.intent.extra.SCREENSHOT");
2155 am_args.push_back(ds.screenshot_path_);
2156 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002157 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002158 am_args.push_back("--es");
2159 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002160 am_args.push_back(ds.options_->notification_title);
2161 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002162 am_args.push_back("--es");
2163 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002164 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002165 }
2166 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002167 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002168 am_args.push_back("--es");
2169 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002170 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002171 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2172 } else {
2173 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2174 }
2175 } else {
2176 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2177 }
2178}
2179
Nandana Dutt58d72e22018-11-16 10:30:48 +00002180static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2181 switch (mode) {
2182 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2183 return "BUGREPORT_FULL";
2184 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2185 return "BUGREPORT_INTERACTIVE";
2186 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2187 return "BUGREPORT_REMOTE";
2188 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2189 return "BUGREPORT_WEAR";
2190 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2191 return "BUGREPORT_TELEPHONY";
2192 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2193 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002194 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2195 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002196 }
2197}
2198
2199static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002200 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002201 switch (mode) {
2202 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2203 options->do_broadcast = true;
2204 options->do_fb = true;
2205 break;
2206 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002207 // Currently, the dumpstate binder is only used by Shell to update progress.
2208 options->do_start_service = true;
2209 options->do_progress_updates = true;
2210 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002211 options->do_broadcast = true;
2212 break;
2213 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002214 options->do_vibrate = false;
2215 options->is_remote_mode = true;
2216 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002217 options->do_broadcast = true;
2218 break;
2219 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002220 options->do_start_service = true;
2221 options->do_progress_updates = true;
2222 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002223 options->do_fb = true;
2224 options->do_broadcast = true;
2225 break;
2226 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002227 options->telephony_only = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002228 options->do_fb = true;
2229 options->do_broadcast = true;
2230 break;
2231 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002232 options->wifi_only = true;
2233 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002234 options->do_fb = true;
2235 options->do_broadcast = true;
2236 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002237 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2238 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002239 }
2240}
2241
2242static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002243 // If the system property is not set, it's assumed to be a default bugreport.
2244 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002245
2246 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2247 if (!extra_options.empty()) {
2248 // Framework uses a system property to override some command-line args.
2249 // Currently, it contains the type of the requested bugreport.
2250 if (extra_options == "bugreportplus") {
2251 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002252 } else if (extra_options == "bugreportfull") {
2253 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002254 } else if (extra_options == "bugreportremote") {
2255 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2256 } else if (extra_options == "bugreportwear") {
2257 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2258 } else if (extra_options == "bugreporttelephony") {
2259 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2260 } else if (extra_options == "bugreportwifi") {
2261 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002262 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002263 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002264 }
2265 // Reset the property
2266 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2267 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002268 return mode;
2269}
2270
2271// TODO: Move away from system properties when we have options passed via binder calls.
2272/* Sets runtime options from the system properties and then clears those properties. */
2273static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2274 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2275 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002276
2277 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2278 if (!options->notification_title.empty()) {
2279 // Reset the property
2280 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2281
Nandana Duttdd8cca32018-11-14 10:10:29 +00002282 options->notification_description =
2283 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002284 if (!options->notification_description.empty()) {
2285 // Reset the property
2286 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2287 }
2288 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2289 options->notification_description.c_str());
2290 }
2291}
2292
Nandana Dutt58d72e22018-11-16 10:30:48 +00002293static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2294 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2295 MYLOGI("do_add_date: %d\n", options.do_add_date);
2296 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2297 MYLOGI("use_socket: %d\n", options.use_socket);
2298 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2299 MYLOGI("do_fb: %d\n", options.do_fb);
2300 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2301 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2302 MYLOGI("show_header_only: %d\n", options.show_header_only);
2303 MYLOGI("do_start_service: %d\n", options.do_start_service);
2304 MYLOGI("telephony_only: %d\n", options.telephony_only);
2305 MYLOGI("wifi_only: %d\n", options.wifi_only);
2306 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002307 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002308 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2309 MYLOGI("args: %s\n", options.args.c_str());
2310 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2311 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2312}
2313
Nandana Dutt54dbd672019-01-11 12:58:05 +00002314void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2315 const android::base::unique_fd& bugreport_fd_in,
2316 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002317 // In the new API world, date is always added; output is always a zip file.
2318 // TODO(111441001): remove these options once they are obsolete.
2319 do_add_date = true;
2320 do_zip_file = true;
2321
Nandana Dutt54dbd672019-01-11 12:58:05 +00002322 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2323 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2324 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002325
2326 extra_options = ModeToString(bugreport_mode);
2327 SetOptionsFromMode(bugreport_mode, this);
2328}
2329
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002330Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2331 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002332 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002333 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002334 switch (c) {
2335 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002336 case 'd': do_add_date = true; break;
2337 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002338 // o=use_outfile not supported anymore.
2339 // TODO(b/111441001): Remove when all callers have migrated.
2340 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002341 case 's': use_socket = true; break;
2342 case 'S': use_control_socket = true; break;
2343 case 'v': show_header_only = true; break;
2344 case 'q': do_vibrate = false; break;
2345 case 'p': do_fb = true; break;
2346 case 'P': do_progress_updates = true; break;
2347 case 'R': is_remote_mode = true; break;
2348 case 'B': do_broadcast = true; break;
2349 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002350 case 'w':
2351 // This was already processed
2352 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002353 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002354 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002355 break;
2356 default:
2357 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002358 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002359 break;
2360 // clang-format on
2361 }
2362 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002363
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002364 // TODO: use helper function to convert argv into a string
2365 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002366 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002367 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002368 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002369 }
2370 }
2371
2372 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2373 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002374
2375 SetOptionsFromProperties(this);
2376 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002377}
2378
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002379bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002380 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002381 return false;
2382 }
2383
Nandana Dutt9a76d202019-01-21 15:56:48 +00002384 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002385 return false;
2386 }
2387
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002388 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002389 return false;
2390 }
2391
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002392 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002393 return false;
2394 }
2395
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002396 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002397 return false;
2398 }
2399 return true;
2400}
2401
Nandana Dutt197661d2018-11-16 16:40:21 +00002402void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2403 options_ = std::move(options);
2404}
2405
Nandana Duttd2f5f082019-01-18 17:13:52 +00002406Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2407 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002408 if (listener_ != nullptr) {
2409 switch (status) {
2410 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002411 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002412 break;
2413 case Dumpstate::RunStatus::HELP:
2414 break;
2415 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002416 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002417 break;
2418 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002419 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2420 break;
2421 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2422 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2423 break;
2424 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2425 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002426 break;
2427 }
2428 }
2429 return status;
2430}
2431
Nandana Dutt979388e2018-11-30 16:48:55 +00002432/*
2433 * Dumps relevant information to a bugreport based on the given options.
2434 *
2435 * The bugreport can be dumped to a file or streamed to a socket.
2436 *
2437 * How dumping to file works:
2438 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2439 * stderr is redirected a log file.
2440 *
2441 * The temporary bugreport is then populated via printfs, dumping contents of files and
2442 * output of commands to stdout.
2443 *
2444 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2445 * text file.
2446 *
2447 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2448 * gets added to the archive.
2449 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002450 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2451 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002452 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002453Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2454 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002455 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002456 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002457 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002458 return RunStatus::INVALID_INPUT;
2459 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002460 /* set as high priority, and protect from OOM killer */
2461 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002462
Felipe Lemed071c682016-10-20 16:48:00 -07002463 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002464 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002465 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002466 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002467 } else {
2468 /* fallback to kernels <= 2.6.35 */
2469 oom_adj = fopen("/proc/self/oom_adj", "we");
2470 if (oom_adj) {
2471 fputs("-17", oom_adj);
2472 fclose(oom_adj);
2473 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002474 }
2475
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002476 if (version_ == VERSION_DEFAULT) {
2477 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002478 }
2479
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002480 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002481 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002482 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002483 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002484 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002485 }
2486
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002487 if (options_->show_header_only) {
2488 PrintHeader();
2489 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002490 }
2491
Nandana Duttd2f5f082019-01-18 17:13:52 +00002492 if (options_->bugreport_fd.get() != -1) {
2493 // If the output needs to be copied over to the caller's fd, get user consent.
2494 android::String16 package(calling_package.c_str());
2495 CheckUserConsent(calling_uid, package);
2496 }
2497
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002498 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002499 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002500
2501 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002502 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002503 is_redirecting
2504 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2505 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002506 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002507
Felipe Lemed071c682016-10-20 16:48:00 -07002508 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002509 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002510 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002511 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2512
2513 MYLOGI("begin\n");
2514
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002515 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002516
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002517 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002518 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002519 MYLOGI("Starting 'dumpstate' service\n");
2520 android::status_t ret;
2521 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2522 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2523 }
2524 }
2525
Felipe Lemef0292972016-11-22 13:57:05 -08002526 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002527 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2528 }
2529
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002530 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2531 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002532
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002533 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002534
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002535 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002536
Christopher Ferrised9354f2014-10-01 17:35:01 -07002537 // If we are going to use a socket, do it as early as possible
2538 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002539 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002540 if (!redirect_to_socket(stdout, "dumpstate")) {
2541 return ERROR;
2542 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002543 }
2544
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002545 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002546 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002547 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002548 if (control_socket_fd_ == -1) {
2549 return ERROR;
2550 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002551 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002552 }
2553
Felipe Leme71bbfc52015-11-23 14:14:51 -08002554 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002555 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002556
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002557 if (options_->do_progress_updates) {
2558 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002559 // clang-format off
2560 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002561 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002562 "--es", "android.intent.extra.NAME", name_,
2563 "--ei", "android.intent.extra.ID", std::to_string(id_),
2564 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2565 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002566 };
2567 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002568 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002569 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002570 if (options_->use_control_socket) {
2571 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002572 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002573 }
2574 }
2575
Nick Kralevichf3599b32016-01-25 15:05:16 -08002576 /* read /proc/cmdline before dropping root */
2577 FILE *cmdline = fopen("/proc/cmdline", "re");
2578 if (cmdline) {
2579 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2580 fclose(cmdline);
2581 }
2582
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002583 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002584 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002585 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002586
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002587 if (options_->do_fb && do_early_screenshot_) {
2588 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002589 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002590 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002591 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002592 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002593 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002594 }
2595 }
2596
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002597 if (options_->do_zip_file && zip_file != nullptr) {
2598 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2599 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002600 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002601 }
2602 }
2603
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002604 int dup_stdout_fd;
2605 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002606 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002607 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002608 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002609 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2610 return ERROR;
2611 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002612 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2613 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2614 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002615 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002616
2617 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2618 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002619 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002620 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002621 /* TODO: rather than generating a text file now and zipping it later,
2622 it would be more efficient to redirect stdout to the zip entry
2623 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002624 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2625 return ERROR;
2626 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002627 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002628 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002629 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002630 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002631 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002632
2633 // Don't buffer stdout
2634 setvbuf(stdout, nullptr, _IONBF, 0);
2635
Felipe Leme608385d2016-02-01 10:35:38 -08002636 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2637 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002638 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002639 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002640
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002641 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002642 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002643 DumpstateBoard();
2644 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002645 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002646 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002647 // Dump state for the default case. This also drops root.
Nandana Dutt5c390032019-03-12 10:52:56 +00002648 RunStatus s = DumpstateDefault();
2649 if (s != RunStatus::OK) {
2650 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2651 HandleUserConsentDenied();
2652 }
2653 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002654 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002655 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002656
Felipe Leme55b42a62015-11-10 17:39:08 -08002657 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002658 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002659 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002660 }
2661
Nandana Duttd2f5f082019-01-18 17:13:52 +00002662 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002663 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002664 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002665 }
2666
Nandana Duttd2f5f082019-01-18 17:13:52 +00002667 // Share the final file with the caller if the user has consented.
2668 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2669 if (options_->bugreport_fd.get() != -1) {
2670 status = CopyBugreportIfUserConsented();
2671 if (status != Dumpstate::RunStatus::OK &&
2672 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2673 // Do an early return if there were errors. We make an exception for consent
2674 // timing out because it's possible the user got distracted. In this case the
2675 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002676 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002677 return status;
2678 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002679 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002680 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2681 options_->screenshot_fd.get());
2682 if (copy_succeeded) {
2683 android::os::UnlinkAndLogOnError(screenshot_path_);
2684 }
2685 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002686 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2687 MYLOGI(
2688 "Did not receive user consent yet."
2689 " Will not copy the bugreport artifacts to caller.\n");
Nandana Dutt5c390032019-03-12 10:52:56 +00002690 // TODO(b/111441001): cancel outstanding requests
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002691 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002692 }
2693
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002694 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002695 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002696 for (int i = 0; i < 3; i++) {
2697 Vibrate(75);
2698 usleep((75 + 50) * 1000);
2699 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002700 }
2701
Jeff Brown1dc94e32014-09-11 14:15:27 -07002702 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002703 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002704 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002705 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002706 }
2707
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002708 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2709 progress_->GetInitialMax());
2710 progress_->Save();
2711 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002712
Felipe Leme107a05f2016-03-08 15:11:15 -08002713 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002714 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002715 }
2716
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002717 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002718 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002719 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002720 }
2721
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002722 tombstone_data_.clear();
2723 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002724
Nandana Duttd2f5f082019-01-18 17:13:52 +00002725 return (consent_callback_ != nullptr &&
2726 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2727 ? USER_CONSENT_TIMED_OUT
2728 : RunStatus::OK;
2729}
2730
2731void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2732 consent_callback_ = new ConsentCallback();
2733 const String16 incidentcompanion("incidentcompanion");
2734 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2735 if (ics != nullptr) {
2736 MYLOGD("Checking user consent via incidentcompanion service\n");
2737 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Joe Onorato1c36d752019-03-17 18:26:43 -07002738 calling_uid, calling_package, String16(), String16(),
2739 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002740 } else {
2741 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2742 }
2743}
2744
Nandana Dutt5c390032019-03-12 10:52:56 +00002745bool Dumpstate::IsUserConsentDenied() const {
2746 return ds.consent_callback_ != nullptr &&
2747 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2748}
2749
Nandana Duttd2f5f082019-01-18 17:13:52 +00002750void Dumpstate::CleanupFiles() {
2751 android::os::UnlinkAndLogOnError(tmp_path_);
2752 android::os::UnlinkAndLogOnError(screenshot_path_);
2753 android::os::UnlinkAndLogOnError(path_);
2754}
2755
2756Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2757 MYLOGD("User denied consent; deleting files and returning\n");
2758 CleanupFiles();
2759 return USER_CONSENT_DENIED;
2760}
2761
2762Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2763 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2764 // user consent.
2765 UserConsentResult consent_result = consent_callback_->getResult();
2766 if (consent_result == UserConsentResult::UNAVAILABLE) {
2767 // User has not responded yet.
2768 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2769 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2770 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2771 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2772 sleep(delay_seconds);
2773 }
2774 consent_result = consent_callback_->getResult();
2775 }
2776 if (consent_result == UserConsentResult::DENIED) {
2777 // User has explicitly denied sharing with the app. To be safe delete the
2778 // internal bugreport & tmp files.
2779 return HandleUserConsentDenied();
2780 }
2781 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002782 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2783 if (copy_succeeded) {
2784 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002785 }
2786 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2787 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2788 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2789 // Since we do not have user consent to share the bugreport it does not get
2790 // copied over to the calling app but remains in the internal directory from
2791 // where the user can manually pull it.
2792 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2793 }
2794 // Unknown result; must be a programming error.
2795 MYLOGE("Unknown user consent result:%d\n", consent_result);
2796 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002797}
2798
Nandana Duttf02564e2019-02-15 15:24:24 +00002799Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002800 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2801 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2802 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002803 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002804 // When directly running dumpstate binary, the output is not expected to be written
2805 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002806 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002807
2808 // calling_uid and calling_package are for user consent to share the bugreport with
2809 // an app; they are irrelvant here because bugreport is only written to a local
2810 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002811 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002812 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002813 return status;
2814}
2815
2816/* Main entry point for dumpstate binary. */
2817int run_main(int argc, char* argv[]) {
2818 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002819
2820 switch (status) {
2821 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002822 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002823 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002824 ShowUsage();
2825 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002826 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002827 fprintf(stderr, "Invalid combination of args\n");
2828 ShowUsage();
2829 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002830 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002831 FALLTHROUGH_INTENDED;
2832 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2833 FALLTHROUGH_INTENDED;
2834 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002835 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002836 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002837}