blob: 08fd2eb2df34f1fcb5780c082966fc2ef59a8771 [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>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070037#include <cmath>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000038#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070039#include <functional>
40#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010041#include <memory>
Hridya Valsarajuac582cd2019-08-05 15:39:54 -070042#include <numeric>
Narayan Kamath8f788292017-05-25 13:20:39 +010043#include <regex>
44#include <set>
45#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070046#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010047#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070048
Felipe Leme96c2bbb2016-09-26 09:21:21 -070049#include <android-base/file.h>
50#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070051#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080052#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070053#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070054#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080055#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080056#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000057#include <android/os/IIncidentCompanion.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080058#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070059#include <cutils/properties.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000060#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080061#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000062#include <dumputils/dump_utils.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080063#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070064#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070065#include <private/android_filesystem_config.h>
66#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080067#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070068#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080069#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080070#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070071#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070072#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080073
Steven Morelandcb7ef822016-11-29 13:20:37 -080074using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080075using ::std::literals::chrono_literals::operator""ms;
76using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080077
Felipe Leme47e9be22016-12-21 15:37:07 -080078// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080079using android::defaultServiceManager;
80using android::Dumpsys;
81using android::INVALID_OPERATION;
82using android::IServiceManager;
83using android::OK;
84using android::sp;
85using android::status_t;
86using android::String16;
87using android::String8;
88using android::TIMED_OUT;
89using android::UNKNOWN_ERROR;
90using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +000091using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +000092using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -080093using android::os::dumpstate::CommandOptions;
94using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080095using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080096using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080097using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080098
Nandana Duttd2f5f082019-01-18 17:13:52 +000099typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
100
Colin Crossf45fa6b2012-03-26 12:38:26 -0700101/* read before root is shed */
102static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700103static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000104static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700105
Felipe Leme1d486fe2016-10-14 18:06:47 -0700106// TODO: variables and functions below should be part of dumpstate object
107
Felipe Leme635ca312016-01-05 14:23:02 -0800108static std::set<std::string> mount_points;
109void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800110
Todd Poynor2a83daa2013-11-22 15:44:22 -0800111#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700112#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700113#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800114
Felipe Lemee82a27d2016-01-05 13:35:44 -0800115#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700116#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700117#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700118#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100119#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
120#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800121#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900122#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800123#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700124
Narayan Kamath8f788292017-05-25 13:20:39 +0100125// TODO(narayan): Since this information has to be kept in sync
126// with tombstoned, we should just put it in a common header.
127//
128// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100129static const std::string TOMBSTONE_DIR = "/data/tombstones/";
130static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
131static const std::string ANR_DIR = "/data/anr/";
132static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700133
Felipe Lemee844a9d2016-09-21 15:01:39 -0700134// TODO: temporary variables and functions used during C++ refactoring
135static Dumpstate& ds = Dumpstate::GetInstance();
Nandana Dutt979388e2018-11-30 16:48:55 +0000136
Nandana Duttbbdb5b42019-03-12 10:52:56 +0000137#define RETURN_IF_USER_DENIED_CONSENT() \
138 if (ds.IsUserConsentDenied()) { \
139 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
140 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
141 }
142
143// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
144// if consent is found to be denied.
145#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
146 RETURN_IF_USER_DENIED_CONSENT(); \
147 func_ptr(__VA_ARGS__); \
148 RETURN_IF_USER_DENIED_CONSENT();
149
Nandana Dutt979388e2018-11-30 16:48:55 +0000150namespace android {
151namespace os {
152namespace {
153
154static int Open(std::string path, int flags, mode_t mode = 0) {
155 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
156 if (fd == -1) {
157 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
158 }
159 return fd;
160}
161
Nandana Dutt979388e2018-11-30 16:48:55 +0000162
163static int OpenForRead(std::string path) {
164 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
165}
166
167bool CopyFile(int in_fd, int out_fd) {
168 char buf[4096];
169 ssize_t byte_count;
170 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
171 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
172 return false;
173 }
174 }
175 return (byte_count != -1);
176}
177
178static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000179 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000180
181 // Obtain a handle to the source file.
182 android::base::unique_fd in_fd(OpenForRead(input_file));
183 if (out_fd != -1 && in_fd.get() != -1) {
184 if (CopyFile(in_fd.get(), out_fd)) {
185 return true;
186 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000187 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000188 }
189 return false;
190}
191
Nandana Duttd2f5f082019-01-18 17:13:52 +0000192static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000193 if (unlink(file.c_str())) {
194 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000195 return false;
196 }
197 return true;
198}
Nandana Dutt979388e2018-11-30 16:48:55 +0000199
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +0000200static bool IsFileEmpty(const std::string& file_path) {
201 std::ifstream file(file_path, std::ios::binary | std::ios::ate);
202 if(file.bad()) {
203 MYLOGE("Cannot open file: %s\n", file_path.c_str());
204 return true;
205 }
206 return file.tellg() <= 0;
207}
208
Nandana Dutt979388e2018-11-30 16:48:55 +0000209} // namespace
210} // namespace os
211} // namespace android
212
Felipe Leme678727a2016-09-21 17:22:11 -0700213static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
214 const CommandOptions& options = CommandOptions::DEFAULT) {
215 return ds.RunCommand(title, fullCommand, options);
216}
217static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800218 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800219 long dumpsysTimeoutMs = 0) {
220 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700221}
222static int DumpFile(const std::string& title, const std::string& path) {
223 return ds.DumpFile(title, path);
224}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800225
Felipe Lemee844a9d2016-09-21 15:01:39 -0700226// Relative directory (inside the zip) for all files copied as-is into the bugreport.
227static const std::string ZIP_ROOT_DIR = "FS";
228
Vishnu Naire97d6122018-01-18 13:58:56 -0800229static const std::string kProtoPath = "proto/";
230static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700231static const std::string kDumpstateBoardFiles[] = {
232 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700233 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700234};
235static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
236
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700237static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700238static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700239static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700240static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
241static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700242
Felipe Lemef0292972016-11-22 13:57:05 -0800243static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
244
Narayan Kamath8f788292017-05-25 13:20:39 +0100245/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100246 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
247 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
248 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700249 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100250 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700251static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
252 const std::string& file_prefix,
253 bool limit_by_mtime,
254 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100255 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
256
Narayan Kamathbd863722017-06-01 18:50:12 +0100257 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100258
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700259 if (dump_dir == nullptr) {
260 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700261 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700262 }
263
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700264 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100265 struct dirent* entry = nullptr;
266 while ((entry = readdir(dump_dir.get()))) {
267 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100268 continue;
269 }
270
Narayan Kamathbd863722017-06-01 18:50:12 +0100271 const std::string base_name(entry->d_name);
272 if (base_name.find(file_prefix) != 0) {
273 continue;
274 }
275
276 const std::string abs_path = dir_path + base_name;
277 android::base::unique_fd fd(
278 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
279 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700280 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100281 break;
282 }
283
284 struct stat st = {};
285 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700286 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100287 continue;
288 }
289
Narayan Kamath3f31b632018-02-22 19:42:36 +0000290 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100291 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100292 continue;
293 }
294
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700295 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700296 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100297
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700298 // Sort in descending modification time so that we only keep the newest
299 // reports if |limit_by_count| is true.
300 std::sort(dump_data.begin(), dump_data.end(),
301 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100302
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700303 if (limit_by_count && dump_data.size() > 10) {
304 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700305 }
306
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700307 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100308}
309
Narayan Kamathbd863722017-06-01 18:50:12 +0100310static bool AddDumps(const std::vector<DumpData>::const_iterator start,
311 const std::vector<DumpData>::const_iterator end,
312 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100313 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100314 for (auto it = start; it != end; ++it) {
315 const std::string& name = it->name;
316 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100317 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100318
319 // Seek to the beginning of the file before dumping any data. A given
320 // DumpData entry might be dumped multiple times in the report.
321 //
322 // For example, the most recent ANR entry is dumped to the body of the
323 // main entry and it also shows up as a separate entry in the bugreport
324 // ZIP file.
325 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
326 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
327 strerror(errno));
328 }
329
Narayan Kamath8f788292017-05-25 13:20:39 +0100330 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800331 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100332 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100333 }
334 } else {
335 dump_file_from_fd(type_name, name.c_str(), fd);
336 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100337 }
338
339 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700340}
341
Felipe Leme635ca312016-01-05 14:23:02 -0800342// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700343void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800344 char path[PATH_MAX];
345
346 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
347 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700348 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800349 char linkname[PATH_MAX];
350 ssize_t r = readlink(path, linkname, PATH_MAX);
351 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800352 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800353 return;
354 }
355 linkname[r] = '\0';
356
357 if (mount_points.find(linkname) == mount_points.end()) {
358 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700359 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700360 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800361 mount_points.insert(linkname);
362 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800363 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800364 }
365 }
366}
367
368void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700369 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700370 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800371 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800372 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700373 for_each_pid(do_mountinfo, nullptr);
374 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800375}
376
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700377static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
378{
379 DIR *d;
380 struct dirent *de;
381 char path[PATH_MAX];
382
383 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700384 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700385 return;
386 }
387
388 while ((de = readdir(d))) {
389 if (de->d_type != DT_LNK) {
390 continue;
391 }
392 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700393 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700394 }
395
396 closedir(d);
397}
398
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700399
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700400
401// dump anrd's trace and add to the zip file.
402// 1. check if anrd is running on this device.
403// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
404// 3. wait until the trace generation completes and add to the zip file.
405static bool dump_anrd_trace() {
406 unsigned int pid;
407 char buf[50], path[PATH_MAX];
408 struct dirent *trace;
409 struct stat st;
410 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700411 int retry = 5;
412 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700413 long long cur_size = 0;
414 const char *trace_path = "/data/misc/anrd/";
415
Felipe Leme1d486fe2016-10-14 18:06:47 -0700416 if (!ds.IsZipping()) {
417 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700418 return false;
419 }
420
421 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700422 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700423
424 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700425 if (stat(trace_path, &st) == 0) {
426 old_mtime = st.st_mtime;
427 } else {
428 MYLOGE("Failed to find: %s\n", trace_path);
429 return false;
430 }
431
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700432 // send SIGUSR1 to the anrd to generate a trace.
433 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700434 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700435 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700436 MYLOGE("anrd signal timed out. Please manually collect trace\n");
437 return false;
438 }
439
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700440 while (retry-- > 0 && old_mtime == st.st_mtime) {
441 sleep(1);
442 stat(trace_path, &st);
443 }
444
445 if (retry < 0 && old_mtime == st.st_mtime) {
446 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
447 return false;
448 }
449
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700450 // identify the trace file by its creation time.
451 if (!(trace_dir = opendir(trace_path))) {
452 MYLOGE("Can't open trace file under %s\n", trace_path);
453 }
454 while ((trace = readdir(trace_dir))) {
455 if (strcmp(trace->d_name, ".") == 0
456 || strcmp(trace->d_name, "..") == 0) {
457 continue;
458 }
459 sprintf(path, "%s%s", trace_path, trace->d_name);
460 if (stat(path, &st) == 0) {
461 if (st.st_ctime > max_ctime) {
462 max_ctime = st.st_ctime;
463 sprintf(buf, "%s", trace->d_name);
464 }
465 }
466 }
467 closedir(trace_dir);
468
469 // Wait until the dump completes by checking the size of the trace.
470 if (max_ctime > 0) {
471 sprintf(path, "%s%s", trace_path, buf);
472 while(true) {
473 sleep(1);
474 if (stat(path, &st) == 0) {
475 if (st.st_size == cur_size) {
476 break;
477 } else if (st.st_size > cur_size) {
478 cur_size = st.st_size;
479 } else {
480 return false;
481 }
482 } else {
483 MYLOGE("Cant stat() %s anymore\n", path);
484 return false;
485 }
486 }
487 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700488 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700489 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
490 } else {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000491 android::os::UnlinkAndLogOnError(path);
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700492 return true;
493 }
494 } else {
495 MYLOGE("Can't stats any trace file under %s\n", trace_path);
496 }
497 }
498 return false;
499}
500
Mark Salyzyn326842f2015-04-30 09:49:41 -0700501static bool skip_not_stat(const char *path) {
502 static const char stat[] = "/stat";
503 size_t len = strlen(path);
504 if (path[len - 1] == '/') { /* Directory? */
505 return false;
506 }
507 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
508}
509
Felipe Leme4c2d6632016-09-28 14:32:00 -0700510static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800511 return false;
512}
513
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700514unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700515
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800516//
517// stat offsets
518// Name units description
519// ---- ----- -----------
520// read I/Os requests number of read I/Os processed
521#define __STAT_READ_IOS 0
522// read merges requests number of read I/Os merged with in-queue I/O
523#define __STAT_READ_MERGES 1
524// read sectors sectors number of sectors read
525#define __STAT_READ_SECTORS 2
526// read ticks milliseconds total wait time for read requests
527#define __STAT_READ_TICKS 3
528// write I/Os requests number of write I/Os processed
529#define __STAT_WRITE_IOS 4
530// write merges requests number of write I/Os merged with in-queue I/O
531#define __STAT_WRITE_MERGES 5
532// write sectors sectors number of sectors written
533#define __STAT_WRITE_SECTORS 6
534// write ticks milliseconds total wait time for write requests
535#define __STAT_WRITE_TICKS 7
536// in_flight requests number of I/Os currently in flight
537#define __STAT_IN_FLIGHT 8
538// io_ticks milliseconds total time this block device has been active
539#define __STAT_IO_TICKS 9
540// time_in_queue milliseconds total wait time for all requests
541#define __STAT_IN_QUEUE 10
542#define __STAT_NUMBER_FIELD 11
543//
544// read I/Os, write I/Os
545// =====================
546//
547// These values increment when an I/O request completes.
548//
549// read merges, write merges
550// =========================
551//
552// These values increment when an I/O request is merged with an
553// already-queued I/O request.
554//
555// read sectors, write sectors
556// ===========================
557//
558// These values count the number of sectors read from or written to this
559// block device. The "sectors" in question are the standard UNIX 512-byte
560// sectors, not any device- or filesystem-specific block size. The
561// counters are incremented when the I/O completes.
562#define SECTOR_SIZE 512
563//
564// read ticks, write ticks
565// =======================
566//
567// These values count the number of milliseconds that I/O requests have
568// waited on this block device. If there are multiple I/O requests waiting,
569// these values will increase at a rate greater than 1000/second; for
570// example, if 60 read requests wait for an average of 30 ms, the read_ticks
571// field will increase by 60*30 = 1800.
572//
573// in_flight
574// =========
575//
576// This value counts the number of I/O requests that have been issued to
577// the device driver but have not yet completed. It does not include I/O
578// requests that are in the queue but not yet issued to the device driver.
579//
580// io_ticks
581// ========
582//
583// This value counts the number of milliseconds during which the device has
584// had I/O requests queued.
585//
586// time_in_queue
587// =============
588//
589// This value counts the number of milliseconds that I/O requests have waited
590// on this block device. If there are multiple I/O requests waiting, this
591// value will increase as the product of the number of milliseconds times the
592// number of requests waiting (see "read ticks" above for an example).
593#define S_TO_MS 1000
594//
595
Mark Salyzyn326842f2015-04-30 09:49:41 -0700596static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800597 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700598 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700599 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700600 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700601 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700602 getline(&buffer, &i, fp);
603 fclose(fp);
604 if (!buffer) {
605 return -errno;
606 }
607 i = strlen(buffer);
608 while ((i > 0) && (buffer[i - 1] == '\n')) {
609 buffer[--i] = '\0';
610 }
611 if (!*buffer) {
612 free(buffer);
613 return 0;
614 }
615 z = true;
616 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800617 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700618 if (fields[i] != 0) {
619 z = false;
620 }
621 }
622 if (z) { /* never accessed */
623 free(buffer);
624 return 0;
625 }
626
Wei Wang509bb5d2017-06-09 14:42:12 -0700627 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
628 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700629 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700630
631 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
632 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
633 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 free(buffer);
635
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800636 if (fields[__STAT_IO_TICKS]) {
637 unsigned long read_perf = 0;
638 unsigned long read_ios = 0;
639 if (fields[__STAT_READ_TICKS]) {
640 unsigned long long divisor = fields[__STAT_READ_TICKS]
641 * fields[__STAT_IO_TICKS];
642 read_perf = ((unsigned long long)SECTOR_SIZE
643 * fields[__STAT_READ_SECTORS]
644 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
645 / divisor;
646 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
647 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
648 / divisor;
649 }
650
651 unsigned long write_perf = 0;
652 unsigned long write_ios = 0;
653 if (fields[__STAT_WRITE_TICKS]) {
654 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
655 * fields[__STAT_IO_TICKS];
656 write_perf = ((unsigned long long)SECTOR_SIZE
657 * fields[__STAT_WRITE_SECTORS]
658 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
659 / divisor;
660 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
661 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
662 / divisor;
663 }
664
665 unsigned queue = (fields[__STAT_IN_QUEUE]
666 + (fields[__STAT_IO_TICKS] >> 1))
667 / fields[__STAT_IO_TICKS];
668
669 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700670 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 -0800671 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700672 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 -0800673 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800674 }
675
676 /* bugreport timeout factor adjustment */
677 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
678 worst_write_perf = write_perf;
679 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700680 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700681 return 0;
682}
683
Yao Chenbe3bbc12018-01-17 16:31:10 -0800684static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
685
686/* timeout in ms to read a list of buffers */
687static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
688 unsigned long timeout_ms = 0;
689 for (const auto& buffer : buffers) {
690 log_id_t id = android_name_to_log_id(buffer.c_str());
691 unsigned long property_size = __android_logger_get_buffer_size(id);
692 /* Engineering margin is ten-fold our guess */
693 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
694 }
695 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700696}
697
Nandana Duttd2f5f082019-01-18 17:13:52 +0000698Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
699}
700
701android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
702 std::lock_guard<std::mutex> lock(lock_);
703 result_ = APPROVED;
704 MYLOGD("User approved consent to share bugreport\n");
705 return android::binder::Status::ok();
706}
707
708android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
709 std::lock_guard<std::mutex> lock(lock_);
710 result_ = DENIED;
711 MYLOGW("User denied consent to share bugreport\n");
712 return android::binder::Status::ok();
713}
714
715UserConsentResult Dumpstate::ConsentCallback::getResult() {
716 std::lock_guard<std::mutex> lock(lock_);
717 return result_;
718}
719
720uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
721 return Nanotime() - start_time_;
722}
723
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700724void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700725 std::string build, fingerprint, radio, bootloader, network;
726 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700727
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700728 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
729 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700730 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
731 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
732 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700733 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700734
Felipe Lemed8b94e52016-12-08 10:21:44 -0800735 printf("========================================================\n");
736 printf("== dumpstate: %s\n", date);
737 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700738
Felipe Lemed8b94e52016-12-08 10:21:44 -0800739 printf("\n");
740 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700741 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800742 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
743 printf("Bootloader: %s\n", bootloader.c_str());
744 printf("Radio: %s\n", radio.c_str());
745 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700746
Felipe Lemed8b94e52016-12-08 10:21:44 -0800747 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800748 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800749 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800750 printf("Uptime: ");
751 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
752 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800753 printf("Bugreport format version: %s\n", version_.c_str());
754 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 +0100755 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800756 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800757}
758
Felipe Leme24b66ee2016-06-16 10:55:26 -0700759// List of file extensions that can cause a zip file attachment to be rejected by some email
760// service providers.
761static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
762 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
763 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
764 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
765};
766
Vishnu Naire97d6122018-01-18 13:58:56 -0800767status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
768 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700769 if (!IsZipping()) {
770 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
771 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800772 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800773 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700774 std::string valid_name = entry_name;
775
776 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700777 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700778 if (idx != std::string::npos) {
779 std::string extension = entry_name.substr(idx);
780 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
781 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
782 valid_name = entry_name + ".renamed";
783 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
784 }
785 }
786
Felipe Leme6fe9db62016-02-12 09:04:16 -0800787 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
788 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700789 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
790 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700791 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700792 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700793 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800794 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800795 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000796 bool finished_entry = false;
797 auto finish_entry = [this, &finished_entry] {
798 if (!finished_entry) {
799 // This should only be called when we're going to return an earlier error,
800 // which would've been logged. This may imply the file is already corrupt
801 // and any further logging from FinishEntry is more likely to mislead than
802 // not.
803 this->zip_writer_->FinishEntry();
804 }
805 };
806 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800807 auto start = std::chrono::steady_clock::now();
808 auto end = start + timeout;
809 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800810
Felipe Leme770410d2016-01-26 17:07:14 -0800811 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800812 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800813 if (timeout.count() > 0) {
814 // lambda to recalculate the timeout.
815 auto time_left_ms = [end]() {
816 auto now = std::chrono::steady_clock::now();
817 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
818 return std::max(diff.count(), 0LL);
819 };
820
821 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
822 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000823 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
824 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800825 return -errno;
826 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000827 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800828 entry_name.c_str(), strerror(errno), timeout.count());
829 return TIMED_OUT;
830 }
831 }
832
Zach Riggle22200402016-08-18 01:01:24 -0400833 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800834 if (bytes_read == 0) {
835 break;
836 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800837 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800838 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800839 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700840 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800841 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700842 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800843 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800844 }
845 }
846
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700847 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000848 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700849 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700850 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800851 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800852 }
853
Vishnu Naire97d6122018-01-18 13:58:56 -0800854 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800855}
856
Felipe Leme1d486fe2016-10-14 18:06:47 -0700857bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
858 android::base::unique_fd fd(
859 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700860 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800861 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800862 return false;
863 }
864
Vishnu Naire97d6122018-01-18 13:58:56 -0800865 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800866}
867
868/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700869static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800870 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800871}
872
Felipe Leme1d486fe2016-10-14 18:06:47 -0700873void Dumpstate::AddDir(const std::string& dir, bool recursive) {
874 if (!IsZipping()) {
875 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800876 return;
877 }
Felipe Leme678727a2016-09-21 17:22:11 -0700878 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800879 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700880 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800881}
882
Felipe Leme1d486fe2016-10-14 18:06:47 -0700883bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
884 if (!IsZipping()) {
885 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
886 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800887 return false;
888 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800889 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700890 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700891 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700892 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700893 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800894 return false;
895 }
896
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700897 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700898 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700899 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700900 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800901 return false;
902 }
903
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700904 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700905 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700906 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800907 return false;
908 }
909
910 return true;
911}
912
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800913static void DoKmsg() {
914 struct stat st;
915 if (!stat(PSTORE_LAST_KMSG, &st)) {
916 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
917 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
918 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
919 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
920 } else {
921 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
922 DumpFile("LAST KMSG", "/proc/last_kmsg");
923 }
924}
925
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800926static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800927 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800928 RunCommand(
929 "KERNEL LOG",
930 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
931 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
932}
933
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800934static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800935 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800936 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
937 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800938 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100939 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800940 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
941 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800942 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800943 RunCommand(
944 "EVENT LOG",
945 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
946 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800947 timeout_ms = logcat_timeout({"stats"});
948 RunCommand(
949 "STATS LOG",
950 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
951 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
952 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800953 RunCommand(
954 "RADIO LOG",
955 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
956 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800957
958 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
959
960 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800961 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
962 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800963}
964
Jayachandran Ca94c7172017-06-10 15:08:12 -0700965static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700966 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
967 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900968 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700969 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900970 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
971 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
972 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
973 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700974}
975
Narayan Kamath8f788292017-05-25 13:20:39 +0100976static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
977 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
978 anr_traces_dir.c_str());
979
980 // If we're here, dump_traces_path will always be a temporary file
981 // (created with mkostemp or similar) that contains dumps taken earlier
982 // on in the process.
983 if (dump_traces_path != nullptr) {
984 if (add_to_zip) {
985 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
986 } else {
987 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
988 dump_traces_path);
989 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
990 }
991
992 const int ret = unlink(dump_traces_path);
993 if (ret == -1) {
994 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
995 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700996 }
997 }
998
Narayan Kamathbd863722017-06-01 18:50:12 +0100999 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001000 if (ds.anr_data_.size() > 0) {
1001 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001002 "VM TRACES AT LAST ANR", add_to_zip);
1003
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001004 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1005 // it will be present in the body of the main entry if |add_to_zip| == false.
1006 //
1007 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001008 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001009 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001010 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001011 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1012 }
1013}
1014
1015static void AddAnrTraceFiles() {
1016 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1017
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001018 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001019
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001020 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001021
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001022 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1023
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001024 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001025 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001026 int i = 0;
1027 while (true) {
1028 const std::string slow_trace_path =
1029 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1030 if (stat(slow_trace_path.c_str(), &st)) {
1031 // No traces file at this index, done with the files.
1032 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001033 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001034 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1035 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001036 }
1037}
1038
Wei Wang509bb5d2017-06-09 14:42:12 -07001039static void DumpBlockStatFiles() {
1040 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001041
Wei Wang1dc1ef52017-06-12 11:28:37 -07001042 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1043
1044 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001045 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1046 return;
1047 }
1048
1049 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001050 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001051 if ((d->d_name[0] == '.')
1052 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1053 || (d->d_name[1] == '\0'))) {
1054 continue;
1055 }
1056 const std::string new_path =
1057 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1058 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1059 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1060 printf("\n");
1061 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001062 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001063}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001064
1065static void DumpPacketStats() {
1066 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1067 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1068 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1069 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1070 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1071}
1072
1073static void DumpIpAddrAndRules() {
1074 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1075 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1076 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1077 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1078 RunCommand("IP RULES", {"ip", "rule", "show"});
1079 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1080}
1081
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001082static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1083 std::chrono::milliseconds timeout,
1084 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001085 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001086 sp<android::IServiceManager> sm = defaultServiceManager();
1087 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001088 Vector<String16> args;
1089 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001090 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1091 for (const String16& service : services) {
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001092 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001093 std::string path(title);
1094 path.append(" - ").append(String8(service).c_str());
1095 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1096 size_t bytes_written = 0;
1097 status_t status = dumpsys.startDumpThread(service, args);
1098 if (status == OK) {
1099 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1100 std::chrono::duration<double> elapsed_seconds;
1101 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1102 /* as_proto = */ false, elapsed_seconds, bytes_written);
1103 section_reporter.setSize(bytes_written);
1104 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1105 bool dump_complete = (status == OK);
1106 dumpsys.stopDumpThread(dump_complete);
1107 }
1108 section_reporter.setStatus(status);
1109
1110 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1111 std::chrono::steady_clock::now() - start);
1112 if (elapsed_duration > timeout) {
1113 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1114 elapsed_duration.count());
1115 break;
1116 }
1117 }
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001118 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001119}
1120
Vishnu Nair64afc022018-02-01 15:29:34 -08001121static void RunDumpsysText(const std::string& title, int priority,
1122 std::chrono::milliseconds timeout,
1123 std::chrono::milliseconds service_timeout) {
1124 DurationReporter duration_reporter(title);
1125 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1126 fsync(STDOUT_FILENO);
1127 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1128}
1129
1130/* Dump all services registered with Normal or Default priority. */
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001131static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1132 std::chrono::milliseconds timeout,
1133 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001134 DurationReporter duration_reporter(title);
1135 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1136 fsync(STDOUT_FILENO);
1137 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1138 service_timeout);
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001139
1140 RETURN_IF_USER_DENIED_CONSENT();
1141
1142 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1143 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001144}
1145
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001146static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1147 std::chrono::milliseconds timeout,
1148 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001149 if (!ds.IsZipping()) {
1150 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001151 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001152 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001153 sp<android::IServiceManager> sm = defaultServiceManager();
1154 Dumpsys dumpsys(sm.get());
1155 Vector<String16> args;
1156 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1157 DurationReporter duration_reporter(title);
1158
1159 auto start = std::chrono::steady_clock::now();
1160 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1161 for (const String16& service : services) {
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001162 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001163 std::string path(kProtoPath);
1164 path.append(String8(service).c_str());
1165 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1166 path.append("_CRITICAL");
1167 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1168 path.append("_HIGH");
1169 }
1170 path.append(kProtoExt);
1171 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1172 status_t status = dumpsys.startDumpThread(service, args);
1173 if (status == OK) {
1174 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1175 bool dumpTerminated = (status == OK);
1176 dumpsys.stopDumpThread(dumpTerminated);
1177 }
1178 ZipWriter::FileEntry file_entry;
1179 ds.zip_writer_->GetLastEntry(&file_entry);
1180 section_reporter.setSize(file_entry.compressed_size);
1181 section_reporter.setStatus(status);
1182
1183 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1184 std::chrono::steady_clock::now() - start);
1185 if (elapsed_duration > timeout) {
1186 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1187 elapsed_duration.count());
1188 break;
1189 }
1190 }
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001191 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001192}
1193
Nandana Dutta7db6342018-11-21 14:53:34 +00001194// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001195static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001196 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1197 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001198
1199 RETURN_IF_USER_DENIED_CONSENT();
1200
1201 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1202 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001203}
1204
1205// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001206static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001207 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1208 // high priority. Reduce timeout once they are able to dump in a shorter time or
1209 // moved to a parallel task.
1210 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1211 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001212
1213 RETURN_IF_USER_DENIED_CONSENT();
1214
1215 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1216 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001217}
1218
1219// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001220static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001221 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001222
1223 RETURN_IF_USER_DENIED_CONSENT();
1224
1225 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1226 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001227}
1228
Steven Moreland44cd9482018-01-04 16:24:13 -08001229static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001230 if (!ds.IsZipping()) {
1231 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1232 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1233 return;
1234 }
1235 DurationReporter duration_reporter("DUMP HALS");
1236 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1237 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1238
Steven Moreland44cd9482018-01-04 16:24:13 -08001239 using android::hidl::manager::V1_0::IServiceManager;
1240 using android::hardware::defaultServiceManager;
1241
1242 sp<IServiceManager> sm = defaultServiceManager();
1243 if (sm == nullptr) {
1244 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1245 return;
1246 }
1247
1248 auto ret = sm->list([&](const auto& interfaces) {
1249 for (const std::string& interface : interfaces) {
1250 std::string cleanName = interface;
1251 std::replace_if(cleanName.begin(),
1252 cleanName.end(),
1253 [](char c) {
1254 return !isalnum(c) &&
1255 std::string("@-_:.").find(c) == std::string::npos;
1256 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001257 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001258
1259 {
1260 auto fd = android::base::unique_fd(
1261 TEMP_FAILURE_RETRY(open(path.c_str(),
1262 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1263 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1264 if (fd < 0) {
1265 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1266 continue;
1267 }
1268 RunCommandToFd(fd,
1269 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001270 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001271 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1272
1273 bool empty = 0 == lseek(fd, 0, SEEK_END);
1274 if (!empty) {
1275 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1276 }
1277 }
1278
1279 unlink(path.c_str());
1280 }
1281 });
1282
1283 if (!ret.isOk()) {
1284 MYLOGE("Could not list hals from hwservicemanager.\n");
1285 }
1286}
1287
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001288static void DumpExternalFragmentationInfo() {
1289 struct stat st;
1290 if (stat("/proc/buddyinfo", &st) != 0) {
1291 MYLOGE("Unable to dump external fragmentation info\n");
1292 return;
1293 }
1294
1295 printf("------ EXTERNAL FRAGMENTATION INFO ------\n");
1296 std::ifstream ifs("/proc/buddyinfo");
1297 auto unusable_index_regex = std::regex{"Node\\s+([0-9]+),\\s+zone\\s+(\\S+)\\s+(.*)"};
1298 for (std::string line; std::getline(ifs, line);) {
1299 std::smatch match_results;
1300 if (std::regex_match(line, match_results, unusable_index_regex)) {
1301 std::stringstream free_pages(std::string{match_results[3]});
1302 std::vector<int> free_pages_per_order(std::istream_iterator<int>{free_pages},
1303 std::istream_iterator<int>());
1304
1305 int total_free_pages = 0;
1306 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1307 total_free_pages += (free_pages_per_order[i] * std::pow(2, i));
1308 }
1309
1310 printf("Node %s, zone %8s", match_results[1].str().c_str(),
1311 match_results[2].str().c_str());
1312
1313 int usable_free_pages = total_free_pages;
1314 for (size_t i = 0; i < free_pages_per_order.size(); i++) {
1315 auto unusable_index = (total_free_pages - usable_free_pages) /
1316 static_cast<double>(total_free_pages);
1317 printf(" %5.3f", unusable_index);
1318 usable_free_pages -= (free_pages_per_order[i] * std::pow(2, i));
1319 }
1320
1321 printf("\n");
1322 }
1323 }
1324 printf("\n");
1325}
1326
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001327// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1328// via the consent they are shown. Ignores other errors that occur while running various
1329// commands. The consent checking is currently done around long running tasks, which happen to
1330// be distributed fairly evenly throughout the function.
1331static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001332 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001333
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001334 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1335 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1336 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001337 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001338 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001339 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001340 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001341 DumpFile("MEMORY INFO", "/proc/meminfo");
1342 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001343 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001344
1345 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1346
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001347 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1348 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1349 DumpFile("SLAB INFO", "/proc/slabinfo");
1350 DumpFile("ZONEINFO", "/proc/zoneinfo");
1351 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1352 DumpFile("BUDDYINFO", "/proc/buddyinfo");
Hridya Valsarajuac582cd2019-08-05 15:39:54 -07001353 DumpExternalFragmentationInfo();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001354
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001355 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1356 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1357 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001358
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001359 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001360 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001361
1362 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1363 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001364
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001365 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001366
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001367 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001368 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001369 struct stat s;
1370 if (stat("/proc/modules", &s) != 0) {
1371 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1372 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001373 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001374 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001375
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001376 if (__android_logger_property_get_bool(
1377 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1378 DoKernelLogcat();
1379 } else {
1380 do_dmesg();
1381 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001382
Felipe Lemef0292972016-11-22 13:57:05 -08001383 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001384
1385 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1386
Jeff Brown1dc94e32014-09-11 14:15:27 -07001387 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001388 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001389
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001390 /* Dump Bluetooth HCI logs */
1391 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001392
Felipe Leme9a523ae2016-10-20 15:10:33 -07001393 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001394 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001395 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001396 }
1397
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001398 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001399
Felipe Lemee184f662016-10-27 10:04:47 -07001400 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001401
Narayan Kamath8f788292017-05-25 13:20:39 +01001402 // NOTE: tombstones are always added as separate entries in the zip archive
1403 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001404 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001405 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001406 if (!tombstones_dumped) {
1407 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001408 }
1409
Jayachandran Ca94c7172017-06-10 15:08:12 -07001410 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001411
Chenbo Feng276a3b62018-08-07 11:44:49 -07001412 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1413
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001414 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001415
Jayachandran Ca94c7172017-06-10 15:08:12 -07001416 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001417
1418 dump_route_tables();
1419
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001420 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1421 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1422 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001423
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001424 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001425
Elliott Hughes23ccc622017-02-28 10:14:22 -08001426 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001427
Jin Qianf334d662017-10-10 14:41:37 -07001428 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001429
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001430 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001431
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001432 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001433
Colin Crossf45fa6b2012-03-26 12:38:26 -07001434 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001435 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1436 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1437 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1438 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1439 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001440
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001441 /* Add window and surface trace files. */
1442 if (!PropertiesHelper::IsUserBuild()) {
1443 ds.AddDir(WMTRACE_DATA_DIR, false);
1444 }
1445
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001446 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001447
Steven Moreland7440ddb2016-12-15 16:13:39 -08001448 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001449 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1450 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001451 // su does not exist on user builds, so try running without it.
1452 // This way any implementations of vril-dump that do not require
1453 // root can run on user builds.
1454 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001455 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001456 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001457 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001458 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001459 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001460 }
1461
Felipe Lemed8b94e52016-12-08 10:21:44 -08001462 printf("========================================================\n");
1463 printf("== Android Framework Services\n");
1464 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001465
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001466 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001467
Felipe Lemed8b94e52016-12-08 10:21:44 -08001468 printf("========================================================\n");
1469 printf("== Checkins\n");
1470 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001471
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001472 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001473
1474 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1475
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001476 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1477 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1478 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1479 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001480
Felipe Lemed8b94e52016-12-08 10:21:44 -08001481 printf("========================================================\n");
1482 printf("== Running Application Activities\n");
1483 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001484
Makoto Onuki60780982018-04-16 15:34:00 -07001485 // The following dumpsys internally collects output from running apps, so it can take a long
1486 // time. So let's extend the timeout.
1487
1488 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1489
1490 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001491
Felipe Lemed8b94e52016-12-08 10:21:44 -08001492 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001493 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001494 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001495
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001496 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001497 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001498
Felipe Lemed8b94e52016-12-08 10:21:44 -08001499 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001500 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001501 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001502
Makoto Onuki60780982018-04-16 15:34:00 -07001503 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1504 DUMPSYS_COMPONENTS_OPTIONS);
1505
1506 printf("========================================================\n");
1507 printf("== Running Application Providers (platform)\n");
1508 printf("========================================================\n");
1509
1510 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1511 DUMPSYS_COMPONENTS_OPTIONS);
1512
1513 printf("========================================================\n");
1514 printf("== Running Application Providers (non-platform)\n");
1515 printf("========================================================\n");
1516
1517 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1518 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001519
Adrian Roos8b397ab2017-04-04 16:35:44 -07001520 printf("========================================================\n");
1521 printf("== Dropbox crashes\n");
1522 printf("========================================================\n");
1523
1524 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1525 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1526
Felipe Lemed8b94e52016-12-08 10:21:44 -08001527 printf("========================================================\n");
1528 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1529 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1530 printf("========================================================\n");
1531 printf("== dumpstate: done (id %d)\n", ds.id_);
1532 printf("========================================================\n");
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001533 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001534}
1535
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001536/*
1537 * Dumps state for the default case; drops root after it's no longer necessary.
1538 *
1539 * Returns RunStatus::OK if everything went fine.
1540 * Returns RunStatus::ERROR if there was an error.
1541 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1542 * with the caller.
1543 */
1544static Dumpstate::RunStatus DumpstateDefault() {
Primiano Tucci2d7f5c22019-01-17 15:51:14 +00001545 // Try to dump anrd trace if the daemon is running.
1546 dump_anrd_trace();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001547
Nandana Duttcf419a72019-03-14 10:40:17 +00001548 // Invoking the following dumpsys calls before DumpTraces() to try and
Nandana Dutt4be45d12018-09-26 15:04:23 +01001549 // keep the system stats as close to its initial state as possible.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001550 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001551
1552 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001553 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001554
1555 /* Run some operations that require root. */
1556 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1557 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1558
1559 ds.AddDir(RECOVERY_DIR, true);
1560 ds.AddDir(RECOVERY_DATA_DIR, true);
1561 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1562 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1563 if (!PropertiesHelper::IsUserBuild()) {
1564 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1565 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1566 }
1567 add_mountinfo();
1568 DumpIpTablesAsRoot();
1569
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001570 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001571 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1572
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001573 // Dump IPsec stats. No keys are exposed here.
1574 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1575
Nandana Dutt4be45d12018-09-26 15:04:23 +01001576 // Run ss as root so we can see socket marks.
1577 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1578
1579 // Run iotop as root to show top 100 IO threads
1580 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1581
Erick Reyese68df822019-02-11 14:46:36 -08001582 // Gather shared memory buffer info if the product implements it
1583 struct stat st;
1584 if (!stat("/product/bin/dmabuf_dump", &st)) {
1585 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1586 }
1587
Nandana Dutt4be45d12018-09-26 15:04:23 +01001588 if (!DropRootUser()) {
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001589 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001590 }
1591
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001592 RETURN_IF_USER_DENIED_CONSENT();
1593 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001594}
1595
mukesh agrawal253dad42018-01-23 21:59:59 -08001596// This method collects common dumpsys for telephony and wifi
1597static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001598 DumpIpTablesAsRoot();
1599
1600 if (!DropRootUser()) {
1601 return;
1602 }
1603
1604 do_dmesg();
1605 DoLogcat();
1606 DumpPacketStats();
1607 DoKmsg();
1608 DumpIpAddrAndRules();
1609 dump_route_tables();
1610
1611 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1612 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001613}
1614
1615// This method collects dumpsys for telephony debugging only
1616static void DumpstateTelephonyOnly() {
1617 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001618 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001619
1620 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001621
1622 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1623
1624 printf("========================================================\n");
1625 printf("== Android Framework Services\n");
1626 printf("========================================================\n");
1627
Vishnu Nair652cc802017-11-30 15:18:30 -08001628 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1629 SEC_TO_MSEC(10));
Chiachang Wang85e0db32019-03-25 08:59:55 +08001630 RunDumpsys("DUMPSYS", {"connmetrics"}, CommandOptions::WithTimeout(90).Build(),
1631 SEC_TO_MSEC(10));
1632 RunDumpsys("DUMPSYS", {"netd"}, CommandOptions::WithTimeout(90).Build(), SEC_TO_MSEC(10));
Vishnu Nair652cc802017-11-30 15:18:30 -08001633 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1634 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001635 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1636 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001637 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1638 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001639
1640 printf("========================================================\n");
1641 printf("== Running Application Services\n");
1642 printf("========================================================\n");
1643
1644 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1645
1646 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001647 printf("== Running Application Services (non-platform)\n");
1648 printf("========================================================\n");
1649
1650 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1651 DUMPSYS_COMPONENTS_OPTIONS);
1652
1653 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001654 printf("== Checkins\n");
1655 printf("========================================================\n");
1656
1657 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1658
1659 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001660 printf("== dumpstate: done (id %d)\n", ds.id_);
1661 printf("========================================================\n");
1662}
1663
mukesh agrawal253dad42018-01-23 21:59:59 -08001664// This method collects dumpsys for wifi debugging only
1665static void DumpstateWifiOnly() {
1666 DurationReporter duration_reporter("DUMPSTATE");
1667
1668 DumpstateRadioCommon();
1669
1670 printf("========================================================\n");
1671 printf("== Android Framework Services\n");
1672 printf("========================================================\n");
1673
1674 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1675 SEC_TO_MSEC(10));
1676 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1677 SEC_TO_MSEC(10));
1678
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001679 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001680
mukesh agrawal253dad42018-01-23 21:59:59 -08001681 printf("========================================================\n");
1682 printf("== dumpstate: done (id %d)\n", ds.id_);
1683 printf("========================================================\n");
1684}
1685
Nandana Duttcf419a72019-03-14 10:40:17 +00001686Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001687 DurationReporter duration_reporter("DUMP TRACES");
1688
1689 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1690 const size_t buf_size = temp_file_pattern.length() + 1;
1691 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1692 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1693
1694 // Create a new, empty file to receive all trace dumps.
1695 //
1696 // TODO: This can be simplified once we remove support for the old style
1697 // dumps. We can have a file descriptor passed in to dump_traces instead
1698 // of creating a file, closing it and then reopening it again.
1699 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1700 if (fd < 0) {
1701 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001702 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001703 }
1704
1705 // Nobody should have access to this temporary file except dumpstate, but we
1706 // temporarily grant 'read' to 'others' here because this file is created
1707 // when tombstoned is still running as root, but dumped after dropping. This
1708 // can go away once support for old style dumping has.
1709 const int chmod_ret = fchmod(fd, 0666);
1710 if (chmod_ret < 0) {
1711 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001712 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001713 }
1714
1715 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1716 if (proc.get() == nullptr) {
1717 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001718 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001719 }
1720
1721 // Number of times process dumping has timed out. If we encounter too many
1722 // failures, we'll give up.
1723 int timeout_failures = 0;
1724 bool dalvik_found = false;
1725
1726 const std::set<int> hal_pids = get_interesting_hal_pids();
1727
1728 struct dirent* d;
1729 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001730 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001731 int pid = atoi(d->d_name);
1732 if (pid <= 0) {
1733 continue;
1734 }
1735
1736 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1737 std::string exe;
1738 if (!android::base::Readlink(link_name, &exe)) {
1739 continue;
1740 }
1741
1742 bool is_java_process;
1743 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1744 // Don't bother dumping backtraces for the zygote.
1745 if (IsZygote(pid)) {
1746 continue;
1747 }
1748
1749 dalvik_found = true;
1750 is_java_process = true;
1751 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1752 is_java_process = false;
1753 } else {
1754 // Probably a native process we don't care about, continue.
1755 continue;
1756 }
1757
1758 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1759 if (timeout_failures == 3) {
1760 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1761 break;
1762 }
1763
1764 const uint64_t start = Nanotime();
1765 const int ret = dump_backtrace_to_file_timeout(
1766 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1767 is_java_process ? 5 : 20, fd);
1768
1769 if (ret == -1) {
1770 // For consistency, the header and footer to this message match those
1771 // dumped by debuggerd in the success case.
1772 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1773 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1774 dprintf(fd, "---- end %d ----", pid);
1775 timeout_failures++;
1776 continue;
1777 }
1778
1779 // We've successfully dumped stack traces, reset the failure count
1780 // and write a summary of the elapsed time to the file and continue with the
1781 // next process.
1782 timeout_failures = 0;
1783
1784 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1785 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1786 }
1787
1788 if (!dalvik_found) {
1789 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1790 }
1791
Nandana Duttcf419a72019-03-14 10:40:17 +00001792 *path = file_name_buf.release();
1793 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001794}
1795
Felipe Leme6f674ae2016-11-18 17:10:33 -08001796void Dumpstate::DumpstateBoard() {
1797 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001798 printf("========================================================\n");
1799 printf("== Board\n");
1800 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001801
Felipe Leme6f674ae2016-11-18 17:10:33 -08001802 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001803 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001804 return;
1805 }
1806
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001807 std::vector<std::string> paths;
1808 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001809 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001810 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1811 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001812 remover.emplace_back(android::base::make_scope_guard(
1813 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001814 }
Jie Song9fbfad02017-06-20 16:29:42 -07001815
Wei Wang587eac92018-04-05 12:17:20 -07001816 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1817 if (dumpstate_device == nullptr) {
1818 MYLOGE("No IDumpstateDevice implementation\n");
1819 return;
1820 }
1821
1822 using ScopedNativeHandle =
1823 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1824 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1825 [](native_handle_t* handle) {
1826 native_handle_close(handle);
1827 native_handle_delete(handle);
1828 });
1829 if (handle == nullptr) {
1830 MYLOGE("Could not create native_handle\n");
1831 return;
1832 }
1833
Nandana Duttbbdb5b42019-03-12 10:52:56 +00001834 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001835 for (size_t i = 0; i < paths.size(); i++) {
1836 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1837
1838 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1839 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1840 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1841 if (fd < 0) {
1842 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1843 return;
1844 }
1845 handle.get()->data[i] = fd.release();
1846 }
1847
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001848 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001849 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1850 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1851 // and grab whatever dumped
1852 std::packaged_task<bool()>
1853 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001854 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1855 if (!status.isOk()) {
1856 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001857 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001858 }
Wei Wang587eac92018-04-05 12:17:20 -07001859 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001860 });
Wei Wang587eac92018-04-05 12:17:20 -07001861
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001862 auto result = dumpstate_task.get_future();
1863 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001864
1865 constexpr size_t timeout_sec = 30;
1866 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1867 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1868 if (!android::base::SetProperty("ctl.interface_restart",
1869 android::base::StringPrintf("%s/default",
1870 IDumpstateDevice::descriptor))) {
1871 MYLOGE("Couldn't restart dumpstate HAL\n");
1872 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001873 }
Wei Wang587eac92018-04-05 12:17:20 -07001874 // Wait some time for init to kill dumpstate vendor HAL
1875 constexpr size_t killing_timeout_sec = 10;
1876 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1877 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1878 "there might be racing in content\n", killing_timeout_sec);
1879 }
1880
1881 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1882 for (size_t i = 0; i < paths.size(); i++) {
1883 struct stat s;
1884 if (fstat(handle.get()->data[i], &s) == -1) {
1885 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1886 strerror(errno));
1887 file_sizes[i] = -1;
1888 continue;
1889 }
1890 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001891 }
1892
1893 for (size_t i = 0; i < paths.size(); i++) {
1894 if (file_sizes[i] == -1) {
1895 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001896 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001897 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001898 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001899 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001900 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001901 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001902 }
1903
Felipe Lemed8b94e52016-12-08 10:21:44 -08001904 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001905}
1906
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001907static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001908 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001909 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001910 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1911 " -h: display this help message\n"
1912 " -b: play sound file instead of vibrate, at beginning of job\n"
1913 " -e: play sound file instead of vibrate, at end of job\n"
1914 " -o: write to file (instead of stdout)\n"
1915 " -d: append date to filename (requires -o)\n"
1916 " -p: capture screenshot to filename.png (requires -o)\n"
1917 " -z: generate zipped file (requires -o)\n"
1918 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001919 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001920 " -q: disable vibrate\n"
1921 " -B: send broadcast when finished (requires -o)\n"
1922 " -P: send broadcast when started and update system properties on "
1923 "progress (requires -o and -B)\n"
1924 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1925 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001926 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001927 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001928}
1929
Wei Liuf87959e2016-08-26 14:51:42 -07001930static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001931 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001932}
1933
Felipe Leme1d486fe2016-10-14 18:06:47 -07001934bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001935 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001936 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001937 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001938 // Final timestamp
1939 char date[80];
1940 time_t the_real_now_please_stand_up = time(nullptr);
1941 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001942 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001943 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001944
Felipe Leme9a523ae2016-10-20 15:10:33 -07001945 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001946 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001947 return false;
1948 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001949 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001950 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001951 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001952 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001953
Felipe Leme0f3fb202016-06-10 17:10:53 -07001954 // Add log file (which contains stderr output) to zip...
1955 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001956 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001957 MYLOGE("Failed to add dumpstate log to .zip file\n");
1958 return false;
1959 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001960 // TODO: Should truncate the existing file.
1961 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001962 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1963 return false;
1964 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001965 fprintf(stderr, "\n");
1966
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001967 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001968 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001969 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001970 return false;
1971 }
1972
Felipe Leme1d486fe2016-10-14 18:06:47 -07001973 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1974 ds.zip_file.reset(nullptr);
1975
Felipe Lemee9d2c542016-11-15 11:48:26 -08001976 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001977 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001978
Felipe Leme1e9edc62015-12-21 16:02:13 -08001979 return true;
1980}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001981
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001982static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001983 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1984 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001985 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001986 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001987 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001988 }
1989
1990 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001991 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001992
1993 std::vector<uint8_t> buffer(65536);
1994 while (1) {
1995 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1996 if (bytes_read == 0) {
1997 break;
1998 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001999 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07002000 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002001 }
2002
Elliott Hughesc4dc1412016-04-12 16:28:31 -07002003 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002004 }
2005
Elliott Hughesc4dc1412016-04-12 16:28:31 -07002006 uint8_t hash[SHA256_DIGEST_LENGTH];
2007 SHA256_Final(hash, &ctx);
2008
2009 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
2010 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00002011 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002012 }
2013 hash_buffer[sizeof(hash_buffer) - 1] = 0;
2014 return std::string(hash_buffer);
2015}
2016
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002017static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2018 // clang-format off
2019 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2020 "--receiver-foreground", "--receiver-include-background", "-a", action};
2021 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002022
2023 am.insert(am.end(), args.begin(), args.end());
2024
Felipe Leme8d2410e2017-02-08 09:46:08 -08002025 RunCommand("", am,
2026 CommandOptions::WithTimeout(20)
2027 .Log("Sending broadcast: '%s'\n")
2028 .Always()
2029 .DropRoot()
2030 .RedirectStderr()
2031 .Build());
2032}
2033
Felipe Leme35b8cf12017-02-10 15:47:29 -08002034static void Vibrate(int duration_ms) {
2035 // clang-format off
2036 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
2037 CommandOptions::WithTimeout(10)
2038 .Log("Vibrate: '%s'\n")
2039 .Always()
2040 .Build());
2041 // clang-format on
2042}
2043
Nandana Dutt979388e2018-11-30 16:48:55 +00002044static void MaybeResolveSymlink(std::string* path) {
2045 std::string resolved_path;
2046 if (android::base::Readlink(*path, &resolved_path)) {
2047 *path = resolved_path;
2048 }
2049}
2050
Nandana Dutt4be45d12018-09-26 15:04:23 +01002051/*
2052 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2053 * if we are writing zip files and adds the version file.
2054 */
2055static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002056 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2057
Nandana Dutt4be45d12018-09-26 15:04:23 +01002058 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2059 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002060 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002061 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002062 char date[80];
2063 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2064 ds.name_ = date;
2065 } else {
2066 ds.name_ = "undated";
2067 }
2068
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002069 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002070 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002071 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002072 ds.base_name_ += "-wifi";
2073 }
2074
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002075 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002076 ds.screenshot_path_ = ds.GetPath(".png");
2077 }
2078 ds.tmp_path_ = ds.GetPath(".tmp");
2079 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2080
Nandana Dutt54dbd672019-01-11 12:58:05 +00002081 std::string destination = ds.options_->bugreport_fd.get() != -1
2082 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002083 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002084 MYLOGD(
2085 "Bugreport dir: %s\n"
2086 "Base name: %s\n"
2087 "Suffix: %s\n"
2088 "Log path: %s\n"
2089 "Temporary path: %s\n"
2090 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002091 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2092 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002093
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002094 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002095 ds.path_ = ds.GetPath(".zip");
2096 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2097 create_parent_dirs(ds.path_.c_str());
2098 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2099 if (ds.zip_file == nullptr) {
2100 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2101 } else {
2102 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2103 }
2104 ds.AddTextZipEntry("version.txt", ds.version_);
2105 }
2106}
2107
2108/*
2109 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2110 * printing zipped file status, etc.
2111 */
2112static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002113 /* check if user changed the suffix using system properties */
2114 std::string name =
2115 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2116 bool change_suffix = false;
2117 if (!name.empty()) {
2118 /* must whitelist which characters are allowed, otherwise it could cross directories */
2119 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2120 if (std::regex_match(name.c_str(), valid_regex)) {
2121 change_suffix = true;
2122 } else {
2123 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2124 }
2125 }
2126 if (change_suffix) {
2127 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2128 ds.name_ = name;
2129 if (!ds.screenshot_path_.empty()) {
2130 std::string new_screenshot_path = ds.GetPath(".png");
2131 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2132 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2133 new_screenshot_path.c_str(), strerror(errno));
2134 } else {
2135 ds.screenshot_path_ = new_screenshot_path;
2136 }
2137 }
2138 }
2139
2140 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002141 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002142 if (!ds.FinishZipFile()) {
2143 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2144 do_text_file = true;
2145 } else {
2146 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002147 // If the user has changed the suffix, we need to change the zip file name.
2148 std::string new_path = ds.GetPath(".zip");
2149 if (ds.path_ != new_path) {
2150 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2151 if (rename(ds.path_.c_str(), new_path.c_str())) {
2152 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2153 strerror(errno));
2154 } else {
2155 ds.path_ = new_path;
2156 }
2157 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002158 }
2159 }
2160 if (do_text_file) {
2161 ds.path_ = ds.GetPath(".txt");
2162 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2163 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2164 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2165 ds.path_.clear();
2166 }
2167 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002168 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002169 if (do_text_file) {
2170 dprintf(ds.control_socket_fd_,
2171 "FAIL:could not create zip file, check %s "
2172 "for more details\n",
2173 ds.log_path_.c_str());
2174 } else {
2175 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2176 }
2177 }
2178}
2179
2180/* Broadcasts that we are done with the bugreport */
2181static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002182 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002183 if (!ds.path_.empty()) {
2184 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002185 // clang-format off
2186
2187 std::vector<std::string> am_args = {
2188 "--receiver-permission", "android.permission.DUMP",
2189 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2190 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2191 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002192 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002193 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2194 };
2195 // clang-format on
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002196 if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002197 am_args.push_back("--es");
2198 am_args.push_back("android.intent.extra.SCREENSHOT");
2199 am_args.push_back(ds.screenshot_path_);
2200 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002201 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002202 am_args.push_back("--es");
2203 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002204 am_args.push_back(ds.options_->notification_title);
2205 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002206 am_args.push_back("--es");
2207 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002208 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002209 }
2210 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002211 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002212 am_args.push_back("--es");
2213 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002214 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002215 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2216 } else {
2217 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2218 }
2219 } else {
2220 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2221 }
2222}
2223
Nandana Dutt58d72e22018-11-16 10:30:48 +00002224static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2225 switch (mode) {
2226 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2227 return "BUGREPORT_FULL";
2228 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2229 return "BUGREPORT_INTERACTIVE";
2230 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2231 return "BUGREPORT_REMOTE";
2232 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2233 return "BUGREPORT_WEAR";
2234 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2235 return "BUGREPORT_TELEPHONY";
2236 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2237 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002238 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2239 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002240 }
2241}
2242
2243static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002244 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002245 switch (mode) {
2246 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2247 options->do_broadcast = true;
2248 options->do_fb = true;
2249 break;
2250 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002251 // Currently, the dumpstate binder is only used by Shell to update progress.
2252 options->do_start_service = true;
2253 options->do_progress_updates = true;
2254 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002255 options->do_broadcast = true;
2256 break;
2257 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002258 options->do_vibrate = false;
2259 options->is_remote_mode = true;
2260 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002261 options->do_broadcast = true;
2262 break;
2263 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002264 options->do_start_service = true;
2265 options->do_progress_updates = true;
2266 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002267 options->do_fb = true;
2268 options->do_broadcast = true;
2269 break;
2270 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002271 options->telephony_only = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002272 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002273 options->do_broadcast = true;
2274 break;
2275 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002276 options->wifi_only = true;
2277 options->do_zip_file = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002278 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002279 options->do_broadcast = true;
2280 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002281 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2282 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002283 }
2284}
2285
2286static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002287 // If the system property is not set, it's assumed to be a default bugreport.
2288 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002289
2290 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2291 if (!extra_options.empty()) {
2292 // Framework uses a system property to override some command-line args.
2293 // Currently, it contains the type of the requested bugreport.
2294 if (extra_options == "bugreportplus") {
2295 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002296 } else if (extra_options == "bugreportfull") {
2297 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002298 } else if (extra_options == "bugreportremote") {
2299 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2300 } else if (extra_options == "bugreportwear") {
2301 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2302 } else if (extra_options == "bugreporttelephony") {
2303 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2304 } else if (extra_options == "bugreportwifi") {
2305 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002306 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002307 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002308 }
2309 // Reset the property
2310 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2311 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002312 return mode;
2313}
2314
2315// TODO: Move away from system properties when we have options passed via binder calls.
2316/* Sets runtime options from the system properties and then clears those properties. */
2317static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2318 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2319 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002320
2321 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2322 if (!options->notification_title.empty()) {
2323 // Reset the property
2324 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2325
Nandana Duttdd8cca32018-11-14 10:10:29 +00002326 options->notification_description =
2327 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002328 if (!options->notification_description.empty()) {
2329 // Reset the property
2330 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2331 }
2332 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2333 options->notification_description.c_str());
2334 }
2335}
2336
Nandana Dutt58d72e22018-11-16 10:30:48 +00002337static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2338 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2339 MYLOGI("do_add_date: %d\n", options.do_add_date);
2340 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2341 MYLOGI("use_socket: %d\n", options.use_socket);
2342 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2343 MYLOGI("do_fb: %d\n", options.do_fb);
2344 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2345 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2346 MYLOGI("show_header_only: %d\n", options.show_header_only);
2347 MYLOGI("do_start_service: %d\n", options.do_start_service);
2348 MYLOGI("telephony_only: %d\n", options.telephony_only);
2349 MYLOGI("wifi_only: %d\n", options.wifi_only);
2350 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002351 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002352 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2353 MYLOGI("args: %s\n", options.args.c_str());
2354 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2355 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2356}
2357
Nandana Dutt54dbd672019-01-11 12:58:05 +00002358void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2359 const android::base::unique_fd& bugreport_fd_in,
2360 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002361 // In the new API world, date is always added; output is always a zip file.
2362 // TODO(111441001): remove these options once they are obsolete.
2363 do_add_date = true;
2364 do_zip_file = true;
2365
Nandana Dutt54dbd672019-01-11 12:58:05 +00002366 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2367 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2368 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002369
2370 extra_options = ModeToString(bugreport_mode);
2371 SetOptionsFromMode(bugreport_mode, this);
2372}
2373
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002374Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2375 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002376 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002377 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002378 switch (c) {
2379 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002380 case 'd': do_add_date = true; break;
2381 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002382 // o=use_outfile not supported anymore.
2383 // TODO(b/111441001): Remove when all callers have migrated.
2384 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002385 case 's': use_socket = true; break;
2386 case 'S': use_control_socket = true; break;
2387 case 'v': show_header_only = true; break;
2388 case 'q': do_vibrate = false; break;
2389 case 'p': do_fb = true; break;
2390 case 'P': do_progress_updates = true; break;
2391 case 'R': is_remote_mode = true; break;
2392 case 'B': do_broadcast = true; break;
2393 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002394 case 'w':
2395 // This was already processed
2396 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002397 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002398 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002399 break;
2400 default:
2401 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002402 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002403 break;
2404 // clang-format on
2405 }
2406 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002407
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002408 // TODO: use helper function to convert argv into a string
2409 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002410 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002411 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002412 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002413 }
2414 }
2415
2416 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2417 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002418
2419 SetOptionsFromProperties(this);
2420 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002421}
2422
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002423bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002424 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002425 return false;
2426 }
2427
Nandana Dutt9a76d202019-01-21 15:56:48 +00002428 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002429 return false;
2430 }
2431
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002432 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002433 return false;
2434 }
2435
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002436 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002437 return false;
2438 }
2439
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002440 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002441 return false;
2442 }
2443 return true;
2444}
2445
Nandana Dutt197661d2018-11-16 16:40:21 +00002446void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2447 options_ = std::move(options);
2448}
2449
Nandana Duttd2f5f082019-01-18 17:13:52 +00002450Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2451 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002452 if (listener_ != nullptr) {
2453 switch (status) {
2454 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002455 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002456 break;
2457 case Dumpstate::RunStatus::HELP:
2458 break;
2459 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002460 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002461 break;
2462 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002463 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2464 break;
2465 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2466 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2467 break;
2468 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2469 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002470 break;
2471 }
2472 }
2473 return status;
2474}
2475
Nandana Dutt979388e2018-11-30 16:48:55 +00002476/*
2477 * Dumps relevant information to a bugreport based on the given options.
2478 *
2479 * The bugreport can be dumped to a file or streamed to a socket.
2480 *
2481 * How dumping to file works:
2482 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2483 * stderr is redirected a log file.
2484 *
2485 * The temporary bugreport is then populated via printfs, dumping contents of files and
2486 * output of commands to stdout.
2487 *
2488 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2489 * text file.
2490 *
2491 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2492 * gets added to the archive.
2493 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002494 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2495 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002496 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002497Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2498 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002499 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002500 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002501 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002502 return RunStatus::INVALID_INPUT;
2503 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002504 /* set as high priority, and protect from OOM killer */
2505 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002506
Felipe Lemed071c682016-10-20 16:48:00 -07002507 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002508 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002509 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002510 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002511 } else {
2512 /* fallback to kernels <= 2.6.35 */
2513 oom_adj = fopen("/proc/self/oom_adj", "we");
2514 if (oom_adj) {
2515 fputs("-17", oom_adj);
2516 fclose(oom_adj);
2517 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002518 }
2519
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002520 if (version_ == VERSION_DEFAULT) {
2521 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002522 }
2523
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002524 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002525 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002526 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002527 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002528 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002529 }
2530
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002531 if (options_->show_header_only) {
2532 PrintHeader();
2533 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002534 }
2535
Nandana Duttd2f5f082019-01-18 17:13:52 +00002536 if (options_->bugreport_fd.get() != -1) {
2537 // If the output needs to be copied over to the caller's fd, get user consent.
2538 android::String16 package(calling_package.c_str());
2539 CheckUserConsent(calling_uid, package);
2540 }
2541
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002542 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002543 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002544
2545 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002546 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002547 is_redirecting
2548 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2549 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002550 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002551
Felipe Lemed071c682016-10-20 16:48:00 -07002552 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002553 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002554 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002555 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2556
2557 MYLOGI("begin\n");
2558
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002559 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002560
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002561 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002562 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002563 MYLOGI("Starting 'dumpstate' service\n");
2564 android::status_t ret;
2565 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2566 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2567 }
2568 }
2569
Felipe Lemef0292972016-11-22 13:57:05 -08002570 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002571 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2572 }
2573
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002574 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2575 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002576
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002577 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002578
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002579 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002580
Christopher Ferrised9354f2014-10-01 17:35:01 -07002581 // If we are going to use a socket, do it as early as possible
2582 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002583 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002584 if (!redirect_to_socket(stdout, "dumpstate")) {
2585 return ERROR;
2586 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002587 }
2588
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002589 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002590 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002591 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002592 if (control_socket_fd_ == -1) {
2593 return ERROR;
2594 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002595 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002596 }
2597
Felipe Leme71bbfc52015-11-23 14:14:51 -08002598 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002599 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002600
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002601 if (options_->do_progress_updates) {
2602 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002603 // clang-format off
2604 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002605 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002606 "--es", "android.intent.extra.NAME", name_,
2607 "--ei", "android.intent.extra.ID", std::to_string(id_),
2608 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2609 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002610 };
2611 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002612 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002613 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002614 if (options_->use_control_socket) {
2615 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002616 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002617 }
2618 }
2619
Nick Kralevichf3599b32016-01-25 15:05:16 -08002620 /* read /proc/cmdline before dropping root */
2621 FILE *cmdline = fopen("/proc/cmdline", "re");
2622 if (cmdline) {
2623 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2624 fclose(cmdline);
2625 }
2626
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002627 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002628 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002629 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002630
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002631 if (options_->do_fb && do_early_screenshot_) {
2632 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002633 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002634 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002635 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002636 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002637 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002638 }
2639 }
2640
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002641 if (options_->do_zip_file && zip_file != nullptr) {
2642 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2643 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002644 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002645 }
2646 }
2647
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002648 int dup_stdout_fd;
2649 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002650 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002651 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002652 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002653 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2654 return ERROR;
2655 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002656 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2657 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2658 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002659 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002660
2661 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2662 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002663 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002664 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002665 /* TODO: rather than generating a text file now and zipping it later,
2666 it would be more efficient to redirect stdout to the zip entry
2667 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002668 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2669 return ERROR;
2670 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002671 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002672 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002673 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002674 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002675 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002676
2677 // Don't buffer stdout
2678 setvbuf(stdout, nullptr, _IONBF, 0);
2679
Felipe Leme608385d2016-02-01 10:35:38 -08002680 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2681 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002682 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002683 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002684
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002685 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002686 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002687 DumpstateBoard();
2688 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002689 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002690 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002691 // Dump state for the default case. This also drops root.
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002692 RunStatus s = DumpstateDefault();
2693 if (s != RunStatus::OK) {
2694 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2695 HandleUserConsentDenied();
2696 }
2697 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002698 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002699 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002700
Felipe Leme55b42a62015-11-10 17:39:08 -08002701 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002702 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002703 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002704 }
2705
Nandana Duttd2f5f082019-01-18 17:13:52 +00002706 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002707 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002708 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002709 }
2710
Nandana Duttd2f5f082019-01-18 17:13:52 +00002711 // Share the final file with the caller if the user has consented.
2712 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2713 if (options_->bugreport_fd.get() != -1) {
2714 status = CopyBugreportIfUserConsented();
2715 if (status != Dumpstate::RunStatus::OK &&
2716 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2717 // Do an early return if there were errors. We make an exception for consent
2718 // timing out because it's possible the user got distracted. In this case the
2719 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002720 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002721 return status;
2722 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002723 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002724 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2725 options_->screenshot_fd.get());
2726 if (copy_succeeded) {
2727 android::os::UnlinkAndLogOnError(screenshot_path_);
2728 }
2729 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002730 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2731 MYLOGI(
2732 "Did not receive user consent yet."
2733 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaur57627412019-04-17 16:00:09 +01002734 const String16 incidentcompanion("incidentcompanion");
2735 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2736 if (ics != nullptr) {
2737 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2738 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2739 consent_callback_.get());
2740 } else {
2741 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2742 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002743 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002744 }
2745
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002746 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002747 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002748 for (int i = 0; i < 3; i++) {
2749 Vibrate(75);
2750 usleep((75 + 50) * 1000);
2751 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002752 }
2753
Jeff Brown1dc94e32014-09-11 14:15:27 -07002754 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002755 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002756 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002757 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002758 }
2759
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002760 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2761 progress_->GetInitialMax());
2762 progress_->Save();
2763 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002764
Felipe Leme107a05f2016-03-08 15:11:15 -08002765 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002766 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002767 }
2768
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002769 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002770 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002771 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002772 }
2773
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002774 tombstone_data_.clear();
2775 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002776
Nandana Duttd2f5f082019-01-18 17:13:52 +00002777 return (consent_callback_ != nullptr &&
2778 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2779 ? USER_CONSENT_TIMED_OUT
2780 : RunStatus::OK;
2781}
2782
2783void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2784 consent_callback_ = new ConsentCallback();
2785 const String16 incidentcompanion("incidentcompanion");
2786 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2787 if (ics != nullptr) {
2788 MYLOGD("Checking user consent via incidentcompanion service\n");
2789 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2790 calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
2791 consent_callback_.get());
2792 } else {
2793 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2794 }
2795}
2796
Nandana Duttbbdb5b42019-03-12 10:52:56 +00002797bool Dumpstate::IsUserConsentDenied() const {
2798 return ds.consent_callback_ != nullptr &&
2799 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2800}
2801
Nandana Duttd2f5f082019-01-18 17:13:52 +00002802void Dumpstate::CleanupFiles() {
2803 android::os::UnlinkAndLogOnError(tmp_path_);
2804 android::os::UnlinkAndLogOnError(screenshot_path_);
2805 android::os::UnlinkAndLogOnError(path_);
2806}
2807
2808Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2809 MYLOGD("User denied consent; deleting files and returning\n");
2810 CleanupFiles();
2811 return USER_CONSENT_DENIED;
2812}
2813
2814Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2815 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2816 // user consent.
2817 UserConsentResult consent_result = consent_callback_->getResult();
2818 if (consent_result == UserConsentResult::UNAVAILABLE) {
2819 // User has not responded yet.
2820 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2821 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2822 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2823 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2824 sleep(delay_seconds);
2825 }
2826 consent_result = consent_callback_->getResult();
2827 }
2828 if (consent_result == UserConsentResult::DENIED) {
2829 // User has explicitly denied sharing with the app. To be safe delete the
2830 // internal bugreport & tmp files.
2831 return HandleUserConsentDenied();
2832 }
2833 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002834 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2835 if (copy_succeeded) {
2836 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002837 }
2838 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2839 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2840 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2841 // Since we do not have user consent to share the bugreport it does not get
2842 // copied over to the calling app but remains in the internal directory from
2843 // where the user can manually pull it.
2844 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2845 }
2846 // Unknown result; must be a programming error.
2847 MYLOGE("Unknown user consent result:%d\n", consent_result);
2848 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002849}
2850
Nandana Duttf02564e2019-02-15 15:24:24 +00002851Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002852 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2853 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2854 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002855 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002856 // When directly running dumpstate binary, the output is not expected to be written
2857 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002858 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002859
2860 // calling_uid and calling_package are for user consent to share the bugreport with
2861 // an app; they are irrelvant here because bugreport is only written to a local
2862 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002863 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002864 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002865 return status;
2866}
2867
2868/* Main entry point for dumpstate binary. */
2869int run_main(int argc, char* argv[]) {
2870 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002871
2872 switch (status) {
2873 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002874 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002875 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002876 ShowUsage();
2877 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002878 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002879 fprintf(stderr, "Invalid combination of args\n");
2880 ShowUsage();
2881 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002882 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002883 FALLTHROUGH_INTENDED;
2884 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2885 FALLTHROUGH_INTENDED;
2886 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002887 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002888 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002889}