blob: 5de40776b9443a86e5b0ec2b919d1ec6e2d546d6 [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>
Nikita Ioffea325a572019-05-16 19:49:47 +010022#include <inttypes.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070024#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070025#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070026#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080029#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070030#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070031#include <sys/resource.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/wait.h>
35#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070036
37#include <chrono>
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>
42#include <regex>
43#include <set>
44#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070045#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010046#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070047
Felipe Leme96c2bbb2016-09-26 09:21:21 -070048#include <android-base/file.h>
49#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070050#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080051#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070052#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070053#include <android-base/unique_fd.h>
Nikita Ioffea325a572019-05-16 19:49:47 +010054#include <android/content/pm/IPackageManagerNative.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>
Nikita Ioffea325a572019-05-16 19:49:47 +010058#include <binder/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080059#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070060#include <cutils/properties.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000061#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080062#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000063#include <dumputils/dump_utils.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080064#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070065#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070066#include <private/android_filesystem_config.h>
67#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080068#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070069#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080070#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080071#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070072#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070073#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080074
Steven Morelandcb7ef822016-11-29 13:20:37 -080075using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080076using ::std::literals::chrono_literals::operator""ms;
77using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080078
Felipe Leme47e9be22016-12-21 15:37:07 -080079// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080080using android::defaultServiceManager;
81using android::Dumpsys;
82using android::INVALID_OPERATION;
83using android::IServiceManager;
84using android::OK;
85using android::sp;
86using android::status_t;
87using android::String16;
88using android::String8;
89using android::TIMED_OUT;
90using android::UNKNOWN_ERROR;
91using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +000092using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +000093using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -080094using android::os::dumpstate::CommandOptions;
95using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080096using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080097using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080098using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080099
Nandana Duttd2f5f082019-01-18 17:13:52 +0000100typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
101
Colin Crossf45fa6b2012-03-26 12:38:26 -0700102/* read before root is shed */
103static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700104static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000105static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700106
Felipe Leme1d486fe2016-10-14 18:06:47 -0700107// TODO: variables and functions below should be part of dumpstate object
108
Felipe Leme635ca312016-01-05 14:23:02 -0800109static std::set<std::string> mount_points;
110void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800111
Todd Poynor2a83daa2013-11-22 15:44:22 -0800112#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700113#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700114#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800115
Felipe Lemee82a27d2016-01-05 13:35:44 -0800116#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700117#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700118#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700119#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100120#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
121#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800122#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900123#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800124#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700125
Narayan Kamath8f788292017-05-25 13:20:39 +0100126// TODO(narayan): Since this information has to be kept in sync
127// with tombstoned, we should just put it in a common header.
128//
129// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100130static const std::string TOMBSTONE_DIR = "/data/tombstones/";
131static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
132static const std::string ANR_DIR = "/data/anr/";
133static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700134
Felipe Lemee844a9d2016-09-21 15:01:39 -0700135// TODO: temporary variables and functions used during C++ refactoring
136static Dumpstate& ds = Dumpstate::GetInstance();
Nandana Dutt979388e2018-11-30 16:48:55 +0000137
Nandana Dutt5c390032019-03-12 10:52:56 +0000138#define RETURN_IF_USER_DENIED_CONSENT() \
139 if (ds.IsUserConsentDenied()) { \
140 MYLOGE("Returning early as user denied consent to share bugreport with calling app."); \
141 return Dumpstate::RunStatus::USER_CONSENT_DENIED; \
142 }
143
144// Runs func_ptr, but checks user consent before and after running it. Returns USER_CONSENT_DENIED
145// if consent is found to be denied.
146#define RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(func_ptr, ...) \
147 RETURN_IF_USER_DENIED_CONSENT(); \
148 func_ptr(__VA_ARGS__); \
149 RETURN_IF_USER_DENIED_CONSENT();
150
Nandana Dutt979388e2018-11-30 16:48:55 +0000151namespace android {
152namespace os {
153namespace {
154
155static int Open(std::string path, int flags, mode_t mode = 0) {
156 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
157 if (fd == -1) {
158 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
159 }
160 return fd;
161}
162
Nandana Dutt979388e2018-11-30 16:48:55 +0000163
164static int OpenForRead(std::string path) {
165 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
166}
167
168bool CopyFile(int in_fd, int out_fd) {
169 char buf[4096];
170 ssize_t byte_count;
171 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
172 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
173 return false;
174 }
175 }
176 return (byte_count != -1);
177}
178
179static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000180 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000181
182 // Obtain a handle to the source file.
183 android::base::unique_fd in_fd(OpenForRead(input_file));
184 if (out_fd != -1 && in_fd.get() != -1) {
185 if (CopyFile(in_fd.get(), out_fd)) {
186 return true;
187 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000188 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000189 }
190 return false;
191}
192
Nandana Duttd2f5f082019-01-18 17:13:52 +0000193static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000194 if (unlink(file.c_str())) {
195 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000196 return false;
197 }
198 return true;
199}
Nandana Dutt979388e2018-11-30 16:48:55 +0000200
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +0000201static bool IsFileEmpty(const std::string& file_path) {
202 std::ifstream file(file_path, std::ios::binary | std::ios::ate);
203 if(file.bad()) {
204 MYLOGE("Cannot open file: %s\n", file_path.c_str());
205 return true;
206 }
207 return file.tellg() <= 0;
208}
209
Nikita Ioffea325a572019-05-16 19:49:47 +0100210int64_t GetModuleMetadataVersion() {
211 auto binder = defaultServiceManager()->getService(android::String16("package_native"));
212 if (binder == nullptr) {
213 MYLOGE("Failed to retrieve package_native service");
214 return 0L;
215 }
216 auto package_service = android::interface_cast<content::pm::IPackageManagerNative>(binder);
217 std::string package_name;
218 auto status = package_service->getModuleMetadataPackageName(&package_name);
219 if (!status.isOk()) {
220 MYLOGE("Failed to retrieve module metadata package name: %s", status.toString8().c_str());
221 return 0L;
222 }
223 MYLOGD("Module metadata package name: %s", package_name.c_str());
224 int64_t version_code;
225 status = package_service->getVersionCodeForPackage(android::String16(package_name.c_str()),
226 &version_code);
227 if (!status.isOk()) {
228 MYLOGE("Failed to retrieve module metadata version: %s", status.toString8().c_str());
229 return 0L;
230 }
231 return version_code;
232}
233
Nandana Dutt979388e2018-11-30 16:48:55 +0000234} // namespace
235} // namespace os
236} // namespace android
237
Felipe Leme678727a2016-09-21 17:22:11 -0700238static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
239 const CommandOptions& options = CommandOptions::DEFAULT) {
240 return ds.RunCommand(title, fullCommand, options);
241}
242static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800243 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800244 long dumpsysTimeoutMs = 0) {
245 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700246}
247static int DumpFile(const std::string& title, const std::string& path) {
248 return ds.DumpFile(title, path);
249}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800250
Felipe Lemee844a9d2016-09-21 15:01:39 -0700251// Relative directory (inside the zip) for all files copied as-is into the bugreport.
252static const std::string ZIP_ROOT_DIR = "FS";
253
Vishnu Naire97d6122018-01-18 13:58:56 -0800254static const std::string kProtoPath = "proto/";
255static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700256static const std::string kDumpstateBoardFiles[] = {
257 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700258 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700259};
260static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
261
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700262static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700263static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700264static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700265static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
266static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700267
Felipe Lemef0292972016-11-22 13:57:05 -0800268static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
269
Narayan Kamath8f788292017-05-25 13:20:39 +0100270/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100271 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
272 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
273 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700274 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100275 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700276static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
277 const std::string& file_prefix,
278 bool limit_by_mtime,
279 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100280 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
281
Narayan Kamathbd863722017-06-01 18:50:12 +0100282 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100283
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700284 if (dump_dir == nullptr) {
285 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700286 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700287 }
288
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700289 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100290 struct dirent* entry = nullptr;
291 while ((entry = readdir(dump_dir.get()))) {
292 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100293 continue;
294 }
295
Narayan Kamathbd863722017-06-01 18:50:12 +0100296 const std::string base_name(entry->d_name);
297 if (base_name.find(file_prefix) != 0) {
298 continue;
299 }
300
301 const std::string abs_path = dir_path + base_name;
302 android::base::unique_fd fd(
303 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
304 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700305 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100306 break;
307 }
308
309 struct stat st = {};
310 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700311 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100312 continue;
313 }
314
Narayan Kamath3f31b632018-02-22 19:42:36 +0000315 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100316 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100317 continue;
318 }
319
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700320 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700321 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100322
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700323 // Sort in descending modification time so that we only keep the newest
324 // reports if |limit_by_count| is true.
325 std::sort(dump_data.begin(), dump_data.end(),
326 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100327
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700328 if (limit_by_count && dump_data.size() > 10) {
329 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700330 }
331
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700332 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100333}
334
Narayan Kamathbd863722017-06-01 18:50:12 +0100335static bool AddDumps(const std::vector<DumpData>::const_iterator start,
336 const std::vector<DumpData>::const_iterator end,
337 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100338 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100339 for (auto it = start; it != end; ++it) {
340 const std::string& name = it->name;
341 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100342 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100343
344 // Seek to the beginning of the file before dumping any data. A given
345 // DumpData entry might be dumped multiple times in the report.
346 //
347 // For example, the most recent ANR entry is dumped to the body of the
348 // main entry and it also shows up as a separate entry in the bugreport
349 // ZIP file.
350 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
351 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
352 strerror(errno));
353 }
354
Narayan Kamath8f788292017-05-25 13:20:39 +0100355 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800356 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100357 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100358 }
359 } else {
360 dump_file_from_fd(type_name, name.c_str(), fd);
361 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100362 }
363
364 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700365}
366
Felipe Leme635ca312016-01-05 14:23:02 -0800367// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700368void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800369 char path[PATH_MAX];
370
371 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
372 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700373 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800374 char linkname[PATH_MAX];
375 ssize_t r = readlink(path, linkname, PATH_MAX);
376 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800377 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800378 return;
379 }
380 linkname[r] = '\0';
381
382 if (mount_points.find(linkname) == mount_points.end()) {
383 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700384 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700385 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800386 mount_points.insert(linkname);
387 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800388 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800389 }
390 }
391}
392
393void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700394 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700395 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800396 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800397 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700398 for_each_pid(do_mountinfo, nullptr);
399 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800400}
401
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700402static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
403{
404 DIR *d;
405 struct dirent *de;
406 char path[PATH_MAX];
407
408 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700409 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700410 return;
411 }
412
413 while ((de = readdir(d))) {
414 if (de->d_type != DT_LNK) {
415 continue;
416 }
417 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700418 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700419 }
420
421 closedir(d);
422}
423
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700424
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700425
426// dump anrd's trace and add to the zip file.
427// 1. check if anrd is running on this device.
428// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
429// 3. wait until the trace generation completes and add to the zip file.
430static bool dump_anrd_trace() {
431 unsigned int pid;
432 char buf[50], path[PATH_MAX];
433 struct dirent *trace;
434 struct stat st;
435 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700436 int retry = 5;
437 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700438 long long cur_size = 0;
439 const char *trace_path = "/data/misc/anrd/";
440
Felipe Leme1d486fe2016-10-14 18:06:47 -0700441 if (!ds.IsZipping()) {
442 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700443 return false;
444 }
445
446 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700447 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700448
449 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700450 if (stat(trace_path, &st) == 0) {
451 old_mtime = st.st_mtime;
452 } else {
453 MYLOGE("Failed to find: %s\n", trace_path);
454 return false;
455 }
456
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700457 // send SIGUSR1 to the anrd to generate a trace.
458 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700459 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700460 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700461 MYLOGE("anrd signal timed out. Please manually collect trace\n");
462 return false;
463 }
464
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700465 while (retry-- > 0 && old_mtime == st.st_mtime) {
466 sleep(1);
467 stat(trace_path, &st);
468 }
469
470 if (retry < 0 && old_mtime == st.st_mtime) {
471 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
472 return false;
473 }
474
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700475 // identify the trace file by its creation time.
476 if (!(trace_dir = opendir(trace_path))) {
477 MYLOGE("Can't open trace file under %s\n", trace_path);
478 }
479 while ((trace = readdir(trace_dir))) {
480 if (strcmp(trace->d_name, ".") == 0
481 || strcmp(trace->d_name, "..") == 0) {
482 continue;
483 }
484 sprintf(path, "%s%s", trace_path, trace->d_name);
485 if (stat(path, &st) == 0) {
486 if (st.st_ctime > max_ctime) {
487 max_ctime = st.st_ctime;
488 sprintf(buf, "%s", trace->d_name);
489 }
490 }
491 }
492 closedir(trace_dir);
493
494 // Wait until the dump completes by checking the size of the trace.
495 if (max_ctime > 0) {
496 sprintf(path, "%s%s", trace_path, buf);
497 while(true) {
498 sleep(1);
499 if (stat(path, &st) == 0) {
500 if (st.st_size == cur_size) {
501 break;
502 } else if (st.st_size > cur_size) {
503 cur_size = st.st_size;
504 } else {
505 return false;
506 }
507 } else {
508 MYLOGE("Cant stat() %s anymore\n", path);
509 return false;
510 }
511 }
512 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700513 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700514 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
515 } else {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000516 android::os::UnlinkAndLogOnError(path);
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700517 return true;
518 }
519 } else {
520 MYLOGE("Can't stats any trace file under %s\n", trace_path);
521 }
522 }
523 return false;
524}
525
Mark Salyzyn326842f2015-04-30 09:49:41 -0700526static bool skip_not_stat(const char *path) {
527 static const char stat[] = "/stat";
528 size_t len = strlen(path);
529 if (path[len - 1] == '/') { /* Directory? */
530 return false;
531 }
532 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
533}
534
Felipe Leme4c2d6632016-09-28 14:32:00 -0700535static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800536 return false;
537}
538
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700539unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700540
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800541//
542// stat offsets
543// Name units description
544// ---- ----- -----------
545// read I/Os requests number of read I/Os processed
546#define __STAT_READ_IOS 0
547// read merges requests number of read I/Os merged with in-queue I/O
548#define __STAT_READ_MERGES 1
549// read sectors sectors number of sectors read
550#define __STAT_READ_SECTORS 2
551// read ticks milliseconds total wait time for read requests
552#define __STAT_READ_TICKS 3
553// write I/Os requests number of write I/Os processed
554#define __STAT_WRITE_IOS 4
555// write merges requests number of write I/Os merged with in-queue I/O
556#define __STAT_WRITE_MERGES 5
557// write sectors sectors number of sectors written
558#define __STAT_WRITE_SECTORS 6
559// write ticks milliseconds total wait time for write requests
560#define __STAT_WRITE_TICKS 7
561// in_flight requests number of I/Os currently in flight
562#define __STAT_IN_FLIGHT 8
563// io_ticks milliseconds total time this block device has been active
564#define __STAT_IO_TICKS 9
565// time_in_queue milliseconds total wait time for all requests
566#define __STAT_IN_QUEUE 10
567#define __STAT_NUMBER_FIELD 11
568//
569// read I/Os, write I/Os
570// =====================
571//
572// These values increment when an I/O request completes.
573//
574// read merges, write merges
575// =========================
576//
577// These values increment when an I/O request is merged with an
578// already-queued I/O request.
579//
580// read sectors, write sectors
581// ===========================
582//
583// These values count the number of sectors read from or written to this
584// block device. The "sectors" in question are the standard UNIX 512-byte
585// sectors, not any device- or filesystem-specific block size. The
586// counters are incremented when the I/O completes.
587#define SECTOR_SIZE 512
588//
589// read ticks, write ticks
590// =======================
591//
592// These values count the number of milliseconds that I/O requests have
593// waited on this block device. If there are multiple I/O requests waiting,
594// these values will increase at a rate greater than 1000/second; for
595// example, if 60 read requests wait for an average of 30 ms, the read_ticks
596// field will increase by 60*30 = 1800.
597//
598// in_flight
599// =========
600//
601// This value counts the number of I/O requests that have been issued to
602// the device driver but have not yet completed. It does not include I/O
603// requests that are in the queue but not yet issued to the device driver.
604//
605// io_ticks
606// ========
607//
608// This value counts the number of milliseconds during which the device has
609// had I/O requests queued.
610//
611// time_in_queue
612// =============
613//
614// This value counts the number of milliseconds that I/O requests have waited
615// on this block device. If there are multiple I/O requests waiting, this
616// value will increase as the product of the number of milliseconds times the
617// number of requests waiting (see "read ticks" above for an example).
618#define S_TO_MS 1000
619//
620
Mark Salyzyn326842f2015-04-30 09:49:41 -0700621static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800622 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700623 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700624 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700625 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700626 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700627 getline(&buffer, &i, fp);
628 fclose(fp);
629 if (!buffer) {
630 return -errno;
631 }
632 i = strlen(buffer);
633 while ((i > 0) && (buffer[i - 1] == '\n')) {
634 buffer[--i] = '\0';
635 }
636 if (!*buffer) {
637 free(buffer);
638 return 0;
639 }
640 z = true;
641 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800642 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700643 if (fields[i] != 0) {
644 z = false;
645 }
646 }
647 if (z) { /* never accessed */
648 free(buffer);
649 return 0;
650 }
651
Wei Wang509bb5d2017-06-09 14:42:12 -0700652 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
653 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700654 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700655
656 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
657 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
658 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700659 free(buffer);
660
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800661 if (fields[__STAT_IO_TICKS]) {
662 unsigned long read_perf = 0;
663 unsigned long read_ios = 0;
664 if (fields[__STAT_READ_TICKS]) {
665 unsigned long long divisor = fields[__STAT_READ_TICKS]
666 * fields[__STAT_IO_TICKS];
667 read_perf = ((unsigned long long)SECTOR_SIZE
668 * fields[__STAT_READ_SECTORS]
669 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
670 / divisor;
671 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
672 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
673 / divisor;
674 }
675
676 unsigned long write_perf = 0;
677 unsigned long write_ios = 0;
678 if (fields[__STAT_WRITE_TICKS]) {
679 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
680 * fields[__STAT_IO_TICKS];
681 write_perf = ((unsigned long long)SECTOR_SIZE
682 * fields[__STAT_WRITE_SECTORS]
683 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
684 / divisor;
685 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
686 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
687 / divisor;
688 }
689
690 unsigned queue = (fields[__STAT_IN_QUEUE]
691 + (fields[__STAT_IO_TICKS] >> 1))
692 / fields[__STAT_IO_TICKS];
693
694 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700695 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 -0800696 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700697 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 -0800698 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800699 }
700
701 /* bugreport timeout factor adjustment */
702 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
703 worst_write_perf = write_perf;
704 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700705 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700706 return 0;
707}
708
Yao Chenbe3bbc12018-01-17 16:31:10 -0800709static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
710
711/* timeout in ms to read a list of buffers */
712static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
713 unsigned long timeout_ms = 0;
714 for (const auto& buffer : buffers) {
715 log_id_t id = android_name_to_log_id(buffer.c_str());
716 unsigned long property_size = __android_logger_get_buffer_size(id);
717 /* Engineering margin is ten-fold our guess */
718 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
719 }
720 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700721}
722
Nandana Duttd2f5f082019-01-18 17:13:52 +0000723Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
724}
725
726android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
727 std::lock_guard<std::mutex> lock(lock_);
728 result_ = APPROVED;
729 MYLOGD("User approved consent to share bugreport\n");
730 return android::binder::Status::ok();
731}
732
733android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
734 std::lock_guard<std::mutex> lock(lock_);
735 result_ = DENIED;
736 MYLOGW("User denied consent to share bugreport\n");
737 return android::binder::Status::ok();
738}
739
740UserConsentResult Dumpstate::ConsentCallback::getResult() {
741 std::lock_guard<std::mutex> lock(lock_);
742 return result_;
743}
744
745uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
746 return Nanotime() - start_time_;
747}
748
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700749void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700750 std::string build, fingerprint, radio, bootloader, network;
751 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700752
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700753 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
754 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700755 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
756 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
757 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700758 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700759
Felipe Lemed8b94e52016-12-08 10:21:44 -0800760 printf("========================================================\n");
761 printf("== dumpstate: %s\n", date);
762 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700763
Felipe Lemed8b94e52016-12-08 10:21:44 -0800764 printf("\n");
765 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700766 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800767 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
768 printf("Bootloader: %s\n", bootloader.c_str());
769 printf("Radio: %s\n", radio.c_str());
770 printf("Network: %s\n", network.c_str());
Nikita Ioffea325a572019-05-16 19:49:47 +0100771 int64_t module_metadata_version = android::os::GetModuleMetadataVersion();
772 if (module_metadata_version != 0) {
773 printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
774 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700775
Felipe Lemed8b94e52016-12-08 10:21:44 -0800776 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800777 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800778 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800779 printf("Uptime: ");
780 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
781 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800782 printf("Bugreport format version: %s\n", version_.c_str());
783 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 +0100784 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800785 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800786}
787
Felipe Leme24b66ee2016-06-16 10:55:26 -0700788// List of file extensions that can cause a zip file attachment to be rejected by some email
789// service providers.
790static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
791 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
792 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
793 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
794};
795
Vishnu Naire97d6122018-01-18 13:58:56 -0800796status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
797 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700798 if (!IsZipping()) {
799 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
800 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800801 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800802 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700803 std::string valid_name = entry_name;
804
805 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700806 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700807 if (idx != std::string::npos) {
808 std::string extension = entry_name.substr(idx);
809 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
810 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
811 valid_name = entry_name + ".renamed";
812 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
813 }
814 }
815
Felipe Leme6fe9db62016-02-12 09:04:16 -0800816 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
817 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700818 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
819 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700820 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700821 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700822 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800823 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800824 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000825 bool finished_entry = false;
826 auto finish_entry = [this, &finished_entry] {
827 if (!finished_entry) {
828 // This should only be called when we're going to return an earlier error,
829 // which would've been logged. This may imply the file is already corrupt
830 // and any further logging from FinishEntry is more likely to mislead than
831 // not.
832 this->zip_writer_->FinishEntry();
833 }
834 };
835 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800836 auto start = std::chrono::steady_clock::now();
837 auto end = start + timeout;
838 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800839
Felipe Leme770410d2016-01-26 17:07:14 -0800840 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800841 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800842 if (timeout.count() > 0) {
843 // lambda to recalculate the timeout.
844 auto time_left_ms = [end]() {
845 auto now = std::chrono::steady_clock::now();
846 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
847 return std::max(diff.count(), 0LL);
848 };
849
850 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
851 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000852 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
853 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800854 return -errno;
855 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000856 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800857 entry_name.c_str(), strerror(errno), timeout.count());
858 return TIMED_OUT;
859 }
860 }
861
Zach Riggle22200402016-08-18 01:01:24 -0400862 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800863 if (bytes_read == 0) {
864 break;
865 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800866 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800867 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800868 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700869 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800870 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700871 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800872 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800873 }
874 }
875
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700876 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000877 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700878 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700879 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800880 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800881 }
882
Vishnu Naire97d6122018-01-18 13:58:56 -0800883 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800884}
885
Felipe Leme1d486fe2016-10-14 18:06:47 -0700886bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
887 android::base::unique_fd fd(
888 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700889 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800890 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800891 return false;
892 }
893
Vishnu Naire97d6122018-01-18 13:58:56 -0800894 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800895}
896
897/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700898static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800899 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800900}
901
Felipe Leme1d486fe2016-10-14 18:06:47 -0700902void Dumpstate::AddDir(const std::string& dir, bool recursive) {
903 if (!IsZipping()) {
904 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800905 return;
906 }
Felipe Leme678727a2016-09-21 17:22:11 -0700907 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800908 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700909 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800910}
911
Felipe Leme1d486fe2016-10-14 18:06:47 -0700912bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
913 if (!IsZipping()) {
914 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
915 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800916 return false;
917 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800918 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700919 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700920 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700921 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700922 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800923 return false;
924 }
925
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700926 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700927 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700928 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700929 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800930 return false;
931 }
932
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700933 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700934 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700935 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800936 return false;
937 }
938
939 return true;
940}
941
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800942static void DoKmsg() {
943 struct stat st;
944 if (!stat(PSTORE_LAST_KMSG, &st)) {
945 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
946 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
947 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
948 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
949 } else {
950 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
951 DumpFile("LAST KMSG", "/proc/last_kmsg");
952 }
953}
954
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800955static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800956 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800957 RunCommand(
958 "KERNEL LOG",
959 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
960 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
961}
962
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800963static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800964 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800965 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
966 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800967 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100968 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800969 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
970 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800971 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800972 RunCommand(
973 "EVENT LOG",
974 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
975 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800976 timeout_ms = logcat_timeout({"stats"});
977 RunCommand(
978 "STATS LOG",
979 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
980 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
981 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800982 RunCommand(
983 "RADIO LOG",
984 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
985 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800986
987 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
988
989 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800990 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
991 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800992}
993
Jayachandran Ca94c7172017-06-10 15:08:12 -0700994static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700995 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
996 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900997 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700998 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900999 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
1000 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
1001 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
1002 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -07001003}
1004
Narayan Kamath8f788292017-05-25 13:20:39 +01001005static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
1006 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
1007 anr_traces_dir.c_str());
1008
1009 // If we're here, dump_traces_path will always be a temporary file
1010 // (created with mkostemp or similar) that contains dumps taken earlier
1011 // on in the process.
1012 if (dump_traces_path != nullptr) {
1013 if (add_to_zip) {
1014 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
1015 } else {
1016 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
1017 dump_traces_path);
1018 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
1019 }
1020
1021 const int ret = unlink(dump_traces_path);
1022 if (ret == -1) {
1023 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1024 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001025 }
1026 }
1027
Narayan Kamathbd863722017-06-01 18:50:12 +01001028 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001029 if (ds.anr_data_.size() > 0) {
1030 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +01001031 "VM TRACES AT LAST ANR", add_to_zip);
1032
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001033 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1034 // it will be present in the body of the main entry if |add_to_zip| == false.
1035 //
1036 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001037 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001038 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001039 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001040 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1041 }
1042}
1043
1044static void AddAnrTraceFiles() {
1045 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1046
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001047 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001048
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001049 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001050
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001051 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1052
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001053 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001054 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001055 int i = 0;
1056 while (true) {
1057 const std::string slow_trace_path =
1058 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1059 if (stat(slow_trace_path.c_str(), &st)) {
1060 // No traces file at this index, done with the files.
1061 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001062 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001063 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1064 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001065 }
1066}
1067
Wei Wang509bb5d2017-06-09 14:42:12 -07001068static void DumpBlockStatFiles() {
1069 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001070
Wei Wang1dc1ef52017-06-12 11:28:37 -07001071 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1072
1073 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001074 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1075 return;
1076 }
1077
1078 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001079 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001080 if ((d->d_name[0] == '.')
1081 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1082 || (d->d_name[1] == '\0'))) {
1083 continue;
1084 }
1085 const std::string new_path =
1086 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1087 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1088 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1089 printf("\n");
1090 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001091 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001092}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001093
1094static void DumpPacketStats() {
1095 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1096 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1097 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1098 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1099 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1100}
1101
1102static void DumpIpAddrAndRules() {
1103 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1104 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1105 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1106 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1107 RunCommand("IP RULES", {"ip", "rule", "show"});
1108 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1109}
1110
Nandana Dutt5c390032019-03-12 10:52:56 +00001111static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, int priority,
1112 std::chrono::milliseconds timeout,
1113 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001114 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001115 sp<android::IServiceManager> sm = defaultServiceManager();
1116 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001117 Vector<String16> args;
1118 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001119 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1120 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001121 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001122 std::string path(title);
1123 path.append(" - ").append(String8(service).c_str());
1124 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1125 size_t bytes_written = 0;
1126 status_t status = dumpsys.startDumpThread(service, args);
1127 if (status == OK) {
1128 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1129 std::chrono::duration<double> elapsed_seconds;
1130 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1131 /* as_proto = */ false, elapsed_seconds, bytes_written);
1132 section_reporter.setSize(bytes_written);
1133 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1134 bool dump_complete = (status == OK);
1135 dumpsys.stopDumpThread(dump_complete);
1136 }
1137 section_reporter.setStatus(status);
1138
1139 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1140 std::chrono::steady_clock::now() - start);
1141 if (elapsed_duration > timeout) {
1142 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1143 elapsed_duration.count());
1144 break;
1145 }
1146 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001147 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001148}
1149
Vishnu Nair64afc022018-02-01 15:29:34 -08001150static void RunDumpsysText(const std::string& title, int priority,
1151 std::chrono::milliseconds timeout,
1152 std::chrono::milliseconds service_timeout) {
1153 DurationReporter duration_reporter(title);
1154 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1155 fsync(STDOUT_FILENO);
1156 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1157}
1158
1159/* Dump all services registered with Normal or Default priority. */
Nandana Dutt5c390032019-03-12 10:52:56 +00001160static Dumpstate::RunStatus RunDumpsysTextNormalPriority(const std::string& title,
1161 std::chrono::milliseconds timeout,
1162 std::chrono::milliseconds service_timeout) {
Vishnu Nair64afc022018-02-01 15:29:34 -08001163 DurationReporter duration_reporter(title);
1164 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1165 fsync(STDOUT_FILENO);
1166 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1167 service_timeout);
Nandana Dutt5c390032019-03-12 10:52:56 +00001168
1169 RETURN_IF_USER_DENIED_CONSENT();
1170
1171 return RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1172 service_timeout);
Vishnu Nair64afc022018-02-01 15:29:34 -08001173}
1174
Nandana Dutt5c390032019-03-12 10:52:56 +00001175static Dumpstate::RunStatus RunDumpsysProto(const std::string& title, int priority,
1176 std::chrono::milliseconds timeout,
1177 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001178 if (!ds.IsZipping()) {
1179 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
Nandana Dutt5c390032019-03-12 10:52:56 +00001180 return Dumpstate::RunStatus::OK;
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001181 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001182 sp<android::IServiceManager> sm = defaultServiceManager();
1183 Dumpsys dumpsys(sm.get());
1184 Vector<String16> args;
1185 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1186 DurationReporter duration_reporter(title);
1187
1188 auto start = std::chrono::steady_clock::now();
1189 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1190 for (const String16& service : services) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001191 RETURN_IF_USER_DENIED_CONSENT();
Vishnu Naire97d6122018-01-18 13:58:56 -08001192 std::string path(kProtoPath);
1193 path.append(String8(service).c_str());
1194 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1195 path.append("_CRITICAL");
1196 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1197 path.append("_HIGH");
1198 }
1199 path.append(kProtoExt);
1200 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1201 status_t status = dumpsys.startDumpThread(service, args);
1202 if (status == OK) {
1203 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1204 bool dumpTerminated = (status == OK);
1205 dumpsys.stopDumpThread(dumpTerminated);
1206 }
1207 ZipWriter::FileEntry file_entry;
1208 ds.zip_writer_->GetLastEntry(&file_entry);
1209 section_reporter.setSize(file_entry.compressed_size);
1210 section_reporter.setStatus(status);
1211
1212 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1213 std::chrono::steady_clock::now() - start);
1214 if (elapsed_duration > timeout) {
1215 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1216 elapsed_duration.count());
1217 break;
1218 }
1219 }
Nandana Dutt5c390032019-03-12 10:52:56 +00001220 return Dumpstate::RunStatus::OK;
Vishnu Naire97d6122018-01-18 13:58:56 -08001221}
1222
Nandana Dutta7db6342018-11-21 14:53:34 +00001223// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001224static Dumpstate::RunStatus RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001225 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1226 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Nandana Dutt5c390032019-03-12 10:52:56 +00001227
1228 RETURN_IF_USER_DENIED_CONSENT();
1229
1230 return RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1231 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001232}
1233
1234// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001235static Dumpstate::RunStatus RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001236 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1237 // high priority. Reduce timeout once they are able to dump in a shorter time or
1238 // moved to a parallel task.
1239 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1240 /* timeout= */ 90s, /* service_timeout= */ 30s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001241
1242 RETURN_IF_USER_DENIED_CONSENT();
1243
1244 return RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1245 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001246}
1247
1248// Runs dumpsys on services that must dump but can take up to 10s to dump.
Nandana Dutt5c390032019-03-12 10:52:56 +00001249static Dumpstate::RunStatus RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001250 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
Nandana Dutt5c390032019-03-12 10:52:56 +00001251
1252 RETURN_IF_USER_DENIED_CONSENT();
1253
1254 return RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1255 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001256}
1257
Steven Moreland44cd9482018-01-04 16:24:13 -08001258static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001259 if (!ds.IsZipping()) {
1260 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1261 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1262 return;
1263 }
1264 DurationReporter duration_reporter("DUMP HALS");
1265 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
Greg Kaiser313202c2019-05-16 10:32:51 -07001266 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001267
Steven Moreland44cd9482018-01-04 16:24:13 -08001268 using android::hidl::manager::V1_0::IServiceManager;
1269 using android::hardware::defaultServiceManager;
1270
1271 sp<IServiceManager> sm = defaultServiceManager();
1272 if (sm == nullptr) {
1273 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1274 return;
1275 }
1276
1277 auto ret = sm->list([&](const auto& interfaces) {
1278 for (const std::string& interface : interfaces) {
1279 std::string cleanName = interface;
1280 std::replace_if(cleanName.begin(),
1281 cleanName.end(),
1282 [](char c) {
1283 return !isalnum(c) &&
1284 std::string("@-_:.").find(c) == std::string::npos;
1285 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001286 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001287
1288 {
1289 auto fd = android::base::unique_fd(
1290 TEMP_FAILURE_RETRY(open(path.c_str(),
1291 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1293 if (fd < 0) {
1294 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1295 continue;
1296 }
1297 RunCommandToFd(fd,
1298 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001299 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001300 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1301
1302 bool empty = 0 == lseek(fd, 0, SEEK_END);
1303 if (!empty) {
1304 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1305 }
1306 }
1307
1308 unlink(path.c_str());
1309 }
1310 });
1311
1312 if (!ret.isOk()) {
1313 MYLOGE("Could not list hals from hwservicemanager.\n");
1314 }
1315}
1316
Nandana Dutt5c390032019-03-12 10:52:56 +00001317// Dumps various things. Returns early with status USER_CONSENT_DENIED if user denies consent
1318// via the consent they are shown. Ignores other errors that occur while running various
1319// commands. The consent checking is currently done around long running tasks, which happen to
1320// be distributed fairly evenly throughout the function.
1321static Dumpstate::RunStatus dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001322 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001323
Nandana Dutt5c390032019-03-12 10:52:56 +00001324 // Dump various things. Note that anything that takes "long" (i.e. several seconds) should
1325 // check intermittently (if it's intrerruptable like a foreach on pids) and/or should be wrapped
1326 // in a consent check (via RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK).
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001327 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001328 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001329 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001330 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001331 DumpFile("MEMORY INFO", "/proc/meminfo");
1332 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001333 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001334
1335 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "PROCRANK", {"procrank"}, AS_ROOT_20);
1336
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001337 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1338 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1339 DumpFile("SLAB INFO", "/proc/slabinfo");
1340 DumpFile("ZONEINFO", "/proc/zoneinfo");
1341 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1342 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1343 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001344
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001345 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1346 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1347 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001348
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001349 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001350 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001351
1352 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunCommand, "LIBRANK", {"librank"},
1353 CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001354
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001355 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001356
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001357 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001358 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001359 struct stat s;
1360 if (stat("/proc/modules", &s) != 0) {
1361 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1362 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001363 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001364 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001365
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001366 if (__android_logger_property_get_bool(
1367 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1368 DoKernelLogcat();
1369 } else {
1370 do_dmesg();
1371 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001372
Felipe Lemef0292972016-11-22 13:57:05 -08001373 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Nandana Dutt5c390032019-03-12 10:52:56 +00001374
1375 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(for_each_pid, do_showmap, "SMAPS OF ALL PROCESSES");
1376
Jeff Brown1dc94e32014-09-11 14:15:27 -07001377 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001378 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001379
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001380 /* Dump Bluetooth HCI logs */
1381 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001382
Felipe Leme9a523ae2016-10-20 15:10:33 -07001383 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001384 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001385 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001386 }
1387
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001388 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001389
Felipe Lemee184f662016-10-27 10:04:47 -07001390 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001391
Narayan Kamath8f788292017-05-25 13:20:39 +01001392 // NOTE: tombstones are always added as separate entries in the zip archive
1393 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001394 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001395 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001396 if (!tombstones_dumped) {
1397 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001398 }
1399
Jayachandran Ca94c7172017-06-10 15:08:12 -07001400 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001401
Chenbo Feng276a3b62018-08-07 11:44:49 -07001402 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1403
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001404 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001405
Jayachandran Ca94c7172017-06-10 15:08:12 -07001406 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001407
1408 dump_route_tables();
1409
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001410 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1411 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1412 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001413
Nandana Dutt5c390032019-03-12 10:52:56 +00001414 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysHigh);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001415
Elliott Hughes23ccc622017-02-28 10:14:22 -08001416 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001417
Jin Qianf334d662017-10-10 14:41:37 -07001418 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001419
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001420 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001421
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001422 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001423
Colin Crossf45fa6b2012-03-26 12:38:26 -07001424 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001425 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1426 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1427 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1428 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1429 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001430
Nataniel Borgesbc73f522019-01-25 16:37:16 -08001431 RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001432 /* Add window and surface trace files. */
1433 if (!PropertiesHelper::IsUserBuild()) {
1434 ds.AddDir(WMTRACE_DATA_DIR, false);
1435 }
1436
Nandana Dutt5c390032019-03-12 10:52:56 +00001437 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpstateBoard);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001438
Steven Moreland7440ddb2016-12-15 16:13:39 -08001439 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001440 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1441 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001442 // su does not exist on user builds, so try running without it.
1443 // This way any implementations of vril-dump that do not require
1444 // root can run on user builds.
1445 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001446 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001447 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001448 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001449 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001450 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001451 }
1452
Felipe Lemed8b94e52016-12-08 10:21:44 -08001453 printf("========================================================\n");
1454 printf("== Android Framework Services\n");
1455 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001456
Nandana Dutt5c390032019-03-12 10:52:56 +00001457 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysNormal);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001458
Felipe Lemed8b94e52016-12-08 10:21:44 -08001459 printf("========================================================\n");
1460 printf("== Checkins\n");
1461 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001462
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001463 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001464
1465 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsys, "CHECKIN MEMINFO", {"meminfo", "--checkin"});
1466
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001467 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1468 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1469 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1470 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001471
Felipe Lemed8b94e52016-12-08 10:21:44 -08001472 printf("========================================================\n");
1473 printf("== Running Application Activities\n");
1474 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001475
Makoto Onuki60780982018-04-16 15:34:00 -07001476 // The following dumpsys internally collects output from running apps, so it can take a long
1477 // time. So let's extend the timeout.
1478
1479 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1480
1481 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001482
Felipe Lemed8b94e52016-12-08 10:21:44 -08001483 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001484 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001485 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001486
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001487 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001488 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001489
Felipe Lemed8b94e52016-12-08 10:21:44 -08001490 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001491 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001492 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001493
Makoto Onuki60780982018-04-16 15:34:00 -07001494 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1495 DUMPSYS_COMPONENTS_OPTIONS);
1496
1497 printf("========================================================\n");
1498 printf("== Running Application Providers (platform)\n");
1499 printf("========================================================\n");
1500
1501 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1502 DUMPSYS_COMPONENTS_OPTIONS);
1503
1504 printf("========================================================\n");
1505 printf("== Running Application Providers (non-platform)\n");
1506 printf("========================================================\n");
1507
1508 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1509 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001510
Adrian Roos8b397ab2017-04-04 16:35:44 -07001511 printf("========================================================\n");
1512 printf("== Dropbox crashes\n");
1513 printf("========================================================\n");
1514
1515 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1516 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1517
Felipe Lemed8b94e52016-12-08 10:21:44 -08001518 printf("========================================================\n");
1519 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1520 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1521 printf("========================================================\n");
1522 printf("== dumpstate: done (id %d)\n", ds.id_);
1523 printf("========================================================\n");
Bookatz38472142018-09-28 10:20:24 -07001524
1525 printf("========================================================\n");
1526 printf("== Obtaining statsd metadata\n");
1527 printf("========================================================\n");
1528 // This differs from the usual dumpsys stats, which is the stats report data.
1529 RunDumpsys("STATSDSTATS", {"stats", "--metadata"});
Nandana Dutt5c390032019-03-12 10:52:56 +00001530 return Dumpstate::RunStatus::OK;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001531}
1532
Nandana Dutt5c390032019-03-12 10:52:56 +00001533/*
1534 * Dumps state for the default case; drops root after it's no longer necessary.
1535 *
1536 * Returns RunStatus::OK if everything went fine.
1537 * Returns RunStatus::ERROR if there was an error.
1538 * Returns RunStatus::USER_DENIED_CONSENT if user explicitly denied consent to sharing the bugreport
1539 * with the caller.
1540 */
1541static Dumpstate::RunStatus DumpstateDefault() {
Primiano Tucci2d7f5c22019-01-17 15:51:14 +00001542 // Try to dump anrd trace if the daemon is running.
1543 dump_anrd_trace();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001544
Nandana Duttcf419a72019-03-14 10:40:17 +00001545 // Invoking the following dumpsys calls before DumpTraces() to try and
Nandana Dutt4be45d12018-09-26 15:04:23 +01001546 // keep the system stats as close to its initial state as possible.
Nandana Dutt5c390032019-03-12 10:52:56 +00001547 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(RunDumpsysCritical);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001548
1549 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttcf419a72019-03-14 10:40:17 +00001550 RUN_SLOW_FUNCTION_WITH_CONSENT_CHECK(ds.DumpTraces, &dump_traces_path);
Nandana Dutt4be45d12018-09-26 15:04:23 +01001551
1552 /* Run some operations that require root. */
1553 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1554 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1555
1556 ds.AddDir(RECOVERY_DIR, true);
1557 ds.AddDir(RECOVERY_DATA_DIR, true);
1558 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1559 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1560 if (!PropertiesHelper::IsUserBuild()) {
1561 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1562 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1563 }
1564 add_mountinfo();
1565 DumpIpTablesAsRoot();
1566
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001567 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001568 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1569
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001570 // Dump IPsec stats. No keys are exposed here.
1571 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1572
Nandana Dutt4be45d12018-09-26 15:04:23 +01001573 // Run ss as root so we can see socket marks.
1574 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1575
1576 // Run iotop as root to show top 100 IO threads
1577 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1578
Erick Reyese68df822019-02-11 14:46:36 -08001579 // Gather shared memory buffer info if the product implements it
1580 struct stat st;
1581 if (!stat("/product/bin/dmabuf_dump", &st)) {
1582 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1583 }
1584
Nandana Dutt4be45d12018-09-26 15:04:23 +01001585 if (!DropRootUser()) {
Nandana Dutt5c390032019-03-12 10:52:56 +00001586 return Dumpstate::RunStatus::ERROR;
Nandana Dutt4be45d12018-09-26 15:04:23 +01001587 }
1588
Nandana Dutt5c390032019-03-12 10:52:56 +00001589 RETURN_IF_USER_DENIED_CONSENT();
1590 return dumpstate();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001591}
1592
mukesh agrawal253dad42018-01-23 21:59:59 -08001593// This method collects common dumpsys for telephony and wifi
1594static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001595 DumpIpTablesAsRoot();
1596
Jayachandran Cb4389d92019-07-08 09:46:05 -07001597 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1598
Jayachandran Ca94c7172017-06-10 15:08:12 -07001599 if (!DropRootUser()) {
1600 return;
1601 }
1602
1603 do_dmesg();
1604 DoLogcat();
1605 DumpPacketStats();
1606 DoKmsg();
1607 DumpIpAddrAndRules();
1608 dump_route_tables();
Jayachandran Cb4389d92019-07-08 09:46:05 -07001609 DumpHals();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001610
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
1679 printf("========================================================\n");
1680 printf("== dumpstate: done (id %d)\n", ds.id_);
1681 printf("========================================================\n");
1682}
1683
Nandana Duttcf419a72019-03-14 10:40:17 +00001684Dumpstate::RunStatus Dumpstate::DumpTraces(const char** path) {
Nandana Duttfaafd522019-03-11 09:23:09 +00001685 DurationReporter duration_reporter("DUMP TRACES");
1686
1687 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1688 const size_t buf_size = temp_file_pattern.length() + 1;
1689 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1690 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1691
1692 // Create a new, empty file to receive all trace dumps.
1693 //
1694 // TODO: This can be simplified once we remove support for the old style
1695 // dumps. We can have a file descriptor passed in to dump_traces instead
1696 // of creating a file, closing it and then reopening it again.
1697 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1698 if (fd < 0) {
1699 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001700 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001701 }
1702
1703 // Nobody should have access to this temporary file except dumpstate, but we
1704 // temporarily grant 'read' to 'others' here because this file is created
1705 // when tombstoned is still running as root, but dumped after dropping. This
1706 // can go away once support for old style dumping has.
1707 const int chmod_ret = fchmod(fd, 0666);
1708 if (chmod_ret < 0) {
1709 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001710 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001711 }
1712
1713 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1714 if (proc.get() == nullptr) {
1715 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
Nandana Duttcf419a72019-03-14 10:40:17 +00001716 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001717 }
1718
1719 // Number of times process dumping has timed out. If we encounter too many
1720 // failures, we'll give up.
1721 int timeout_failures = 0;
1722 bool dalvik_found = false;
1723
1724 const std::set<int> hal_pids = get_interesting_hal_pids();
1725
1726 struct dirent* d;
1727 while ((d = readdir(proc.get()))) {
Nandana Duttcf419a72019-03-14 10:40:17 +00001728 RETURN_IF_USER_DENIED_CONSENT();
Nandana Duttfaafd522019-03-11 09:23:09 +00001729 int pid = atoi(d->d_name);
1730 if (pid <= 0) {
1731 continue;
1732 }
1733
1734 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1735 std::string exe;
1736 if (!android::base::Readlink(link_name, &exe)) {
1737 continue;
1738 }
1739
1740 bool is_java_process;
1741 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1742 // Don't bother dumping backtraces for the zygote.
1743 if (IsZygote(pid)) {
1744 continue;
1745 }
1746
1747 dalvik_found = true;
1748 is_java_process = true;
1749 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1750 is_java_process = false;
1751 } else {
1752 // Probably a native process we don't care about, continue.
1753 continue;
1754 }
1755
1756 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1757 if (timeout_failures == 3) {
1758 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1759 break;
1760 }
1761
1762 const uint64_t start = Nanotime();
1763 const int ret = dump_backtrace_to_file_timeout(
1764 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1765 is_java_process ? 5 : 20, fd);
1766
1767 if (ret == -1) {
1768 // For consistency, the header and footer to this message match those
1769 // dumped by debuggerd in the success case.
1770 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1771 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1772 dprintf(fd, "---- end %d ----", pid);
1773 timeout_failures++;
1774 continue;
1775 }
1776
1777 // We've successfully dumped stack traces, reset the failure count
1778 // and write a summary of the elapsed time to the file and continue with the
1779 // next process.
1780 timeout_failures = 0;
1781
1782 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1783 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1784 }
1785
1786 if (!dalvik_found) {
1787 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1788 }
1789
Nandana Duttcf419a72019-03-14 10:40:17 +00001790 *path = file_name_buf.release();
1791 return RunStatus::OK;
Nandana Duttfaafd522019-03-11 09:23:09 +00001792}
1793
Felipe Leme6f674ae2016-11-18 17:10:33 -08001794void Dumpstate::DumpstateBoard() {
1795 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001796 printf("========================================================\n");
1797 printf("== Board\n");
1798 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001799
Felipe Leme6f674ae2016-11-18 17:10:33 -08001800 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001801 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001802 return;
1803 }
1804
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001805 std::vector<std::string> paths;
1806 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001807 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001808 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1809 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001810 remover.emplace_back(android::base::make_scope_guard(
1811 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001812 }
Jie Song9fbfad02017-06-20 16:29:42 -07001813
Wei Wang587eac92018-04-05 12:17:20 -07001814 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1815 if (dumpstate_device == nullptr) {
1816 MYLOGE("No IDumpstateDevice implementation\n");
1817 return;
1818 }
1819
1820 using ScopedNativeHandle =
1821 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1822 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1823 [](native_handle_t* handle) {
1824 native_handle_close(handle);
1825 native_handle_delete(handle);
1826 });
1827 if (handle == nullptr) {
1828 MYLOGE("Could not create native_handle\n");
1829 return;
1830 }
1831
Nandana Dutt5c390032019-03-12 10:52:56 +00001832 // TODO(128270426): Check for consent in between?
Wei Wang587eac92018-04-05 12:17:20 -07001833 for (size_t i = 0; i < paths.size(); i++) {
1834 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1835
1836 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1837 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1838 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1839 if (fd < 0) {
1840 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1841 return;
1842 }
1843 handle.get()->data[i] = fd.release();
1844 }
1845
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001846 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001847 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1848 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1849 // and grab whatever dumped
1850 std::packaged_task<bool()>
1851 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001852 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1853 if (!status.isOk()) {
1854 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001855 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001856 }
Wei Wang587eac92018-04-05 12:17:20 -07001857 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001858 });
Wei Wang587eac92018-04-05 12:17:20 -07001859
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001860 auto result = dumpstate_task.get_future();
1861 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001862
1863 constexpr size_t timeout_sec = 30;
1864 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1865 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1866 if (!android::base::SetProperty("ctl.interface_restart",
1867 android::base::StringPrintf("%s/default",
1868 IDumpstateDevice::descriptor))) {
1869 MYLOGE("Couldn't restart dumpstate HAL\n");
1870 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001871 }
Wei Wang587eac92018-04-05 12:17:20 -07001872 // Wait some time for init to kill dumpstate vendor HAL
1873 constexpr size_t killing_timeout_sec = 10;
1874 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1875 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1876 "there might be racing in content\n", killing_timeout_sec);
1877 }
1878
1879 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1880 for (size_t i = 0; i < paths.size(); i++) {
1881 struct stat s;
1882 if (fstat(handle.get()->data[i], &s) == -1) {
1883 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1884 strerror(errno));
1885 file_sizes[i] = -1;
1886 continue;
1887 }
1888 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001889 }
1890
1891 for (size_t i = 0; i < paths.size(); i++) {
1892 if (file_sizes[i] == -1) {
1893 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001894 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001895 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001896 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001897 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001898 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001899 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001900 }
1901
Felipe Lemed8b94e52016-12-08 10:21:44 -08001902 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001903}
1904
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001905static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001906 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001907 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001908 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1909 " -h: display this help message\n"
1910 " -b: play sound file instead of vibrate, at beginning of job\n"
1911 " -e: play sound file instead of vibrate, at end of job\n"
1912 " -o: write to file (instead of stdout)\n"
1913 " -d: append date to filename (requires -o)\n"
1914 " -p: capture screenshot to filename.png (requires -o)\n"
1915 " -z: generate zipped file (requires -o)\n"
1916 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001917 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001918 " -q: disable vibrate\n"
1919 " -B: send broadcast when finished (requires -o)\n"
1920 " -P: send broadcast when started and update system properties on "
1921 "progress (requires -o and -B)\n"
1922 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1923 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001924 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001925 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001926}
1927
Wei Liuf87959e2016-08-26 14:51:42 -07001928static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001929 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001930}
1931
Felipe Leme1d486fe2016-10-14 18:06:47 -07001932bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001933 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001934 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001935 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001936 // Final timestamp
1937 char date[80];
1938 time_t the_real_now_please_stand_up = time(nullptr);
1939 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001940 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001941 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001942
Felipe Leme9a523ae2016-10-20 15:10:33 -07001943 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001944 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001945 return false;
1946 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001947 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001948 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001949 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001950 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001951
Felipe Leme0f3fb202016-06-10 17:10:53 -07001952 // Add log file (which contains stderr output) to zip...
1953 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001954 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001955 MYLOGE("Failed to add dumpstate log to .zip file\n");
1956 return false;
1957 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001958 // TODO: Should truncate the existing file.
1959 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001960 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1961 return false;
1962 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001963 fprintf(stderr, "\n");
1964
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001965 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001966 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001967 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001968 return false;
1969 }
1970
Felipe Leme1d486fe2016-10-14 18:06:47 -07001971 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1972 ds.zip_file.reset(nullptr);
1973
Felipe Lemee9d2c542016-11-15 11:48:26 -08001974 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001975 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001976
Felipe Leme1e9edc62015-12-21 16:02:13 -08001977 return true;
1978}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001979
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001980static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001981 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1982 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001983 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001984 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001985 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001986 }
1987
1988 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001989 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001990
1991 std::vector<uint8_t> buffer(65536);
1992 while (1) {
1993 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1994 if (bytes_read == 0) {
1995 break;
1996 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001997 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001998 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001999 }
2000
Elliott Hughesc4dc1412016-04-12 16:28:31 -07002001 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002002 }
2003
Elliott Hughesc4dc1412016-04-12 16:28:31 -07002004 uint8_t hash[SHA256_DIGEST_LENGTH];
2005 SHA256_Final(hash, &ctx);
2006
2007 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
2008 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00002009 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002010 }
2011 hash_buffer[sizeof(hash_buffer) - 1] = 0;
2012 return std::string(hash_buffer);
2013}
2014
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002015static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
2016 // clang-format off
2017 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
2018 "--receiver-foreground", "--receiver-include-background", "-a", action};
2019 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08002020
2021 am.insert(am.end(), args.begin(), args.end());
2022
Felipe Leme8d2410e2017-02-08 09:46:08 -08002023 RunCommand("", am,
2024 CommandOptions::WithTimeout(20)
2025 .Log("Sending broadcast: '%s'\n")
2026 .Always()
2027 .DropRoot()
2028 .RedirectStderr()
2029 .Build());
2030}
2031
Felipe Leme35b8cf12017-02-10 15:47:29 -08002032static void Vibrate(int duration_ms) {
2033 // clang-format off
2034 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
2035 CommandOptions::WithTimeout(10)
2036 .Log("Vibrate: '%s'\n")
2037 .Always()
2038 .Build());
2039 // clang-format on
2040}
2041
Nandana Dutt979388e2018-11-30 16:48:55 +00002042static void MaybeResolveSymlink(std::string* path) {
2043 std::string resolved_path;
2044 if (android::base::Readlink(*path, &resolved_path)) {
2045 *path = resolved_path;
2046 }
2047}
2048
Nandana Dutt4be45d12018-09-26 15:04:23 +01002049/*
2050 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
2051 * if we are writing zip files and adds the version file.
2052 */
2053static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002054 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
2055
Nandana Dutt4be45d12018-09-26 15:04:23 +01002056 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
2057 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002058 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002059 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002060 char date[80];
2061 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
2062 ds.name_ = date;
2063 } else {
2064 ds.name_ = "undated";
2065 }
2066
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002067 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002068 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002069 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002070 ds.base_name_ += "-wifi";
2071 }
2072
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002073 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002074 ds.screenshot_path_ = ds.GetPath(".png");
2075 }
2076 ds.tmp_path_ = ds.GetPath(".tmp");
2077 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
2078
Nandana Dutt54dbd672019-01-11 12:58:05 +00002079 std::string destination = ds.options_->bugreport_fd.get() != -1
2080 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00002081 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01002082 MYLOGD(
2083 "Bugreport dir: %s\n"
2084 "Base name: %s\n"
2085 "Suffix: %s\n"
2086 "Log path: %s\n"
2087 "Temporary path: %s\n"
2088 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00002089 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
2090 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002091
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002092 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002093 ds.path_ = ds.GetPath(".zip");
2094 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2095 create_parent_dirs(ds.path_.c_str());
2096 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2097 if (ds.zip_file == nullptr) {
2098 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2099 } else {
2100 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2101 }
2102 ds.AddTextZipEntry("version.txt", ds.version_);
2103 }
2104}
2105
2106/*
2107 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2108 * printing zipped file status, etc.
2109 */
2110static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002111 /* check if user changed the suffix using system properties */
2112 std::string name =
2113 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2114 bool change_suffix = false;
2115 if (!name.empty()) {
2116 /* must whitelist which characters are allowed, otherwise it could cross directories */
2117 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2118 if (std::regex_match(name.c_str(), valid_regex)) {
2119 change_suffix = true;
2120 } else {
2121 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2122 }
2123 }
2124 if (change_suffix) {
2125 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2126 ds.name_ = name;
2127 if (!ds.screenshot_path_.empty()) {
2128 std::string new_screenshot_path = ds.GetPath(".png");
2129 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2130 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2131 new_screenshot_path.c_str(), strerror(errno));
2132 } else {
2133 ds.screenshot_path_ = new_screenshot_path;
2134 }
2135 }
2136 }
2137
2138 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002139 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002140 if (!ds.FinishZipFile()) {
2141 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2142 do_text_file = true;
2143 } else {
2144 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002145 // If the user has changed the suffix, we need to change the zip file name.
2146 std::string new_path = ds.GetPath(".zip");
2147 if (ds.path_ != new_path) {
2148 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2149 if (rename(ds.path_.c_str(), new_path.c_str())) {
2150 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2151 strerror(errno));
2152 } else {
2153 ds.path_ = new_path;
2154 }
2155 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002156 }
2157 }
2158 if (do_text_file) {
2159 ds.path_ = ds.GetPath(".txt");
2160 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2161 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2162 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2163 ds.path_.clear();
2164 }
2165 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002166 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002167 if (do_text_file) {
2168 dprintf(ds.control_socket_fd_,
2169 "FAIL:could not create zip file, check %s "
2170 "for more details\n",
2171 ds.log_path_.c_str());
2172 } else {
2173 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2174 }
2175 }
2176}
2177
2178/* Broadcasts that we are done with the bugreport */
2179static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002180 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002181 if (!ds.path_.empty()) {
2182 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002183 // clang-format off
2184
2185 std::vector<std::string> am_args = {
2186 "--receiver-permission", "android.permission.DUMP",
2187 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2188 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2189 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002190 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002191 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2192 };
2193 // clang-format on
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002194 if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002195 am_args.push_back("--es");
2196 am_args.push_back("android.intent.extra.SCREENSHOT");
2197 am_args.push_back(ds.screenshot_path_);
2198 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002199 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002200 am_args.push_back("--es");
2201 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002202 am_args.push_back(ds.options_->notification_title);
2203 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002204 am_args.push_back("--es");
2205 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002206 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002207 }
2208 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002209 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002210 am_args.push_back("--es");
2211 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002212 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002213 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2214 } else {
2215 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2216 }
2217 } else {
2218 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2219 }
2220}
2221
Nandana Dutt58d72e22018-11-16 10:30:48 +00002222static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2223 switch (mode) {
2224 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2225 return "BUGREPORT_FULL";
2226 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2227 return "BUGREPORT_INTERACTIVE";
2228 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2229 return "BUGREPORT_REMOTE";
2230 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2231 return "BUGREPORT_WEAR";
2232 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2233 return "BUGREPORT_TELEPHONY";
2234 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2235 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002236 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2237 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002238 }
2239}
2240
2241static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002242 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002243 switch (mode) {
2244 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2245 options->do_broadcast = true;
2246 options->do_fb = true;
2247 break;
2248 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002249 // Currently, the dumpstate binder is only used by Shell to update progress.
2250 options->do_start_service = true;
2251 options->do_progress_updates = true;
2252 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002253 options->do_broadcast = true;
2254 break;
2255 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002256 options->do_vibrate = false;
2257 options->is_remote_mode = true;
2258 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002259 options->do_broadcast = true;
2260 break;
2261 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002262 options->do_start_service = true;
2263 options->do_progress_updates = true;
2264 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002265 options->do_fb = true;
2266 options->do_broadcast = true;
2267 break;
2268 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002269 options->telephony_only = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002270 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002271 options->do_broadcast = true;
2272 break;
2273 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002274 options->wifi_only = true;
2275 options->do_zip_file = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002276 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002277 options->do_broadcast = true;
2278 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002279 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2280 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002281 }
2282}
2283
2284static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002285 // If the system property is not set, it's assumed to be a default bugreport.
2286 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002287
2288 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2289 if (!extra_options.empty()) {
2290 // Framework uses a system property to override some command-line args.
2291 // Currently, it contains the type of the requested bugreport.
2292 if (extra_options == "bugreportplus") {
2293 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002294 } else if (extra_options == "bugreportfull") {
2295 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002296 } else if (extra_options == "bugreportremote") {
2297 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2298 } else if (extra_options == "bugreportwear") {
2299 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2300 } else if (extra_options == "bugreporttelephony") {
2301 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2302 } else if (extra_options == "bugreportwifi") {
2303 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002304 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002305 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002306 }
2307 // Reset the property
2308 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2309 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002310 return mode;
2311}
2312
2313// TODO: Move away from system properties when we have options passed via binder calls.
2314/* Sets runtime options from the system properties and then clears those properties. */
2315static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2316 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2317 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002318
2319 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2320 if (!options->notification_title.empty()) {
2321 // Reset the property
2322 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2323
Nandana Duttdd8cca32018-11-14 10:10:29 +00002324 options->notification_description =
2325 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002326 if (!options->notification_description.empty()) {
2327 // Reset the property
2328 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2329 }
2330 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2331 options->notification_description.c_str());
2332 }
2333}
2334
Nandana Dutt58d72e22018-11-16 10:30:48 +00002335static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2336 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2337 MYLOGI("do_add_date: %d\n", options.do_add_date);
2338 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2339 MYLOGI("use_socket: %d\n", options.use_socket);
2340 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2341 MYLOGI("do_fb: %d\n", options.do_fb);
2342 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2343 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2344 MYLOGI("show_header_only: %d\n", options.show_header_only);
2345 MYLOGI("do_start_service: %d\n", options.do_start_service);
2346 MYLOGI("telephony_only: %d\n", options.telephony_only);
2347 MYLOGI("wifi_only: %d\n", options.wifi_only);
2348 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002349 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002350 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2351 MYLOGI("args: %s\n", options.args.c_str());
2352 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2353 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2354}
2355
Nandana Dutt54dbd672019-01-11 12:58:05 +00002356void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2357 const android::base::unique_fd& bugreport_fd_in,
2358 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002359 // In the new API world, date is always added; output is always a zip file.
2360 // TODO(111441001): remove these options once they are obsolete.
2361 do_add_date = true;
2362 do_zip_file = true;
2363
Nandana Dutt54dbd672019-01-11 12:58:05 +00002364 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2365 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2366 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002367
2368 extra_options = ModeToString(bugreport_mode);
2369 SetOptionsFromMode(bugreport_mode, this);
2370}
2371
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002372Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2373 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002374 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002375 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002376 switch (c) {
2377 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002378 case 'd': do_add_date = true; break;
2379 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002380 // o=use_outfile not supported anymore.
2381 // TODO(b/111441001): Remove when all callers have migrated.
2382 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002383 case 's': use_socket = true; break;
2384 case 'S': use_control_socket = true; break;
2385 case 'v': show_header_only = true; break;
2386 case 'q': do_vibrate = false; break;
2387 case 'p': do_fb = true; break;
2388 case 'P': do_progress_updates = true; break;
2389 case 'R': is_remote_mode = true; break;
2390 case 'B': do_broadcast = true; break;
2391 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002392 case 'w':
2393 // This was already processed
2394 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002395 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002396 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002397 break;
2398 default:
2399 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002400 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002401 break;
2402 // clang-format on
2403 }
2404 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002405
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002406 // TODO: use helper function to convert argv into a string
2407 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002408 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002409 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002410 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002411 }
2412 }
2413
2414 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2415 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002416
2417 SetOptionsFromProperties(this);
2418 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002419}
2420
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002421bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002422 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002423 return false;
2424 }
2425
Nandana Dutt9a76d202019-01-21 15:56:48 +00002426 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002427 return false;
2428 }
2429
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002430 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002431 return false;
2432 }
2433
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002434 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002435 return false;
2436 }
2437
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002438 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002439 return false;
2440 }
2441 return true;
2442}
2443
Nandana Dutt197661d2018-11-16 16:40:21 +00002444void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2445 options_ = std::move(options);
2446}
2447
Nandana Duttd2f5f082019-01-18 17:13:52 +00002448Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2449 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002450 if (listener_ != nullptr) {
2451 switch (status) {
2452 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002453 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002454 break;
2455 case Dumpstate::RunStatus::HELP:
2456 break;
2457 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002458 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002459 break;
2460 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002461 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2462 break;
2463 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2464 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2465 break;
2466 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2467 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002468 break;
2469 }
2470 }
2471 return status;
2472}
2473
Nandana Dutt979388e2018-11-30 16:48:55 +00002474/*
2475 * Dumps relevant information to a bugreport based on the given options.
2476 *
2477 * The bugreport can be dumped to a file or streamed to a socket.
2478 *
2479 * How dumping to file works:
2480 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2481 * stderr is redirected a log file.
2482 *
2483 * The temporary bugreport is then populated via printfs, dumping contents of files and
2484 * output of commands to stdout.
2485 *
2486 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2487 * text file.
2488 *
2489 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2490 * gets added to the archive.
2491 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002492 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2493 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002494 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002495Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2496 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002497 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002498 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002499 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002500 return RunStatus::INVALID_INPUT;
2501 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002502 /* set as high priority, and protect from OOM killer */
2503 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002504
Felipe Lemed071c682016-10-20 16:48:00 -07002505 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002506 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002507 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002508 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002509 } else {
2510 /* fallback to kernels <= 2.6.35 */
2511 oom_adj = fopen("/proc/self/oom_adj", "we");
2512 if (oom_adj) {
2513 fputs("-17", oom_adj);
2514 fclose(oom_adj);
2515 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002516 }
2517
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002518 if (version_ == VERSION_DEFAULT) {
2519 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002520 }
2521
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002522 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002523 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002524 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002525 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002526 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002527 }
2528
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002529 if (options_->show_header_only) {
2530 PrintHeader();
2531 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002532 }
2533
Nandana Duttd2f5f082019-01-18 17:13:52 +00002534 if (options_->bugreport_fd.get() != -1) {
2535 // If the output needs to be copied over to the caller's fd, get user consent.
2536 android::String16 package(calling_package.c_str());
2537 CheckUserConsent(calling_uid, package);
2538 }
2539
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002540 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002541 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002542
2543 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002544 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002545 is_redirecting
2546 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2547 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002548 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002549
Felipe Lemed071c682016-10-20 16:48:00 -07002550 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002551 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002552 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002553 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2554
2555 MYLOGI("begin\n");
2556
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002557 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002558
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002559 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002560 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002561 MYLOGI("Starting 'dumpstate' service\n");
2562 android::status_t ret;
2563 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2564 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2565 }
2566 }
2567
Felipe Lemef0292972016-11-22 13:57:05 -08002568 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002569 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2570 }
2571
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002572 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2573 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002574
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002575 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002576
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002577 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002578
Christopher Ferrised9354f2014-10-01 17:35:01 -07002579 // If we are going to use a socket, do it as early as possible
2580 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002581 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002582 if (!redirect_to_socket(stdout, "dumpstate")) {
2583 return ERROR;
2584 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002585 }
2586
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002587 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002588 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002589 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002590 if (control_socket_fd_ == -1) {
2591 return ERROR;
2592 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002593 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002594 }
2595
Felipe Leme71bbfc52015-11-23 14:14:51 -08002596 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002597 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002598
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002599 if (options_->do_progress_updates) {
2600 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002601 // clang-format off
2602 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002603 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002604 "--es", "android.intent.extra.NAME", name_,
2605 "--ei", "android.intent.extra.ID", std::to_string(id_),
2606 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2607 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002608 };
2609 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002610 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002611 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002612 if (options_->use_control_socket) {
2613 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002614 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002615 }
2616 }
2617
Nick Kralevichf3599b32016-01-25 15:05:16 -08002618 /* read /proc/cmdline before dropping root */
2619 FILE *cmdline = fopen("/proc/cmdline", "re");
2620 if (cmdline) {
2621 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2622 fclose(cmdline);
2623 }
2624
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002625 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002626 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002627 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002628
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002629 if (options_->do_fb && do_early_screenshot_) {
2630 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002631 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002632 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002633 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002634 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002635 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002636 }
2637 }
2638
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002639 if (options_->do_zip_file && zip_file != nullptr) {
2640 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2641 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002642 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002643 }
2644 }
2645
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002646 int dup_stdout_fd;
2647 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002648 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002649 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002650 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002651 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2652 return ERROR;
2653 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002654 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2655 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2656 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002657 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002658
2659 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2660 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002661 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002662 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002663 /* TODO: rather than generating a text file now and zipping it later,
2664 it would be more efficient to redirect stdout to the zip entry
2665 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002666 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2667 return ERROR;
2668 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002669 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002670 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002671 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002672 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002673 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002674
2675 // Don't buffer stdout
2676 setvbuf(stdout, nullptr, _IONBF, 0);
2677
Felipe Leme608385d2016-02-01 10:35:38 -08002678 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2679 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002680 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002681 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002682
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002683 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002684 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002685 DumpstateBoard();
2686 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002687 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002688 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002689 // Dump state for the default case. This also drops root.
Nandana Dutt5c390032019-03-12 10:52:56 +00002690 RunStatus s = DumpstateDefault();
2691 if (s != RunStatus::OK) {
2692 if (s == RunStatus::USER_CONSENT_TIMED_OUT) {
2693 HandleUserConsentDenied();
2694 }
2695 return s;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002696 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002697 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002698
Felipe Leme55b42a62015-11-10 17:39:08 -08002699 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002700 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002701 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002702 }
2703
Nandana Duttd2f5f082019-01-18 17:13:52 +00002704 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002705 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002706 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002707 }
2708
Nandana Duttd2f5f082019-01-18 17:13:52 +00002709 // Share the final file with the caller if the user has consented.
2710 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2711 if (options_->bugreport_fd.get() != -1) {
2712 status = CopyBugreportIfUserConsented();
2713 if (status != Dumpstate::RunStatus::OK &&
2714 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2715 // Do an early return if there were errors. We make an exception for consent
2716 // timing out because it's possible the user got distracted. In this case the
2717 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002718 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002719 return status;
2720 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002721 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002722 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2723 options_->screenshot_fd.get());
2724 if (copy_succeeded) {
2725 android::os::UnlinkAndLogOnError(screenshot_path_);
2726 }
2727 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002728 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2729 MYLOGI(
2730 "Did not receive user consent yet."
2731 " Will not copy the bugreport artifacts to caller.\n");
Abhijeet Kaurc5eff422019-04-17 16:00:09 +01002732 const String16 incidentcompanion("incidentcompanion");
2733 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2734 if (ics != nullptr) {
2735 MYLOGD("Canceling user consent request via incidentcompanion service\n");
2736 android::interface_cast<android::os::IIncidentCompanion>(ics)->cancelAuthorization(
2737 consent_callback_.get());
2738 } else {
2739 MYLOGD("Unable to cancel user consent; incidentcompanion service unavailable\n");
2740 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002741 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002742 }
2743
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002744 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002745 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002746 for (int i = 0; i < 3; i++) {
2747 Vibrate(75);
2748 usleep((75 + 50) * 1000);
2749 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002750 }
2751
Jeff Brown1dc94e32014-09-11 14:15:27 -07002752 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002753 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002754 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002755 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002756 }
2757
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002758 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2759 progress_->GetInitialMax());
2760 progress_->Save();
2761 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002762
Felipe Leme107a05f2016-03-08 15:11:15 -08002763 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002764 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002765 }
2766
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002767 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002768 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002769 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002770 }
2771
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002772 tombstone_data_.clear();
2773 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002774
Nandana Duttd2f5f082019-01-18 17:13:52 +00002775 return (consent_callback_ != nullptr &&
2776 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2777 ? USER_CONSENT_TIMED_OUT
2778 : RunStatus::OK;
2779}
2780
2781void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2782 consent_callback_ = new ConsentCallback();
2783 const String16 incidentcompanion("incidentcompanion");
2784 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2785 if (ics != nullptr) {
2786 MYLOGD("Checking user consent via incidentcompanion service\n");
2787 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
Joe Onorato1c36d752019-03-17 18:26:43 -07002788 calling_uid, calling_package, String16(), String16(),
2789 0x1 /* FLAG_CONFIRMATION_DIALOG */, consent_callback_.get());
Nandana Duttd2f5f082019-01-18 17:13:52 +00002790 } else {
2791 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2792 }
2793}
2794
Nandana Dutt5c390032019-03-12 10:52:56 +00002795bool Dumpstate::IsUserConsentDenied() const {
2796 return ds.consent_callback_ != nullptr &&
2797 ds.consent_callback_->getResult() == UserConsentResult::DENIED;
2798}
2799
Nandana Duttd2f5f082019-01-18 17:13:52 +00002800void Dumpstate::CleanupFiles() {
2801 android::os::UnlinkAndLogOnError(tmp_path_);
2802 android::os::UnlinkAndLogOnError(screenshot_path_);
2803 android::os::UnlinkAndLogOnError(path_);
2804}
2805
2806Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2807 MYLOGD("User denied consent; deleting files and returning\n");
2808 CleanupFiles();
2809 return USER_CONSENT_DENIED;
2810}
2811
2812Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2813 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2814 // user consent.
2815 UserConsentResult consent_result = consent_callback_->getResult();
2816 if (consent_result == UserConsentResult::UNAVAILABLE) {
2817 // User has not responded yet.
2818 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2819 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2820 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2821 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2822 sleep(delay_seconds);
2823 }
2824 consent_result = consent_callback_->getResult();
2825 }
2826 if (consent_result == UserConsentResult::DENIED) {
2827 // User has explicitly denied sharing with the app. To be safe delete the
2828 // internal bugreport & tmp files.
2829 return HandleUserConsentDenied();
2830 }
2831 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002832 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2833 if (copy_succeeded) {
2834 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002835 }
2836 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2837 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2838 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2839 // Since we do not have user consent to share the bugreport it does not get
2840 // copied over to the calling app but remains in the internal directory from
2841 // where the user can manually pull it.
2842 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2843 }
2844 // Unknown result; must be a programming error.
2845 MYLOGE("Unknown user consent result:%d\n", consent_result);
2846 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002847}
2848
Nandana Duttf02564e2019-02-15 15:24:24 +00002849Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002850 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2851 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2852 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002853 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002854 // When directly running dumpstate binary, the output is not expected to be written
2855 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002856 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002857
2858 // calling_uid and calling_package are for user consent to share the bugreport with
2859 // an app; they are irrelvant here because bugreport is only written to a local
2860 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002861 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002862 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002863 return status;
2864}
2865
2866/* Main entry point for dumpstate binary. */
2867int run_main(int argc, char* argv[]) {
2868 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002869
2870 switch (status) {
2871 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002872 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002873 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002874 ShowUsage();
2875 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002876 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002877 fprintf(stderr, "Invalid combination of args\n");
2878 ShowUsage();
2879 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002880 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002881 FALLTHROUGH_INTENDED;
2882 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2883 FALLTHROUGH_INTENDED;
2884 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002885 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002886 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002887}