blob: a32fffdcbbe521a78406f960d4cd13805d71e63b [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
1498 // Invoking the following dumpsys calls before dump_traces() to try and
1499 // 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 Duttbbdb5b42019-03-12 10:52:56 +00001503 // TODO(128270426): Refactor to take output argument and wrap in
1504 // RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK.
Nandana Duttfaafd522019-03-11 09:23:09 +00001505 dump_traces_path = ds.DumpTraces();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001506
1507 /* Run some operations that require root. */
1508 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1509 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1510
1511 ds.AddDir(RECOVERY_DIR, true);
1512 ds.AddDir(RECOVERY_DATA_DIR, true);
1513 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1514 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1515 if (!PropertiesHelper::IsUserBuild()) {
1516 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1517 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1518 }
1519 add_mountinfo();
1520 DumpIpTablesAsRoot();
1521
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001522 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001523 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1524
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001525 // Dump IPsec stats. No keys are exposed here.
1526 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1527
Nandana Dutt4be45d12018-09-26 15:04:23 +01001528 // Run ss as root so we can see socket marks.
1529 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1530
1531 // Run iotop as root to show top 100 IO threads
1532 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1533
Erick Reyese68df822019-02-11 14:46:36 -08001534 // Gather shared memory buffer info if the product implements it
1535 struct stat st;
1536 if (!stat("/product/bin/dmabuf_dump", &st)) {
1537 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1538 }
1539
Nandana Dutt4be45d12018-09-26 15:04:23 +01001540 if (!DropRootUser()) {
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001541 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001542 }
1543
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001544 RETURN_IF_USER_DENIED_CONSENT();
1545 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001546}
1547
mukesh agrawal253dad42018-01-23 21:59:59 -08001548// This method collects common dumpsys for telephony and wifi
1549static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001550 DumpIpTablesAsRoot();
1551
1552 if (!DropRootUser()) {
1553 return;
1554 }
1555
1556 do_dmesg();
1557 DoLogcat();
1558 DumpPacketStats();
1559 DoKmsg();
1560 DumpIpAddrAndRules();
1561 dump_route_tables();
1562
1563 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1564 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001565}
1566
1567// This method collects dumpsys for telephony debugging only
1568static void DumpstateTelephonyOnly() {
1569 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001570 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001571
1572 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001573
1574 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1575
1576 printf("========================================================\n");
1577 printf("== Android Framework Services\n");
1578 printf("========================================================\n");
1579
Vishnu Nair652cc802017-11-30 15:18:30 -08001580 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1581 SEC_TO_MSEC(10));
1582 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1583 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001584 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1585 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001586 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1587 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001588
1589 printf("========================================================\n");
1590 printf("== Running Application Services\n");
1591 printf("========================================================\n");
1592
1593 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1594
1595 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001596 printf("== Running Application Services (non-platform)\n");
1597 printf("========================================================\n");
1598
1599 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1600 DUMPSYS_COMPONENTS_OPTIONS);
1601
1602 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001603 printf("== Checkins\n");
1604 printf("========================================================\n");
1605
1606 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1607
1608 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001609 printf("== dumpstate: done (id %d)\n", ds.id_);
1610 printf("========================================================\n");
1611}
1612
mukesh agrawal253dad42018-01-23 21:59:59 -08001613// This method collects dumpsys for wifi debugging only
1614static void DumpstateWifiOnly() {
1615 DurationReporter duration_reporter("DUMPSTATE");
1616
1617 DumpstateRadioCommon();
1618
1619 printf("========================================================\n");
1620 printf("== Android Framework Services\n");
1621 printf("========================================================\n");
1622
1623 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1624 SEC_TO_MSEC(10));
1625 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1626 SEC_TO_MSEC(10));
1627
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001628 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001629
mukesh agrawal253dad42018-01-23 21:59:59 -08001630 printf("========================================================\n");
1631 printf("== dumpstate: done (id %d)\n", ds.id_);
1632 printf("========================================================\n");
1633}
1634
Nandana Duttfaafd522019-03-11 09:23:09 +00001635const char* Dumpstate::DumpTraces() {
1636 DurationReporter duration_reporter("DUMP TRACES");
1637
1638 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1639 const size_t buf_size = temp_file_pattern.length() + 1;
1640 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1641 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1642
1643 // Create a new, empty file to receive all trace dumps.
1644 //
1645 // TODO: This can be simplified once we remove support for the old style
1646 // dumps. We can have a file descriptor passed in to dump_traces instead
1647 // of creating a file, closing it and then reopening it again.
1648 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1649 if (fd < 0) {
1650 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
1651 return nullptr;
1652 }
1653
1654 // Nobody should have access to this temporary file except dumpstate, but we
1655 // temporarily grant 'read' to 'others' here because this file is created
1656 // when tombstoned is still running as root, but dumped after dropping. This
1657 // can go away once support for old style dumping has.
1658 const int chmod_ret = fchmod(fd, 0666);
1659 if (chmod_ret < 0) {
1660 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
1661 return nullptr;
1662 }
1663
1664 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1665 if (proc.get() == nullptr) {
1666 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
1667 return nullptr;
1668 }
1669
1670 // Number of times process dumping has timed out. If we encounter too many
1671 // failures, we'll give up.
1672 int timeout_failures = 0;
1673 bool dalvik_found = false;
1674
1675 const std::set<int> hal_pids = get_interesting_hal_pids();
1676
1677 struct dirent* d;
1678 while ((d = readdir(proc.get()))) {
1679 int pid = atoi(d->d_name);
1680 if (pid <= 0) {
1681 continue;
1682 }
1683
1684 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1685 std::string exe;
1686 if (!android::base::Readlink(link_name, &exe)) {
1687 continue;
1688 }
1689
1690 bool is_java_process;
1691 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1692 // Don't bother dumping backtraces for the zygote.
1693 if (IsZygote(pid)) {
1694 continue;
1695 }
1696
1697 dalvik_found = true;
1698 is_java_process = true;
1699 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1700 is_java_process = false;
1701 } else {
1702 // Probably a native process we don't care about, continue.
1703 continue;
1704 }
1705
1706 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1707 if (timeout_failures == 3) {
1708 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1709 break;
1710 }
1711
1712 const uint64_t start = Nanotime();
1713 const int ret = dump_backtrace_to_file_timeout(
1714 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1715 is_java_process ? 5 : 20, fd);
1716
1717 if (ret == -1) {
1718 // For consistency, the header and footer to this message match those
1719 // dumped by debuggerd in the success case.
1720 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1721 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1722 dprintf(fd, "---- end %d ----", pid);
1723 timeout_failures++;
1724 continue;
1725 }
1726
1727 // We've successfully dumped stack traces, reset the failure count
1728 // and write a summary of the elapsed time to the file and continue with the
1729 // next process.
1730 timeout_failures = 0;
1731
1732 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1733 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1734 }
1735
1736 if (!dalvik_found) {
1737 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1738 }
1739
1740 return file_name_buf.release();
1741}
1742
Felipe Leme6f674ae2016-11-18 17:10:33 -08001743void Dumpstate::DumpstateBoard() {
1744 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001745 printf("========================================================\n");
1746 printf("== Board\n");
1747 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001748
Felipe Leme6f674ae2016-11-18 17:10:33 -08001749 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001750 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001751 return;
1752 }
1753
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001754 std::vector<std::string> paths;
1755 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001756 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001757 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1758 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001759 remover.emplace_back(android::base::make_scope_guard(
1760 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001761 }
Jie Song9fbfad02017-06-20 16:29:42 -07001762
Wei Wang587eac92018-04-05 12:17:20 -07001763 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1764 if (dumpstate_device == nullptr) {
1765 MYLOGE("No IDumpstateDevice implementation\n");
1766 return;
1767 }
1768
1769 using ScopedNativeHandle =
1770 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1771 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1772 [](native_handle_t* handle) {
1773 native_handle_close(handle);
1774 native_handle_delete(handle);
1775 });
1776 if (handle == nullptr) {
1777 MYLOGE("Could not create native_handle\n");
1778 return;
1779 }
1780
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001781 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001782 for (size_t i = 0; i < paths.size(); i++) {
1783 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1784
1785 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1786 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1787 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1788 if (fd < 0) {
1789 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1790 return;
1791 }
1792 handle.get()->data[i] = fd.release();
1793 }
1794
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001795 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001796 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1797 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1798 // and grab whatever dumped
1799 std::packaged_task<bool()>
1800 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001801 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1802 if (!status.isOk()) {
1803 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001804 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001805 }
Wei Wang587eac92018-04-05 12:17:20 -07001806 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001807 });
Wei Wang587eac92018-04-05 12:17:20 -07001808
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001809 auto result = dumpstate_task.get_future();
1810 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001811
1812 constexpr size_t timeout_sec = 30;
1813 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1814 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1815 if (!android::base::SetProperty("ctl.interface_restart",
1816 android::base::StringPrintf("%s/default",
1817 IDumpstateDevice::descriptor))) {
1818 MYLOGE("Couldn't restart dumpstate HAL\n");
1819 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001820 }
Wei Wang587eac92018-04-05 12:17:20 -07001821 // Wait some time for init to kill dumpstate vendor HAL
1822 constexpr size_t killing_timeout_sec = 10;
1823 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1824 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1825 "there might be racing in content\n", killing_timeout_sec);
1826 }
1827
1828 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1829 for (size_t i = 0; i < paths.size(); i++) {
1830 struct stat s;
1831 if (fstat(handle.get()->data[i], &s) == -1) {
1832 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1833 strerror(errno));
1834 file_sizes[i] = -1;
1835 continue;
1836 }
1837 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001838 }
1839
1840 for (size_t i = 0; i < paths.size(); i++) {
1841 if (file_sizes[i] == -1) {
1842 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001843 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001844 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001845 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001846 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001847 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001848 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001849 }
1850
Felipe Lemed8b94e52016-12-08 10:21:44 -08001851 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001852}
1853
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001854static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001855 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001856 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001857 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1858 " -h: display this help message\n"
1859 " -b: play sound file instead of vibrate, at beginning of job\n"
1860 " -e: play sound file instead of vibrate, at end of job\n"
1861 " -o: write to file (instead of stdout)\n"
1862 " -d: append date to filename (requires -o)\n"
1863 " -p: capture screenshot to filename.png (requires -o)\n"
1864 " -z: generate zipped file (requires -o)\n"
1865 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001866 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001867 " -q: disable vibrate\n"
1868 " -B: send broadcast when finished (requires -o)\n"
1869 " -P: send broadcast when started and update system properties on "
1870 "progress (requires -o and -B)\n"
1871 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1872 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001873 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001874 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001875}
1876
Wei Liuf87959e2016-08-26 14:51:42 -07001877static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001878 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001879}
1880
Felipe Leme1d486fe2016-10-14 18:06:47 -07001881bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001882 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001883 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001884 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001885 // Final timestamp
1886 char date[80];
1887 time_t the_real_now_please_stand_up = time(nullptr);
1888 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001889 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001890 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001891
Felipe Leme9a523ae2016-10-20 15:10:33 -07001892 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001893 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001894 return false;
1895 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001896 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001897 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001898 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001899 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001900
Felipe Leme0f3fb202016-06-10 17:10:53 -07001901 // Add log file (which contains stderr output) to zip...
1902 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001903 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001904 MYLOGE("Failed to add dumpstate log to .zip file\n");
1905 return false;
1906 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001907 // TODO: Should truncate the existing file.
1908 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001909 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1910 return false;
1911 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001912 fprintf(stderr, "\n");
1913
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001914 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001915 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001916 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001917 return false;
1918 }
1919
Felipe Leme1d486fe2016-10-14 18:06:47 -07001920 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1921 ds.zip_file.reset(nullptr);
1922
Felipe Lemee9d2c542016-11-15 11:48:26 -08001923 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001924 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001925
Felipe Leme1e9edc62015-12-21 16:02:13 -08001926 return true;
1927}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001928
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001929static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001930 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1931 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001932 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001933 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001934 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001935 }
1936
1937 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001938 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001939
1940 std::vector<uint8_t> buffer(65536);
1941 while (1) {
1942 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1943 if (bytes_read == 0) {
1944 break;
1945 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001946 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001947 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001948 }
1949
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001950 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001951 }
1952
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001953 uint8_t hash[SHA256_DIGEST_LENGTH];
1954 SHA256_Final(hash, &ctx);
1955
1956 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1957 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001958 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001959 }
1960 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1961 return std::string(hash_buffer);
1962}
1963
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001964static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1965 // clang-format off
1966 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1967 "--receiver-foreground", "--receiver-include-background", "-a", action};
1968 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001969
1970 am.insert(am.end(), args.begin(), args.end());
1971
Felipe Leme8d2410e2017-02-08 09:46:08 -08001972 RunCommand("", am,
1973 CommandOptions::WithTimeout(20)
1974 .Log("Sending broadcast: '%s'\n")
1975 .Always()
1976 .DropRoot()
1977 .RedirectStderr()
1978 .Build());
1979}
1980
Felipe Leme35b8cf12017-02-10 15:47:29 -08001981static void Vibrate(int duration_ms) {
1982 // clang-format off
1983 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1984 CommandOptions::WithTimeout(10)
1985 .Log("Vibrate: '%s'\n")
1986 .Always()
1987 .Build());
1988 // clang-format on
1989}
1990
Nandana Dutt979388e2018-11-30 16:48:55 +00001991static void MaybeResolveSymlink(std::string* path) {
1992 std::string resolved_path;
1993 if (android::base::Readlink(*path, &resolved_path)) {
1994 *path = resolved_path;
1995 }
1996}
1997
Nandana Dutt4be45d12018-09-26 15:04:23 +01001998/*
1999 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2000 * if we are writing zip files and adds the version file.
2001 */
2002static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002003 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2004
Nandana Dutt4be45d12018-09-26 15:04:23 +01002005 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2006 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002007 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002008 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002009 char date[80];
2010 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2011 ds.name_ = date;
2012 } else {
2013 ds.name_ = "undated";
2014 }
2015
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002016 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002017 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002018 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002019 ds.base_name_ += "-wifi";
2020 }
2021
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002022 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002023 ds.screenshot_path_ = ds.GetPath(".png");
2024 }
2025 ds.tmp_path_ = ds.GetPath(".tmp");
2026 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2027
Nandana Dutt54dbd672019-01-11 12:58:05 +00002028 std::string destination = ds.options_->bugreport_fd.get() != -1
2029 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002030 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002031 MYLOGD(
2032 "Bugreport dir: %s\n"
2033 "Base name: %s\n"
2034 "Suffix: %s\n"
2035 "Log path: %s\n"
2036 "Temporary path: %s\n"
2037 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002038 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2039 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002040
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002041 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002042 ds.path_ = ds.GetPath(".zip");
2043 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2044 create_parent_dirs(ds.path_.c_str());
2045 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2046 if (ds.zip_file == nullptr) {
2047 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2048 } else {
2049 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2050 }
2051 ds.AddTextZipEntry("version.txt", ds.version_);
2052 }
2053}
2054
2055/*
2056 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2057 * printing zipped file status, etc.
2058 */
2059static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002060 /* check if user changed the suffix using system properties */
2061 std::string name =
2062 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2063 bool change_suffix = false;
2064 if (!name.empty()) {
2065 /* must whitelist which characters are allowed, otherwise it could cross directories */
2066 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2067 if (std::regex_match(name.c_str(), valid_regex)) {
2068 change_suffix = true;
2069 } else {
2070 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2071 }
2072 }
2073 if (change_suffix) {
2074 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2075 ds.name_ = name;
2076 if (!ds.screenshot_path_.empty()) {
2077 std::string new_screenshot_path = ds.GetPath(".png");
2078 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2079 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2080 new_screenshot_path.c_str(), strerror(errno));
2081 } else {
2082 ds.screenshot_path_ = new_screenshot_path;
2083 }
2084 }
2085 }
2086
2087 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002088 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002089 if (!ds.FinishZipFile()) {
2090 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2091 do_text_file = true;
2092 } else {
2093 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002094 // If the user has changed the suffix, we need to change the zip file name.
2095 std::string new_path = ds.GetPath(".zip");
2096 if (ds.path_ != new_path) {
2097 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2098 if (rename(ds.path_.c_str(), new_path.c_str())) {
2099 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2100 strerror(errno));
2101 } else {
2102 ds.path_ = new_path;
2103 }
2104 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002105 }
2106 }
2107 if (do_text_file) {
2108 ds.path_ = ds.GetPath(".txt");
2109 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2110 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2111 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2112 ds.path_.clear();
2113 }
2114 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002115 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002116 if (do_text_file) {
2117 dprintf(ds.control_socket_fd_,
2118 "FAIL:could not create zip file, check %s "
2119 "for more details\n",
2120 ds.log_path_.c_str());
2121 } else {
2122 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2123 }
2124 }
2125}
2126
2127/* Broadcasts that we are done with the bugreport */
2128static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002129 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002130 if (!ds.path_.empty()) {
2131 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002132 // clang-format off
2133
2134 std::vector<std::string> am_args = {
2135 "--receiver-permission", "android.permission.DUMP",
2136 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2137 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2138 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002139 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002140 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2141 };
2142 // clang-format on
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002143 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002144 am_args.push_back("--es");
2145 am_args.push_back("android.intent.extra.SCREENSHOT");
2146 am_args.push_back(ds.screenshot_path_);
2147 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002148 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002149 am_args.push_back("--es");
2150 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002151 am_args.push_back(ds.options_->notification_title);
2152 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002153 am_args.push_back("--es");
2154 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002155 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002156 }
2157 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002158 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002159 am_args.push_back("--es");
2160 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002161 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002162 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2163 } else {
2164 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2165 }
2166 } else {
2167 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2168 }
2169}
2170
Nandana Dutt58d72e22018-11-16 10:30:48 +00002171static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2172 switch (mode) {
2173 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2174 return "BUGREPORT_FULL";
2175 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2176 return "BUGREPORT_INTERACTIVE";
2177 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2178 return "BUGREPORT_REMOTE";
2179 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2180 return "BUGREPORT_WEAR";
2181 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2182 return "BUGREPORT_TELEPHONY";
2183 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2184 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002185 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2186 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002187 }
2188}
2189
2190static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002191 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002192 switch (mode) {
2193 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2194 options->do_broadcast = true;
2195 options->do_fb = true;
2196 break;
2197 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002198 // Currently, the dumpstate binder is only used by Shell to update progress.
2199 options->do_start_service = true;
2200 options->do_progress_updates = true;
2201 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002202 options->do_broadcast = true;
2203 break;
2204 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002205 options->do_vibrate = false;
2206 options->is_remote_mode = true;
2207 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002208 options->do_broadcast = true;
2209 break;
2210 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002211 options->do_start_service = true;
2212 options->do_progress_updates = true;
2213 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002214 options->do_fb = true;
2215 options->do_broadcast = true;
2216 break;
2217 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002218 options->telephony_only = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002219 options->do_fb = true;
2220 options->do_broadcast = true;
2221 break;
2222 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002223 options->wifi_only = true;
2224 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002225 options->do_fb = true;
2226 options->do_broadcast = true;
2227 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002228 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2229 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002230 }
2231}
2232
2233static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002234 // If the system property is not set, it's assumed to be a default bugreport.
2235 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002236
2237 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2238 if (!extra_options.empty()) {
2239 // Framework uses a system property to override some command-line args.
2240 // Currently, it contains the type of the requested bugreport.
2241 if (extra_options == "bugreportplus") {
2242 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002243 } else if (extra_options == "bugreportfull") {
2244 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002245 } else if (extra_options == "bugreportremote") {
2246 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2247 } else if (extra_options == "bugreportwear") {
2248 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2249 } else if (extra_options == "bugreporttelephony") {
2250 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2251 } else if (extra_options == "bugreportwifi") {
2252 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002253 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002254 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002255 }
2256 // Reset the property
2257 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2258 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002259 return mode;
2260}
2261
2262// TODO: Move away from system properties when we have options passed via binder calls.
2263/* Sets runtime options from the system properties and then clears those properties. */
2264static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2265 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2266 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002267
2268 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2269 if (!options->notification_title.empty()) {
2270 // Reset the property
2271 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2272
Nandana Duttdd8cca32018-11-14 10:10:29 +00002273 options->notification_description =
2274 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002275 if (!options->notification_description.empty()) {
2276 // Reset the property
2277 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2278 }
2279 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2280 options->notification_description.c_str());
2281 }
2282}
2283
Nandana Dutt58d72e22018-11-16 10:30:48 +00002284static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2285 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2286 MYLOGI("do_add_date: %d\n", options.do_add_date);
2287 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2288 MYLOGI("use_socket: %d\n", options.use_socket);
2289 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2290 MYLOGI("do_fb: %d\n", options.do_fb);
2291 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2292 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2293 MYLOGI("show_header_only: %d\n", options.show_header_only);
2294 MYLOGI("do_start_service: %d\n", options.do_start_service);
2295 MYLOGI("telephony_only: %d\n", options.telephony_only);
2296 MYLOGI("wifi_only: %d\n", options.wifi_only);
2297 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002298 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002299 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2300 MYLOGI("args: %s\n", options.args.c_str());
2301 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2302 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2303}
2304
Nandana Dutt54dbd672019-01-11 12:58:05 +00002305void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2306 const android::base::unique_fd& bugreport_fd_in,
2307 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002308 // In the new API world, date is always added; output is always a zip file.
2309 // TODO(111441001): remove these options once they are obsolete.
2310 do_add_date = true;
2311 do_zip_file = true;
2312
Nandana Dutt54dbd672019-01-11 12:58:05 +00002313 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2314 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2315 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002316
2317 extra_options = ModeToString(bugreport_mode);
2318 SetOptionsFromMode(bugreport_mode, this);
2319}
2320
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002321Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2322 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002323 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002324 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002325 switch (c) {
2326 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002327 case 'd': do_add_date = true; break;
2328 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002329 // o=use_outfile not supported anymore.
2330 // TODO(b/111441001): Remove when all callers have migrated.
2331 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002332 case 's': use_socket = true; break;
2333 case 'S': use_control_socket = true; break;
2334 case 'v': show_header_only = true; break;
2335 case 'q': do_vibrate = false; break;
2336 case 'p': do_fb = true; break;
2337 case 'P': do_progress_updates = true; break;
2338 case 'R': is_remote_mode = true; break;
2339 case 'B': do_broadcast = true; break;
2340 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002341 case 'w':
2342 // This was already processed
2343 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002344 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002345 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002346 break;
2347 default:
2348 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002349 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002350 break;
2351 // clang-format on
2352 }
2353 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002354
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002355 // TODO: use helper function to convert argv into a string
2356 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002357 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002358 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002359 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002360 }
2361 }
2362
2363 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2364 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002365
2366 SetOptionsFromProperties(this);
2367 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002368}
2369
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002370bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002371 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002372 return false;
2373 }
2374
Nandana Dutt9a76d202019-01-21 15:56:48 +00002375 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002376 return false;
2377 }
2378
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002379 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002380 return false;
2381 }
2382
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002383 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002384 return false;
2385 }
2386
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002387 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002388 return false;
2389 }
2390 return true;
2391}
2392
Nandana Dutt197661d2018-11-16 16:40:21 +00002393void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2394 options_ = std::move(options);
2395}
2396
Nandana Duttd2f5f082019-01-18 17:13:52 +00002397Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2398 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002399 if (listener_ != nullptr) {
2400 switch (status) {
2401 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002402 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002403 break;
2404 case Dumpstate::RunStatus::HELP:
2405 break;
2406 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002407 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002408 break;
2409 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002410 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2411 break;
2412 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2413 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2414 break;
2415 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2416 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002417 break;
2418 }
2419 }
2420 return status;
2421}
2422
Nandana Dutt979388e2018-11-30 16:48:55 +00002423/*
2424 * Dumps relevant information to a bugreport based on the given options.
2425 *
2426 * The bugreport can be dumped to a file or streamed to a socket.
2427 *
2428 * How dumping to file works:
2429 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2430 * stderr is redirected a log file.
2431 *
2432 * The temporary bugreport is then populated via printfs, dumping contents of files and
2433 * output of commands to stdout.
2434 *
2435 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2436 * text file.
2437 *
2438 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2439 * gets added to the archive.
2440 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002441 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2442 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002443 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002444Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2445 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002446 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002447 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002448 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002449 return RunStatus::INVALID_INPUT;
2450 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002451 /* set as high priority, and protect from OOM killer */
2452 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002453
Felipe Lemed071c682016-10-20 16:48:00 -07002454 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002455 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002456 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002457 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002458 } else {
2459 /* fallback to kernels <= 2.6.35 */
2460 oom_adj = fopen("/proc/self/oom_adj", "we");
2461 if (oom_adj) {
2462 fputs("-17", oom_adj);
2463 fclose(oom_adj);
2464 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002465 }
2466
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002467 if (version_ == VERSION_DEFAULT) {
2468 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002469 }
2470
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002471 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002472 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002473 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002474 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002475 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002476 }
2477
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002478 if (options_->show_header_only) {
2479 PrintHeader();
2480 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002481 }
2482
Nandana Duttd2f5f082019-01-18 17:13:52 +00002483 if (options_->bugreport_fd.get() != -1) {
2484 // If the output needs to be copied over to the caller's fd, get user consent.
2485 android::String16 package(calling_package.c_str());
2486 CheckUserConsent(calling_uid, package);
2487 }
2488
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002489 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002490 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002491
2492 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002493 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002494 is_redirecting
2495 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2496 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002497 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002498
Felipe Lemed071c682016-10-20 16:48:00 -07002499 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002500 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002501 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002502 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2503
2504 MYLOGI("begin\n");
2505
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002506 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002507
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002508 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002509 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002510 MYLOGI("Starting 'dumpstate' service\n");
2511 android::status_t ret;
2512 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2513 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2514 }
2515 }
2516
Felipe Lemef0292972016-11-22 13:57:05 -08002517 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002518 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2519 }
2520
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002521 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2522 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002523
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002524 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002525
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002526 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002527
Christopher Ferrised9354f2014-10-01 17:35:01 -07002528 // If we are going to use a socket, do it as early as possible
2529 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002530 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002531 if (!redirect_to_socket(stdout, "dumpstate")) {
2532 return ERROR;
2533 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002534 }
2535
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002536 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002537 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002538 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002539 if (control_socket_fd_ == -1) {
2540 return ERROR;
2541 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002542 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002543 }
2544
Felipe Leme71bbfc52015-11-23 14:14:51 -08002545 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002546 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002547
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002548 if (options_->do_progress_updates) {
2549 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002550 // clang-format off
2551 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002552 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002553 "--es", "android.intent.extra.NAME", name_,
2554 "--ei", "android.intent.extra.ID", std::to_string(id_),
2555 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2556 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002557 };
2558 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002559 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002560 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002561 if (options_->use_control_socket) {
2562 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002563 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002564 }
2565 }
2566
Nick Kralevichf3599b32016-01-25 15:05:16 -08002567 /* read /proc/cmdline before dropping root */
2568 FILE *cmdline = fopen("/proc/cmdline", "re");
2569 if (cmdline) {
2570 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2571 fclose(cmdline);
2572 }
2573
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002574 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002575 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002576 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002577
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002578 if (options_->do_fb && do_early_screenshot_) {
2579 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002580 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002581 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002582 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002583 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002584 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002585 }
2586 }
2587
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002588 if (options_->do_zip_file && zip_file != nullptr) {
2589 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2590 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002591 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002592 }
2593 }
2594
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002595 int dup_stdout_fd;
2596 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002597 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002598 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002599 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002600 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2601 return ERROR;
2602 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002603 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2604 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2605 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002606 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002607
2608 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2609 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002610 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002611 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002612 /* TODO: rather than generating a text file now and zipping it later,
2613 it would be more efficient to redirect stdout to the zip entry
2614 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002615 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2616 return ERROR;
2617 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002618 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002619 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002620 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002621 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002622 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002623
2624 // Don't buffer stdout
2625 setvbuf(stdout, nullptr, _IONBF, 0);
2626
Felipe Leme608385d2016-02-01 10:35:38 -08002627 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2628 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002629 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002630 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002631
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002632 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002633 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002634 DumpstateBoard();
2635 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002636 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002637 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002638 // Dump state for the default case. This also drops root.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002639 RunStatus s = DumpstateDefault();
2640 if (s != RunStatus::OK) {
2641 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2642 HandleUserConsentDenied();
2643 }
2644 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002645 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002646 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002647
Felipe Leme55b42a62015-11-10 17:39:08 -08002648 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002649 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002650 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002651 }
2652
Nandana Duttd2f5f082019-01-18 17:13:52 +00002653 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002654 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002655 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002656 }
2657
Nandana Duttd2f5f082019-01-18 17:13:52 +00002658 // Share the final file with the caller if the user has consented.
2659 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2660 if (options_->bugreport_fd.get() != -1) {
2661 status = CopyBugreportIfUserConsented();
2662 if (status != Dumpstate::RunStatus::OK &&
2663 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2664 // Do an early return if there were errors. We make an exception for consent
2665 // timing out because it's possible the user got distracted. In this case the
2666 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002667 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002668 return status;
2669 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002670 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002671 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2672 options_->screenshot_fd.get());
2673 if (copy_succeeded) {
2674 android::os::UnlinkAndLogOnError(screenshot_path_);
2675 }
2676 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002677 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2678 MYLOGI(
2679 "Did not receive user consent yet."
2680 " Will not copy the bugreport artifacts to caller.\n");
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002681 // TODO(b/111441001): cancel outstanding requests
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002682 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002683 }
2684
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002685 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002686 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002687 for (int i = 0; i < 3; i++) {
2688 Vibrate(75);
2689 usleep((75 + 50) * 1000);
2690 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002691 }
2692
Jeff Brown1dc94e32014-09-11 14:15:27 -07002693 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002694 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002695 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002696 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002697 }
2698
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002699 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2700 progress_->GetInitialMax());
2701 progress_->Save();
2702 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002703
Felipe Leme107a05f2016-03-08 15:11:15 -08002704 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002705 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002706 }
2707
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002708 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002709 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002710 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002711 }
2712
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002713 tombstone_data_.clear();
2714 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002715
Nandana Duttd2f5f082019-01-18 17:13:52 +00002716 return (consent_callback_ != nullptr &&
2717 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2718 ? USER_CONSENT_TIMED_OUT
2719 : RunStatus::OK;
2720}
2721
2722void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2723 consent_callback_ = new ConsentCallback();
2724 const String16 incidentcompanion("incidentcompanion");
2725 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2726 if (ics != nullptr) {
2727 MYLOGD("Checking user consent via incidentcompanion service\n");
2728 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2729 calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
2730 consent_callback_.get());
2731 } else {
2732 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2733 }
2734}
2735
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002736bool Dumpstate::IsUserConsentDenied() const {
2737 return ds.consent_callback_ != nullptr &&
2738 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2739}
2740
Nandana Duttd2f5f082019-01-18 17:13:52 +00002741void Dumpstate::CleanupFiles() {
2742 android::os::UnlinkAndLogOnError(tmp_path_);
2743 android::os::UnlinkAndLogOnError(screenshot_path_);
2744 android::os::UnlinkAndLogOnError(path_);
2745}
2746
2747Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2748 MYLOGD("User denied consent; deleting files and returning\n");
2749 CleanupFiles();
2750 return USER_CONSENT_DENIED;
2751}
2752
2753Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2754 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2755 // user consent.
2756 UserConsentResult consent_result = consent_callback_->getResult();
2757 if (consent_result == UserConsentResult::UNAVAILABLE) {
2758 // User has not responded yet.
2759 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2760 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2761 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2762 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2763 sleep(delay_seconds);
2764 }
2765 consent_result = consent_callback_->getResult();
2766 }
2767 if (consent_result == UserConsentResult::DENIED) {
2768 // User has explicitly denied sharing with the app. To be safe delete the
2769 // internal bugreport & tmp files.
2770 return HandleUserConsentDenied();
2771 }
2772 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002773 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2774 if (copy_succeeded) {
2775 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002776 }
2777 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2778 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2779 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2780 // Since we do not have user consent to share the bugreport it does not get
2781 // copied over to the calling app but remains in the internal directory from
2782 // where the user can manually pull it.
2783 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2784 }
2785 // Unknown result; must be a programming error.
2786 MYLOGE("Unknown user consent result:%d\n", consent_result);
2787 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002788}
2789
Nandana Duttf02564e2019-02-15 15:24:24 +00002790Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002791 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2792 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2793 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002794 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002795 // When directly running dumpstate binary, the output is not expected to be written
2796 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002797 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002798
2799 // calling_uid and calling_package are for user consent to share the bugreport with
2800 // an app; they are irrelvant here because bugreport is only written to a local
2801 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002802 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002803 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002804 return status;
2805}
2806
2807/* Main entry point for dumpstate binary. */
2808int run_main(int argc, char* argv[]) {
2809 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002810
2811 switch (status) {
2812 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002813 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002814 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002815 ShowUsage();
2816 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002817 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002818 fprintf(stderr, "Invalid combination of args\n");
2819 ShowUsage();
2820 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002821 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002822 FALLTHROUGH_INTENDED;
2823 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2824 FALLTHROUGH_INTENDED;
2825 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002826 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002827 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002828}