blob: c1a4b3bc9a692d42cc97c932b6682a022706ec42 [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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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 Duttbbdb5b42019-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");
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001483 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001484}
1485
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001486/*
1487 * Dumps state for the default case; drops root after it's no longer necessary.
1488 *
1489 * Returns RunStatus::OK if everything went fine.
1490 * Returns RunStatus::ERROR if there was an error.
1491 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1492 * with the caller.
1493 */
1494static Dumpstate::RunStatus DumpstateDefault() {
Primiano Tucci2d7f5c22019-01-17 15:51:14 +00001495 // Try to dump anrd trace if the daemon is running.
1496 dump_anrd_trace();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001497
Nandana Duttcf419a72019-03-14 10:40:17 +00001498 // Invoking the following dumpsys calls before DumpTraces() to try and
Nandana Dutt4be45d12018-09-26 15:04:23 +01001499 // keep the system stats as close to its initial state as possible.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001500 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001501
1502 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001503 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001504
1505 /* Run some operations that require root. */
1506 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1507 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1508
1509 ds.AddDir(RECOVERY_DIR, true);
1510 ds.AddDir(RECOVERY_DATA_DIR, true);
1511 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1512 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1513 if (!PropertiesHelper::IsUserBuild()) {
1514 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1515 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1516 }
1517 add_mountinfo();
1518 DumpIpTablesAsRoot();
1519
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001520 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001521 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1522
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001523 // Dump IPsec stats. No keys are exposed here.
1524 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1525
Nandana Dutt4be45d12018-09-26 15:04:23 +01001526 // Run ss as root so we can see socket marks.
1527 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1528
1529 // Run iotop as root to show top 100 IO threads
1530 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1531
Erick Reyese68df822019-02-11 14:46:36 -08001532 // Gather shared memory buffer info if the product implements it
1533 struct stat st;
1534 if (!stat("/product/bin/dmabuf_dump", &st)) {
1535 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1536 }
1537
Nandana Dutt4be45d12018-09-26 15:04:23 +01001538 if (!DropRootUser()) {
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001539 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001540 }
1541
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001542 RETURN_IF_USER_DENIED_CONSENT();
1543 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001544}
1545
mukesh agrawal253dad42018-01-23 21:59:59 -08001546// This method collects common dumpsys for telephony and wifi
1547static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001548 DumpIpTablesAsRoot();
1549
1550 if (!DropRootUser()) {
1551 return;
1552 }
1553
1554 do_dmesg();
1555 DoLogcat();
1556 DumpPacketStats();
1557 DoKmsg();
1558 DumpIpAddrAndRules();
1559 dump_route_tables();
1560
1561 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1562 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001563}
1564
1565// This method collects dumpsys for telephony debugging only
1566static void DumpstateTelephonyOnly() {
1567 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001568 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001569
1570 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001571
1572 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1573
1574 printf("========================================================\n");
1575 printf("== Android Framework Services\n");
1576 printf("========================================================\n");
1577
Vishnu Nair652cc802017-11-30 15:18:30 -08001578 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1579 SEC_TO_MSEC(10));
Chiachang Wang85e0db32019-03-25 08:59:55 +08001580 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1581 SEC_TO_MSEC(10));
1582 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Vishnu Nair652cc802017-11-30 15:18:30 -08001583 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1584 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001585 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1586 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001587 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1588 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001589
1590 printf("========================================================\n");
1591 printf("== Running Application Services\n");
1592 printf("========================================================\n");
1593
1594 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1595
1596 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001597 printf("== Running Application Services (non-platform)\n");
1598 printf("========================================================\n");
1599
1600 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1601 DUMPSYS_COMPONENTS_OPTIONS);
1602
1603 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001604 printf("== Checkins\n");
1605 printf("========================================================\n");
1606
1607 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1608
1609 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001610 printf("== dumpstate: done (id %d)\n", ds.id_);
1611 printf("========================================================\n");
1612}
1613
mukesh agrawal253dad42018-01-23 21:59:59 -08001614// This method collects dumpsys for wifi debugging only
1615static void DumpstateWifiOnly() {
1616 DurationReporter duration_reporter("DUMPSTATE");
1617
1618 DumpstateRadioCommon();
1619
1620 printf("========================================================\n");
1621 printf("== Android Framework Services\n");
1622 printf("========================================================\n");
1623
1624 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1625 SEC_TO_MSEC(10));
1626 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1627 SEC_TO_MSEC(10));
1628
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001629 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001630
mukesh agrawal253dad42018-01-23 21:59:59 -08001631 printf("========================================================\n");
1632 printf("== dumpstate: done (id %d)\n", ds.id_);
1633 printf("========================================================\n");
1634}
1635
Nandana Duttcf419a72019-03-14 10:40:17 +00001636Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001637 DurationReporter duration_reporter("DUMP TRACES");
1638
1639 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1640 const size_t buf_size = temp_file_pattern.length() + 1;
1641 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1642 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1643
1644 // Create a new, empty file to receive all trace dumps.
1645 //
1646 // TODO: This can be simplified once we remove support for the old style
1647 // dumps. We can have a file descriptor passed in to dump_traces instead
1648 // of creating a file, closing it and then reopening it again.
1649 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1650 if (fd < 0) {
1651 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001652 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001653 }
1654
1655 // Nobody should have access to this temporary file except dumpstate, but we
1656 // temporarily grant 'read' to 'others' here because this file is created
1657 // when tombstoned is still running as root, but dumped after dropping. This
1658 // can go away once support for old style dumping has.
1659 const int chmod_ret = fchmod(fd, 0666);
1660 if (chmod_ret < 0) {
1661 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001662 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001663 }
1664
1665 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1666 if (proc.get() == nullptr) {
1667 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001668 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001669 }
1670
1671 // Number of times process dumping has timed out. If we encounter too many
1672 // failures, we'll give up.
1673 int timeout_failures = 0;
1674 bool dalvik_found = false;
1675
1676 const std::set<int> hal_pids = get_interesting_hal_pids();
1677
1678 struct dirent* d;
1679 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001680 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001681 int pid = atoi(d->d_name);
1682 if (pid <= 0) {
1683 continue;
1684 }
1685
1686 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1687 std::string exe;
1688 if (!android::base::Readlink(link_name, &exe)) {
1689 continue;
1690 }
1691
1692 bool is_java_process;
1693 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1694 // Don't bother dumping backtraces for the zygote.
1695 if (IsZygote(pid)) {
1696 continue;
1697 }
1698
1699 dalvik_found = true;
1700 is_java_process = true;
1701 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1702 is_java_process = false;
1703 } else {
1704 // Probably a native process we don't care about, continue.
1705 continue;
1706 }
1707
1708 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1709 if (timeout_failures == 3) {
1710 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1711 break;
1712 }
1713
1714 const uint64_t start = Nanotime();
1715 const int ret = dump_backtrace_to_file_timeout(
1716 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1717 is_java_process ? 5 : 20, fd);
1718
1719 if (ret == -1) {
1720 // For consistency, the header and footer to this message match those
1721 // dumped by debuggerd in the success case.
1722 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1723 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1724 dprintf(fd, "---- end %d ----", pid);
1725 timeout_failures++;
1726 continue;
1727 }
1728
1729 // We've successfully dumped stack traces, reset the failure count
1730 // and write a summary of the elapsed time to the file and continue with the
1731 // next process.
1732 timeout_failures = 0;
1733
1734 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1735 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1736 }
1737
1738 if (!dalvik_found) {
1739 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1740 }
1741
Nandana Duttcf419a72019-03-14 10:40:17 +00001742 *path = file_name_buf.release();
1743 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001744}
1745
Felipe Leme6f674ae2016-11-18 17:10:33 -08001746void Dumpstate::DumpstateBoard() {
1747 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001748 printf("========================================================\n");
1749 printf("== Board\n");
1750 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001751
Felipe Leme6f674ae2016-11-18 17:10:33 -08001752 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001753 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001754 return;
1755 }
1756
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001757 std::vector<std::string> paths;
1758 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001759 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001760 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1761 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001762 remover.emplace_back(android::base::make_scope_guard(
1763 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001764 }
Jie Song9fbfad02017-06-20 16:29:42 -07001765
Wei Wang587eac92018-04-05 12:17:20 -07001766 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1767 if (dumpstate_device == nullptr) {
1768 MYLOGE("No IDumpstateDevice implementation\n");
1769 return;
1770 }
1771
1772 using ScopedNativeHandle =
1773 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1774 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1775 [](native_handle_t* handle) {
1776 native_handle_close(handle);
1777 native_handle_delete(handle);
1778 });
1779 if (handle == nullptr) {
1780 MYLOGE("Could not create native_handle\n");
1781 return;
1782 }
1783
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001784 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001785 for (size_t i = 0; i < paths.size(); i++) {
1786 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1787
1788 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1789 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1790 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1791 if (fd < 0) {
1792 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1793 return;
1794 }
1795 handle.get()->data[i] = fd.release();
1796 }
1797
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001798 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001799 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1800 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1801 // and grab whatever dumped
1802 std::packaged_task<bool()>
1803 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001804 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1805 if (!status.isOk()) {
1806 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001807 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001808 }
Wei Wang587eac92018-04-05 12:17:20 -07001809 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001810 });
Wei Wang587eac92018-04-05 12:17:20 -07001811
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001812 auto result = dumpstate_task.get_future();
1813 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001814
1815 constexpr size_t timeout_sec = 30;
1816 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1817 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1818 if (!android::base::SetProperty("ctl.interface_restart",
1819 android::base::StringPrintf("%s/default",
1820 IDumpstateDevice::descriptor))) {
1821 MYLOGE("Couldn't restart dumpstate HAL\n");
1822 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001823 }
Wei Wang587eac92018-04-05 12:17:20 -07001824 // Wait some time for init to kill dumpstate vendor HAL
1825 constexpr size_t killing_timeout_sec = 10;
1826 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1827 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1828 "there might be racing in content\n", killing_timeout_sec);
1829 }
1830
1831 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1832 for (size_t i = 0; i < paths.size(); i++) {
1833 struct stat s;
1834 if (fstat(handle.get()->data[i], &s) == -1) {
1835 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1836 strerror(errno));
1837 file_sizes[i] = -1;
1838 continue;
1839 }
1840 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001841 }
1842
1843 for (size_t i = 0; i < paths.size(); i++) {
1844 if (file_sizes[i] == -1) {
1845 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001846 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001847 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001848 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001849 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001850 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001851 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001852 }
1853
Felipe Lemed8b94e52016-12-08 10:21:44 -08001854 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001855}
1856
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001857static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001858 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001859 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001860 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1861 " -h: display this help message\n"
1862 " -b: play sound file instead of vibrate, at beginning of job\n"
1863 " -e: play sound file instead of vibrate, at end of job\n"
1864 " -o: write to file (instead of stdout)\n"
1865 " -d: append date to filename (requires -o)\n"
1866 " -p: capture screenshot to filename.png (requires -o)\n"
1867 " -z: generate zipped file (requires -o)\n"
1868 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001869 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001870 " -q: disable vibrate\n"
1871 " -B: send broadcast when finished (requires -o)\n"
1872 " -P: send broadcast when started and update system properties on "
1873 "progress (requires -o and -B)\n"
1874 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1875 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001876 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001877 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001878}
1879
Wei Liuf87959e2016-08-26 14:51:42 -07001880static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001881 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001882}
1883
Felipe Leme1d486fe2016-10-14 18:06:47 -07001884bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001885 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001886 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001887 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001888 // Final timestamp
1889 char date[80];
1890 time_t the_real_now_please_stand_up = time(nullptr);
1891 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001892 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001893 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001894
Felipe Leme9a523ae2016-10-20 15:10:33 -07001895 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001896 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001897 return false;
1898 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001899 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001900 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001901 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001902 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001903
Felipe Leme0f3fb202016-06-10 17:10:53 -07001904 // Add log file (which contains stderr output) to zip...
1905 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001906 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001907 MYLOGE("Failed to add dumpstate log to .zip file\n");
1908 return false;
1909 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001910 // TODO: Should truncate the existing file.
1911 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001912 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1913 return false;
1914 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001915 fprintf(stderr, "\n");
1916
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001917 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001918 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001919 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001920 return false;
1921 }
1922
Felipe Leme1d486fe2016-10-14 18:06:47 -07001923 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1924 ds.zip_file.reset(nullptr);
1925
Felipe Lemee9d2c542016-11-15 11:48:26 -08001926 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001927 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001928
Felipe Leme1e9edc62015-12-21 16:02:13 -08001929 return true;
1930}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001931
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001932static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001933 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1934 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001935 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001936 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001937 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001938 }
1939
1940 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001941 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001942
1943 std::vector<uint8_t> buffer(65536);
1944 while (1) {
1945 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1946 if (bytes_read == 0) {
1947 break;
1948 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001949 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001950 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001951 }
1952
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001953 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001954 }
1955
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001956 uint8_t hash[SHA256_DIGEST_LENGTH];
1957 SHA256_Final(hash, &ctx);
1958
1959 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1960 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001961 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001962 }
1963 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1964 return std::string(hash_buffer);
1965}
1966
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001967static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1968 // clang-format off
1969 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1970 "--receiver-foreground", "--receiver-include-background", "-a", action};
1971 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001972
1973 am.insert(am.end(), args.begin(), args.end());
1974
Felipe Leme8d2410e2017-02-08 09:46:08 -08001975 RunCommand("", am,
1976 CommandOptions::WithTimeout(20)
1977 .Log("Sending broadcast: '%s'\n")
1978 .Always()
1979 .DropRoot()
1980 .RedirectStderr()
1981 .Build());
1982}
1983
Felipe Leme35b8cf12017-02-10 15:47:29 -08001984static void Vibrate(int duration_ms) {
1985 // clang-format off
1986 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1987 CommandOptions::WithTimeout(10)
1988 .Log("Vibrate: '%s'\n")
1989 .Always()
1990 .Build());
1991 // clang-format on
1992}
1993
Nandana Dutt979388e2018-11-30 16:48:55 +00001994static void MaybeResolveSymlink(std::string* path) {
1995 std::string resolved_path;
1996 if (android::base::Readlink(*path, &resolved_path)) {
1997 *path = resolved_path;
1998 }
1999}
2000
Nandana Dutt4be45d12018-09-26 15:04:23 +01002001/*
2002 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2003 * if we are writing zip files and adds the version file.
2004 */
2005static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002006 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2007
Nandana Dutt4be45d12018-09-26 15:04:23 +01002008 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2009 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002010 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002011 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002012 char date[80];
2013 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2014 ds.name_ = date;
2015 } else {
2016 ds.name_ = "undated";
2017 }
2018
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002019 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002020 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002021 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002022 ds.base_name_ += "-wifi";
2023 }
2024
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002025 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002026 ds.screenshot_path_ = ds.GetPath(".png");
2027 }
2028 ds.tmp_path_ = ds.GetPath(".tmp");
2029 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2030
Nandana Dutt54dbd672019-01-11 12:58:05 +00002031 std::string destination = ds.options_->bugreport_fd.get() != -1
2032 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002033 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002034 MYLOGD(
2035 "Bugreport dir: %s\n"
2036 "Base name: %s\n"
2037 "Suffix: %s\n"
2038 "Log path: %s\n"
2039 "Temporary path: %s\n"
2040 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002041 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2042 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002043
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002044 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002045 ds.path_ = ds.GetPath(".zip");
2046 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2047 create_parent_dirs(ds.path_.c_str());
2048 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2049 if (ds.zip_file == nullptr) {
2050 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2051 } else {
2052 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2053 }
2054 ds.AddTextZipEntry("version.txt", ds.version_);
2055 }
2056}
2057
2058/*
2059 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2060 * printing zipped file status, etc.
2061 */
2062static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002063 /* check if user changed the suffix using system properties */
2064 std::string name =
2065 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2066 bool change_suffix = false;
2067 if (!name.empty()) {
2068 /* must whitelist which characters are allowed, otherwise it could cross directories */
2069 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2070 if (std::regex_match(name.c_str(), valid_regex)) {
2071 change_suffix = true;
2072 } else {
2073 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2074 }
2075 }
2076 if (change_suffix) {
2077 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2078 ds.name_ = name;
2079 if (!ds.screenshot_path_.empty()) {
2080 std::string new_screenshot_path = ds.GetPath(".png");
2081 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2082 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2083 new_screenshot_path.c_str(), strerror(errno));
2084 } else {
2085 ds.screenshot_path_ = new_screenshot_path;
2086 }
2087 }
2088 }
2089
2090 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002091 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002092 if (!ds.FinishZipFile()) {
2093 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2094 do_text_file = true;
2095 } else {
2096 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002097 // If the user has changed the suffix, we need to change the zip file name.
2098 std::string new_path = ds.GetPath(".zip");
2099 if (ds.path_ != new_path) {
2100 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2101 if (rename(ds.path_.c_str(), new_path.c_str())) {
2102 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2103 strerror(errno));
2104 } else {
2105 ds.path_ = new_path;
2106 }
2107 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002108 }
2109 }
2110 if (do_text_file) {
2111 ds.path_ = ds.GetPath(".txt");
2112 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2113 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2114 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2115 ds.path_.clear();
2116 }
2117 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002118 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002119 if (do_text_file) {
2120 dprintf(ds.control_socket_fd_,
2121 "FAIL:could not create zip file, check %s "
2122 "for more details\n",
2123 ds.log_path_.c_str());
2124 } else {
2125 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2126 }
2127 }
2128}
2129
2130/* Broadcasts that we are done with the bugreport */
2131static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002132 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002133 if (!ds.path_.empty()) {
2134 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002135 // clang-format off
2136
2137 std::vector<std::string> am_args = {
2138 "--receiver-permission", "android.permission.DUMP",
2139 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2140 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2141 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002142 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002143 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2144 };
2145 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002146 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002147 am_args.push_back("--es");
2148 am_args.push_back("android.intent.extra.SCREENSHOT");
2149 am_args.push_back(ds.screenshot_path_);
2150 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002151 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002152 am_args.push_back("--es");
2153 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002154 am_args.push_back(ds.options_->notification_title);
2155 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002156 am_args.push_back("--es");
2157 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002158 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002159 }
2160 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002161 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002162 am_args.push_back("--es");
2163 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002164 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002165 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2166 } else {
2167 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2168 }
2169 } else {
2170 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2171 }
2172}
2173
Nandana Dutt58d72e22018-11-16 10:30:48 +00002174static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2175 switch (mode) {
2176 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2177 return "BUGREPORT_FULL";
2178 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2179 return "BUGREPORT_INTERACTIVE";
2180 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2181 return "BUGREPORT_REMOTE";
2182 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2183 return "BUGREPORT_WEAR";
2184 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2185 return "BUGREPORT_TELEPHONY";
2186 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2187 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002188 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2189 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002190 }
2191}
2192
2193static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002194 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002195 switch (mode) {
2196 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2197 options->do_broadcast = true;
2198 options->do_fb = true;
2199 break;
2200 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002201 // Currently, the dumpstate binder is only used by Shell to update progress.
2202 options->do_start_service = true;
2203 options->do_progress_updates = true;
2204 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002205 options->do_broadcast = true;
2206 break;
2207 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002208 options->do_vibrate = false;
2209 options->is_remote_mode = 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_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002214 options->do_start_service = true;
2215 options->do_progress_updates = true;
2216 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002217 options->do_fb = true;
2218 options->do_broadcast = true;
2219 break;
2220 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002221 options->telephony_only = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002222 options->do_fb = true;
2223 options->do_broadcast = true;
2224 break;
2225 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002226 options->wifi_only = true;
2227 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002228 options->do_fb = true;
2229 options->do_broadcast = true;
2230 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002231 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2232 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002233 }
2234}
2235
2236static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002237 // If the system property is not set, it's assumed to be a default bugreport.
2238 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002239
2240 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2241 if (!extra_options.empty()) {
2242 // Framework uses a system property to override some command-line args.
2243 // Currently, it contains the type of the requested bugreport.
2244 if (extra_options == "bugreportplus") {
2245 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002246 } else if (extra_options == "bugreportfull") {
2247 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002248 } else if (extra_options == "bugreportremote") {
2249 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2250 } else if (extra_options == "bugreportwear") {
2251 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2252 } else if (extra_options == "bugreporttelephony") {
2253 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2254 } else if (extra_options == "bugreportwifi") {
2255 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002256 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002257 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002258 }
2259 // Reset the property
2260 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2261 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002262 return mode;
2263}
2264
2265// TODO: Move away from system properties when we have options passed via binder calls.
2266/* Sets runtime options from the system properties and then clears those properties. */
2267static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2268 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2269 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002270
2271 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2272 if (!options->notification_title.empty()) {
2273 // Reset the property
2274 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2275
Nandana Duttdd8cca32018-11-14 10:10:29 +00002276 options->notification_description =
2277 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002278 if (!options->notification_description.empty()) {
2279 // Reset the property
2280 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2281 }
2282 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2283 options->notification_description.c_str());
2284 }
2285}
2286
Nandana Dutt58d72e22018-11-16 10:30:48 +00002287static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2288 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2289 MYLOGI("do_add_date: %d\n", options.do_add_date);
2290 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2291 MYLOGI("use_socket: %d\n", options.use_socket);
2292 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2293 MYLOGI("do_fb: %d\n", options.do_fb);
2294 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2295 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2296 MYLOGI("show_header_only: %d\n", options.show_header_only);
2297 MYLOGI("do_start_service: %d\n", options.do_start_service);
2298 MYLOGI("telephony_only: %d\n", options.telephony_only);
2299 MYLOGI("wifi_only: %d\n", options.wifi_only);
2300 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002301 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002302 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2303 MYLOGI("args: %s\n", options.args.c_str());
2304 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2305 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2306}
2307
Nandana Dutt54dbd672019-01-11 12:58:05 +00002308void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2309 const android::base::unique_fd& bugreport_fd_in,
2310 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002311 // In the new API world, date is always added; output is always a zip file.
2312 // TODO(111441001): remove these options once they are obsolete.
2313 do_add_date = true;
2314 do_zip_file = true;
2315
Nandana Dutt54dbd672019-01-11 12:58:05 +00002316 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2317 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2318 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002319
2320 extra_options = ModeToString(bugreport_mode);
2321 SetOptionsFromMode(bugreport_mode, this);
2322}
2323
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002324Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2325 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002326 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002327 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002328 switch (c) {
2329 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002330 case 'd': do_add_date = true; break;
2331 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002332 // o=use_outfile not supported anymore.
2333 // TODO(b/111441001): Remove when all callers have migrated.
2334 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002335 case 's': use_socket = true; break;
2336 case 'S': use_control_socket = true; break;
2337 case 'v': show_header_only = true; break;
2338 case 'q': do_vibrate = false; break;
2339 case 'p': do_fb = true; break;
2340 case 'P': do_progress_updates = true; break;
2341 case 'R': is_remote_mode = true; break;
2342 case 'B': do_broadcast = true; break;
2343 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002344 case 'w':
2345 // This was already processed
2346 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002347 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002348 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002349 break;
2350 default:
2351 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002352 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002353 break;
2354 // clang-format on
2355 }
2356 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002357
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002358 // TODO: use helper function to convert argv into a string
2359 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002360 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002361 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002362 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002363 }
2364 }
2365
2366 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2367 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002368
2369 SetOptionsFromProperties(this);
2370 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002371}
2372
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002373bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002374 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002375 return false;
2376 }
2377
Nandana Dutt9a76d202019-01-21 15:56:48 +00002378 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002379 return false;
2380 }
2381
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002382 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002383 return false;
2384 }
2385
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002386 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002387 return false;
2388 }
2389
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002390 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002391 return false;
2392 }
2393 return true;
2394}
2395
Nandana Dutt197661d2018-11-16 16:40:21 +00002396void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2397 options_ = std::move(options);
2398}
2399
Nandana Duttd2f5f082019-01-18 17:13:52 +00002400Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2401 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002402 if (listener_ != nullptr) {
2403 switch (status) {
2404 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002405 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002406 break;
2407 case Dumpstate::RunStatus::HELP:
2408 break;
2409 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002410 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002411 break;
2412 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002413 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2414 break;
2415 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2416 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2417 break;
2418 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2419 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002420 break;
2421 }
2422 }
2423 return status;
2424}
2425
Nandana Dutt979388e2018-11-30 16:48:55 +00002426/*
2427 * Dumps relevant information to a bugreport based on the given options.
2428 *
2429 * The bugreport can be dumped to a file or streamed to a socket.
2430 *
2431 * How dumping to file works:
2432 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2433 * stderr is redirected a log file.
2434 *
2435 * The temporary bugreport is then populated via printfs, dumping contents of files and
2436 * output of commands to stdout.
2437 *
2438 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2439 * text file.
2440 *
2441 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2442 * gets added to the archive.
2443 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002444 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2445 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002446 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002447Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2448 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002449 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002450 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002451 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002452 return RunStatus::INVALID_INPUT;
2453 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002454 /* set as high priority, and protect from OOM killer */
2455 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002456
Felipe Lemed071c682016-10-20 16:48:00 -07002457 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002458 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002459 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002460 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002461 } else {
2462 /* fallback to kernels <= 2.6.35 */
2463 oom_adj = fopen("/proc/self/oom_adj", "we");
2464 if (oom_adj) {
2465 fputs("-17", oom_adj);
2466 fclose(oom_adj);
2467 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002468 }
2469
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002470 if (version_ == VERSION_DEFAULT) {
2471 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002472 }
2473
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002474 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002475 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002476 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002477 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002478 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002479 }
2480
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002481 if (options_->show_header_only) {
2482 PrintHeader();
2483 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002484 }
2485
Nandana Duttd2f5f082019-01-18 17:13:52 +00002486 if (options_->bugreport_fd.get() != -1) {
2487 // If the output needs to be copied over to the caller's fd, get user consent.
2488 android::String16 package(calling_package.c_str());
2489 CheckUserConsent(calling_uid, package);
2490 }
2491
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002492 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002493 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002494
2495 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002496 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002497 is_redirecting
2498 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2499 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002500 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002501
Felipe Lemed071c682016-10-20 16:48:00 -07002502 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002503 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002504 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002505 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2506
2507 MYLOGI("begin\n");
2508
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002509 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002510
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002511 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002512 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002513 MYLOGI("Starting 'dumpstate' service\n");
2514 android::status_t ret;
2515 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2516 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2517 }
2518 }
2519
Felipe Lemef0292972016-11-22 13:57:05 -08002520 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002521 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2522 }
2523
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002524 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2525 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002526
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002527 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002528
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002529 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002530
Christopher Ferrised9354f2014-10-01 17:35:01 -07002531 // If we are going to use a socket, do it as early as possible
2532 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002533 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002534 if (!redirect_to_socket(stdout, "dumpstate")) {
2535 return ERROR;
2536 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002537 }
2538
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002539 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002540 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002541 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002542 if (control_socket_fd_ == -1) {
2543 return ERROR;
2544 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002545 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002546 }
2547
Felipe Leme71bbfc52015-11-23 14:14:51 -08002548 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002549 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002550
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002551 if (options_->do_progress_updates) {
2552 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002553 // clang-format off
2554 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002555 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002556 "--es", "android.intent.extra.NAME", name_,
2557 "--ei", "android.intent.extra.ID", std::to_string(id_),
2558 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2559 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002560 };
2561 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002562 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002563 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002564 if (options_->use_control_socket) {
2565 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002566 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002567 }
2568 }
2569
Nick Kralevichf3599b32016-01-25 15:05:16 -08002570 /* read /proc/cmdline before dropping root */
2571 FILE *cmdline = fopen("/proc/cmdline", "re");
2572 if (cmdline) {
2573 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2574 fclose(cmdline);
2575 }
2576
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002577 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002578 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002579 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002580
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002581 if (options_->do_fb && do_early_screenshot_) {
2582 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002583 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002584 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002585 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002586 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002587 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002588 }
2589 }
2590
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002591 if (options_->do_zip_file && zip_file != nullptr) {
2592 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2593 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002594 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002595 }
2596 }
2597
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002598 int dup_stdout_fd;
2599 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002600 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002601 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002602 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002603 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2604 return ERROR;
2605 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002606 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2607 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2608 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002609 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002610
2611 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2612 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002613 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002614 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002615 /* TODO: rather than generating a text file now and zipping it later,
2616 it would be more efficient to redirect stdout to the zip entry
2617 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002618 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2619 return ERROR;
2620 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002621 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002622 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002623 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002624 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002625 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002626
2627 // Don't buffer stdout
2628 setvbuf(stdout, nullptr, _IONBF, 0);
2629
Felipe Leme608385d2016-02-01 10:35:38 -08002630 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2631 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002632 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002633 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002634
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002635 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002636 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002637 DumpstateBoard();
2638 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002639 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002640 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002641 // Dump state for the default case. This also drops root.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002642 RunStatus s = DumpstateDefault();
2643 if (s != RunStatus::OK) {
2644 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2645 HandleUserConsentDenied();
2646 }
2647 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002648 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002649 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002650
Felipe Leme55b42a62015-11-10 17:39:08 -08002651 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002652 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002653 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002654 }
2655
Nandana Duttd2f5f082019-01-18 17:13:52 +00002656 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002657 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002658 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002659 }
2660
Nandana Duttd2f5f082019-01-18 17:13:52 +00002661 // Share the final file with the caller if the user has consented.
2662 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2663 if (options_->bugreport_fd.get() != -1) {
2664 status = CopyBugreportIfUserConsented();
2665 if (status != Dumpstate::RunStatus::OK &&
2666 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2667 // Do an early return if there were errors. We make an exception for consent
2668 // timing out because it's possible the user got distracted. In this case the
2669 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002670 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002671 return status;
2672 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002673 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002674 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2675 options_->screenshot_fd.get());
2676 if (copy_succeeded) {
2677 android::os::UnlinkAndLogOnError(screenshot_path_);
2678 }
2679 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002680 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2681 MYLOGI(
2682 "Did not receive user consent yet."
2683 " Will not copy the bugreport artifacts to caller.\n");
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002684 // TODO(b/111441001): cancel outstanding requests
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002685 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002686 }
2687
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002688 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002689 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002690 for (int i = 0; i < 3; i++) {
2691 Vibrate(75);
2692 usleep((75 + 50) * 1000);
2693 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002694 }
2695
Jeff Brown1dc94e32014-09-11 14:15:27 -07002696 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002697 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002698 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002699 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002700 }
2701
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002702 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2703 progress_->GetInitialMax());
2704 progress_->Save();
2705 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002706
Felipe Leme107a05f2016-03-08 15:11:15 -08002707 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002708 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002709 }
2710
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002711 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002712 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002713 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002714 }
2715
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002716 tombstone_data_.clear();
2717 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002718
Nandana Duttd2f5f082019-01-18 17:13:52 +00002719 return (consent_callback_ != nullptr &&
2720 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2721 ? USER_CONSENT_TIMED_OUT
2722 : RunStatus::OK;
2723}
2724
2725void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2726 consent_callback_ = new ConsentCallback();
2727 const String16 incidentcompanion("incidentcompanion");
2728 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2729 if (ics != nullptr) {
2730 MYLOGD("Checking user consent via incidentcompanion service\n");
2731 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2732 calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
2733 consent_callback_.get());
2734 } else {
2735 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2736 }
2737}
2738
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002739bool Dumpstate::IsUserConsentDenied() const {
2740 return ds.consent_callback_ != nullptr &&
2741 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2742}
2743
Nandana Duttd2f5f082019-01-18 17:13:52 +00002744void Dumpstate::CleanupFiles() {
2745 android::os::UnlinkAndLogOnError(tmp_path_);
2746 android::os::UnlinkAndLogOnError(screenshot_path_);
2747 android::os::UnlinkAndLogOnError(path_);
2748}
2749
2750Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2751 MYLOGD("User denied consent; deleting files and returning\n");
2752 CleanupFiles();
2753 return USER_CONSENT_DENIED;
2754}
2755
2756Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2757 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2758 // user consent.
2759 UserConsentResult consent_result = consent_callback_->getResult();
2760 if (consent_result == UserConsentResult::UNAVAILABLE) {
2761 // User has not responded yet.
2762 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2763 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2764 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2765 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2766 sleep(delay_seconds);
2767 }
2768 consent_result = consent_callback_->getResult();
2769 }
2770 if (consent_result == UserConsentResult::DENIED) {
2771 // User has explicitly denied sharing with the app. To be safe delete the
2772 // internal bugreport & tmp files.
2773 return HandleUserConsentDenied();
2774 }
2775 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002776 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2777 if (copy_succeeded) {
2778 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002779 }
2780 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2781 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2782 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2783 // Since we do not have user consent to share the bugreport it does not get
2784 // copied over to the calling app but remains in the internal directory from
2785 // where the user can manually pull it.
2786 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2787 }
2788 // Unknown result; must be a programming error.
2789 MYLOGE("Unknown user consent result:%d\n", consent_result);
2790 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002791}
2792
Nandana Duttf02564e2019-02-15 15:24:24 +00002793Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002794 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2795 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2796 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002797 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002798 // When directly running dumpstate binary, the output is not expected to be written
2799 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002800 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002801
2802 // calling_uid and calling_package are for user consent to share the bugreport with
2803 // an app; they are irrelvant here because bugreport is only written to a local
2804 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002805 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002806 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002807 return status;
2808}
2809
2810/* Main entry point for dumpstate binary. */
2811int run_main(int argc, char* argv[]) {
2812 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002813
2814 switch (status) {
2815 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002816 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002817 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002818 ShowUsage();
2819 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002820 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002821 fprintf(stderr, "Invalid combination of args\n");
2822 ShowUsage();
2823 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002824 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002825 FALLTHROUGH_INTENDED;
2826 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2827 FALLTHROUGH_INTENDED;
2828 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002829 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002830 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002831}