blob: a66a8c16b29dd7db50d8098d6d1ccbbd02bbe21f [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080022#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070023#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070024#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080028#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070029#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <sys/resource.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/wait.h>
34#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070035
36#include <chrono>
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +000037#include <fstream>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070038#include <functional>
39#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010040#include <memory>
41#include <regex>
42#include <set>
43#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070044#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010045#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070046
Felipe Leme96c2bbb2016-09-26 09:21:21 -070047#include <android-base/file.h>
48#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070049#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080050#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070051#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070052#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080053#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080054#include <android/hidl/manager/1.0/IServiceManager.h>
Nandana Duttd2f5f082019-01-18 17:13:52 +000055#include <android/os/IIncidentCompanion.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080056#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070057#include <cutils/properties.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000058#include <debuggerd/client.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080059#include <dumpsys.h>
Nandana Duttfaafd522019-03-11 09:23:09 +000060#include <dumputils/dump_utils.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080061#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070062#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070063#include <private/android_filesystem_config.h>
64#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080065#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070066#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080067#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080068#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070069#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070070#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080071
Steven Morelandcb7ef822016-11-29 13:20:37 -080072using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080073using ::std::literals::chrono_literals::operator""ms;
74using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080075
Felipe Leme47e9be22016-12-21 15:37:07 -080076// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080077using android::defaultServiceManager;
78using android::Dumpsys;
79using android::INVALID_OPERATION;
80using android::IServiceManager;
81using android::OK;
82using android::sp;
83using android::status_t;
84using android::String16;
85using android::String8;
86using android::TIMED_OUT;
87using android::UNKNOWN_ERROR;
88using android::Vector;
Nandana Dutt979388e2018-11-30 16:48:55 +000089using android::base::StringPrintf;
Nandana Duttd2f5f082019-01-18 17:13:52 +000090using android::os::IDumpstateListener;
Felipe Leme47e9be22016-12-21 15:37:07 -080091using android::os::dumpstate::CommandOptions;
92using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080093using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080094using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080095using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080096
Nandana Duttd2f5f082019-01-18 17:13:52 +000097typedef Dumpstate::ConsentCallback::ConsentResult UserConsentResult;
98
Colin Crossf45fa6b2012-03-26 12:38:26 -070099/* read before root is shed */
100static char cmdline_buf[16384] = "(unknown)";
Yi Kong19d5c002018-07-20 13:39:55 -0700101static const char *dump_traces_path = nullptr;
Nandana Duttd2f5f082019-01-18 17:13:52 +0000102static const uint64_t USER_CONSENT_TIMEOUT_MS = 30 * 1000;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700103
Felipe Leme1d486fe2016-10-14 18:06:47 -0700104// TODO: variables and functions below should be part of dumpstate object
105
Felipe Leme635ca312016-01-05 14:23:02 -0800106static std::set<std::string> mount_points;
107void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -0800108
Todd Poynor2a83daa2013-11-22 15:44:22 -0800109#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700110#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700111#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800112
Felipe Lemee82a27d2016-01-05 13:35:44 -0800113#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700114#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700115#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700116#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100117#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
118#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Benedict Wong8f9d8a42019-01-03 16:19:38 -0800119#define XFRM_STAT_PROC_FILE "/proc/net/xfrm_stat"
Erik Kline08165202016-05-30 11:55:44 +0900120#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800121#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700122
Narayan Kamath8f788292017-05-25 13:20:39 +0100123// TODO(narayan): Since this information has to be kept in sync
124// with tombstoned, we should just put it in a common header.
125//
126// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100127static const std::string TOMBSTONE_DIR = "/data/tombstones/";
128static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
129static const std::string ANR_DIR = "/data/anr/";
130static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700131
Felipe Lemee844a9d2016-09-21 15:01:39 -0700132// TODO: temporary variables and functions used during C++ refactoring
133static Dumpstate& ds = Dumpstate::GetInstance();
Nandana Dutt979388e2018-11-30 16:48:55 +0000134
135namespace android {
136namespace os {
137namespace {
138
139static int Open(std::string path, int flags, mode_t mode = 0) {
140 int fd = TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode));
141 if (fd == -1) {
142 MYLOGE("open(%s, %s)\n", path.c_str(), strerror(errno));
143 }
144 return fd;
145}
146
Nandana Dutt979388e2018-11-30 16:48:55 +0000147
148static int OpenForRead(std::string path) {
149 return Open(path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
150}
151
152bool CopyFile(int in_fd, int out_fd) {
153 char buf[4096];
154 ssize_t byte_count;
155 while ((byte_count = TEMP_FAILURE_RETRY(read(in_fd, buf, sizeof(buf)))) > 0) {
156 if (!android::base::WriteFully(out_fd, buf, byte_count)) {
157 return false;
158 }
159 }
160 return (byte_count != -1);
161}
162
163static bool CopyFileToFd(const std::string& input_file, int out_fd) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000164 MYLOGD("Going to copy file (%s) to %d\n", input_file.c_str(), out_fd);
Nandana Dutt979388e2018-11-30 16:48:55 +0000165
166 // Obtain a handle to the source file.
167 android::base::unique_fd in_fd(OpenForRead(input_file));
168 if (out_fd != -1 && in_fd.get() != -1) {
169 if (CopyFile(in_fd.get(), out_fd)) {
170 return true;
171 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000172 MYLOGE("Failed to copy file: %s\n", strerror(errno));
Nandana Dutt979388e2018-11-30 16:48:55 +0000173 }
174 return false;
175}
176
Nandana Duttd2f5f082019-01-18 17:13:52 +0000177static bool UnlinkAndLogOnError(const std::string& file) {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000178 if (unlink(file.c_str())) {
179 MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
Nandana Duttd2f5f082019-01-18 17:13:52 +0000180 return false;
181 }
182 return true;
183}
Nandana Dutt979388e2018-11-30 16:48:55 +0000184
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +0000185static bool IsFileEmpty(const std::string& file_path) {
186 std::ifstream file(file_path, std::ios::binary | std::ios::ate);
187 if(file.bad()) {
188 MYLOGE("Cannot open file: %s\n", file_path.c_str());
189 return true;
190 }
191 return file.tellg() <= 0;
192}
193
Nandana Dutt979388e2018-11-30 16:48:55 +0000194} // namespace
195} // namespace os
196} // namespace android
197
Felipe Leme678727a2016-09-21 17:22:11 -0700198static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
199 const CommandOptions& options = CommandOptions::DEFAULT) {
200 return ds.RunCommand(title, fullCommand, options);
201}
202static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800203 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800204 long dumpsysTimeoutMs = 0) {
205 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700206}
207static int DumpFile(const std::string& title, const std::string& path) {
208 return ds.DumpFile(title, path);
209}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800210
Felipe Lemee844a9d2016-09-21 15:01:39 -0700211// Relative directory (inside the zip) for all files copied as-is into the bugreport.
212static const std::string ZIP_ROOT_DIR = "FS";
213
Vishnu Naire97d6122018-01-18 13:58:56 -0800214static const std::string kProtoPath = "proto/";
215static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700216static const std::string kDumpstateBoardFiles[] = {
217 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700218 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700219};
220static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
221
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700222static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700223static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700224static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700225static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
226static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700227
Felipe Lemef0292972016-11-22 13:57:05 -0800228static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
229
Narayan Kamath8f788292017-05-25 13:20:39 +0100230/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100231 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
232 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
233 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700234 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100235 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700236static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
237 const std::string& file_prefix,
238 bool limit_by_mtime,
239 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100240 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
241
Narayan Kamathbd863722017-06-01 18:50:12 +0100242 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100243
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700244 if (dump_dir == nullptr) {
245 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700246 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700247 }
248
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700249 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100250 struct dirent* entry = nullptr;
251 while ((entry = readdir(dump_dir.get()))) {
252 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100253 continue;
254 }
255
Narayan Kamathbd863722017-06-01 18:50:12 +0100256 const std::string base_name(entry->d_name);
257 if (base_name.find(file_prefix) != 0) {
258 continue;
259 }
260
261 const std::string abs_path = dir_path + base_name;
262 android::base::unique_fd fd(
263 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
264 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700265 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100266 break;
267 }
268
269 struct stat st = {};
270 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700271 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100272 continue;
273 }
274
Narayan Kamath3f31b632018-02-22 19:42:36 +0000275 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100276 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100277 continue;
278 }
279
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700280 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700281 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100282
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700283 // Sort in descending modification time so that we only keep the newest
284 // reports if |limit_by_count| is true.
285 std::sort(dump_data.begin(), dump_data.end(),
286 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100287
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700288 if (limit_by_count && dump_data.size() > 10) {
289 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700290 }
291
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700292 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100293}
294
Narayan Kamathbd863722017-06-01 18:50:12 +0100295static bool AddDumps(const std::vector<DumpData>::const_iterator start,
296 const std::vector<DumpData>::const_iterator end,
297 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100298 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100299 for (auto it = start; it != end; ++it) {
300 const std::string& name = it->name;
301 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100302 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100303
304 // Seek to the beginning of the file before dumping any data. A given
305 // DumpData entry might be dumped multiple times in the report.
306 //
307 // For example, the most recent ANR entry is dumped to the body of the
308 // main entry and it also shows up as a separate entry in the bugreport
309 // ZIP file.
310 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
311 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
312 strerror(errno));
313 }
314
Narayan Kamath8f788292017-05-25 13:20:39 +0100315 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800316 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100317 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100318 }
319 } else {
320 dump_file_from_fd(type_name, name.c_str(), fd);
321 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100322 }
323
324 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700325}
326
Felipe Leme635ca312016-01-05 14:23:02 -0800327// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700328void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800329 char path[PATH_MAX];
330
331 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
332 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700333 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800334 char linkname[PATH_MAX];
335 ssize_t r = readlink(path, linkname, PATH_MAX);
336 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800337 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800338 return;
339 }
340 linkname[r] = '\0';
341
342 if (mount_points.find(linkname) == mount_points.end()) {
343 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700344 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700345 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800346 mount_points.insert(linkname);
347 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800348 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800349 }
350 }
351}
352
353void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700354 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700355 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800356 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800357 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700358 for_each_pid(do_mountinfo, nullptr);
359 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800360}
361
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700362static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
363{
364 DIR *d;
365 struct dirent *de;
366 char path[PATH_MAX];
367
368 d = opendir(driverpath);
Yi Kong19d5c002018-07-20 13:39:55 -0700369 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700370 return;
371 }
372
373 while ((de = readdir(d))) {
374 if (de->d_type != DT_LNK) {
375 continue;
376 }
377 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700378 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700379 }
380
381 closedir(d);
382}
383
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700384
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700385
386// dump anrd's trace and add to the zip file.
387// 1. check if anrd is running on this device.
388// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
389// 3. wait until the trace generation completes and add to the zip file.
390static bool dump_anrd_trace() {
391 unsigned int pid;
392 char buf[50], path[PATH_MAX];
393 struct dirent *trace;
394 struct stat st;
395 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700396 int retry = 5;
397 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700398 long long cur_size = 0;
399 const char *trace_path = "/data/misc/anrd/";
400
Felipe Leme1d486fe2016-10-14 18:06:47 -0700401 if (!ds.IsZipping()) {
402 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700403 return false;
404 }
405
406 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700407 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700408
409 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700410 if (stat(trace_path, &st) == 0) {
411 old_mtime = st.st_mtime;
412 } else {
413 MYLOGE("Failed to find: %s\n", trace_path);
414 return false;
415 }
416
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700417 // send SIGUSR1 to the anrd to generate a trace.
418 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700419 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700420 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700421 MYLOGE("anrd signal timed out. Please manually collect trace\n");
422 return false;
423 }
424
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700425 while (retry-- > 0 && old_mtime == st.st_mtime) {
426 sleep(1);
427 stat(trace_path, &st);
428 }
429
430 if (retry < 0 && old_mtime == st.st_mtime) {
431 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
432 return false;
433 }
434
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700435 // identify the trace file by its creation time.
436 if (!(trace_dir = opendir(trace_path))) {
437 MYLOGE("Can't open trace file under %s\n", trace_path);
438 }
439 while ((trace = readdir(trace_dir))) {
440 if (strcmp(trace->d_name, ".") == 0
441 || strcmp(trace->d_name, "..") == 0) {
442 continue;
443 }
444 sprintf(path, "%s%s", trace_path, trace->d_name);
445 if (stat(path, &st) == 0) {
446 if (st.st_ctime > max_ctime) {
447 max_ctime = st.st_ctime;
448 sprintf(buf, "%s", trace->d_name);
449 }
450 }
451 }
452 closedir(trace_dir);
453
454 // Wait until the dump completes by checking the size of the trace.
455 if (max_ctime > 0) {
456 sprintf(path, "%s%s", trace_path, buf);
457 while(true) {
458 sleep(1);
459 if (stat(path, &st) == 0) {
460 if (st.st_size == cur_size) {
461 break;
462 } else if (st.st_size > cur_size) {
463 cur_size = st.st_size;
464 } else {
465 return false;
466 }
467 } else {
468 MYLOGE("Cant stat() %s anymore\n", path);
469 return false;
470 }
471 }
472 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700473 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700474 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
475 } else {
Nandana Dutt16d1aee2019-02-15 16:13:53 +0000476 android::os::UnlinkAndLogOnError(path);
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700477 return true;
478 }
479 } else {
480 MYLOGE("Can't stats any trace file under %s\n", trace_path);
481 }
482 }
483 return false;
484}
485
Mark Salyzyn326842f2015-04-30 09:49:41 -0700486static bool skip_not_stat(const char *path) {
487 static const char stat[] = "/stat";
488 size_t len = strlen(path);
489 if (path[len - 1] == '/') { /* Directory? */
490 return false;
491 }
492 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
493}
494
Felipe Leme4c2d6632016-09-28 14:32:00 -0700495static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800496 return false;
497}
498
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700499unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700500
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800501//
502// stat offsets
503// Name units description
504// ---- ----- -----------
505// read I/Os requests number of read I/Os processed
506#define __STAT_READ_IOS 0
507// read merges requests number of read I/Os merged with in-queue I/O
508#define __STAT_READ_MERGES 1
509// read sectors sectors number of sectors read
510#define __STAT_READ_SECTORS 2
511// read ticks milliseconds total wait time for read requests
512#define __STAT_READ_TICKS 3
513// write I/Os requests number of write I/Os processed
514#define __STAT_WRITE_IOS 4
515// write merges requests number of write I/Os merged with in-queue I/O
516#define __STAT_WRITE_MERGES 5
517// write sectors sectors number of sectors written
518#define __STAT_WRITE_SECTORS 6
519// write ticks milliseconds total wait time for write requests
520#define __STAT_WRITE_TICKS 7
521// in_flight requests number of I/Os currently in flight
522#define __STAT_IN_FLIGHT 8
523// io_ticks milliseconds total time this block device has been active
524#define __STAT_IO_TICKS 9
525// time_in_queue milliseconds total wait time for all requests
526#define __STAT_IN_QUEUE 10
527#define __STAT_NUMBER_FIELD 11
528//
529// read I/Os, write I/Os
530// =====================
531//
532// These values increment when an I/O request completes.
533//
534// read merges, write merges
535// =========================
536//
537// These values increment when an I/O request is merged with an
538// already-queued I/O request.
539//
540// read sectors, write sectors
541// ===========================
542//
543// These values count the number of sectors read from or written to this
544// block device. The "sectors" in question are the standard UNIX 512-byte
545// sectors, not any device- or filesystem-specific block size. The
546// counters are incremented when the I/O completes.
547#define SECTOR_SIZE 512
548//
549// read ticks, write ticks
550// =======================
551//
552// These values count the number of milliseconds that I/O requests have
553// waited on this block device. If there are multiple I/O requests waiting,
554// these values will increase at a rate greater than 1000/second; for
555// example, if 60 read requests wait for an average of 30 ms, the read_ticks
556// field will increase by 60*30 = 1800.
557//
558// in_flight
559// =========
560//
561// This value counts the number of I/O requests that have been issued to
562// the device driver but have not yet completed. It does not include I/O
563// requests that are in the queue but not yet issued to the device driver.
564//
565// io_ticks
566// ========
567//
568// This value counts the number of milliseconds during which the device has
569// had I/O requests queued.
570//
571// time_in_queue
572// =============
573//
574// This value counts the number of milliseconds that I/O requests have waited
575// on this block device. If there are multiple I/O requests waiting, this
576// value will increase as the product of the number of milliseconds times the
577// number of requests waiting (see "read ticks" above for an example).
578#define S_TO_MS 1000
579//
580
Mark Salyzyn326842f2015-04-30 09:49:41 -0700581static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800582 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700583 bool z;
Yi Kong19d5c002018-07-20 13:39:55 -0700584 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700585 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700586 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700587 getline(&buffer, &i, fp);
588 fclose(fp);
589 if (!buffer) {
590 return -errno;
591 }
592 i = strlen(buffer);
593 while ((i > 0) && (buffer[i - 1] == '\n')) {
594 buffer[--i] = '\0';
595 }
596 if (!*buffer) {
597 free(buffer);
598 return 0;
599 }
600 z = true;
601 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800602 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700603 if (fields[i] != 0) {
604 z = false;
605 }
606 }
607 if (z) { /* never accessed */
608 free(buffer);
609 return 0;
610 }
611
Wei Wang509bb5d2017-06-09 14:42:12 -0700612 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
613 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700614 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700615
616 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
617 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
618 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700619 free(buffer);
620
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800621 if (fields[__STAT_IO_TICKS]) {
622 unsigned long read_perf = 0;
623 unsigned long read_ios = 0;
624 if (fields[__STAT_READ_TICKS]) {
625 unsigned long long divisor = fields[__STAT_READ_TICKS]
626 * fields[__STAT_IO_TICKS];
627 read_perf = ((unsigned long long)SECTOR_SIZE
628 * fields[__STAT_READ_SECTORS]
629 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
630 / divisor;
631 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
632 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
633 / divisor;
634 }
635
636 unsigned long write_perf = 0;
637 unsigned long write_ios = 0;
638 if (fields[__STAT_WRITE_TICKS]) {
639 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
640 * fields[__STAT_IO_TICKS];
641 write_perf = ((unsigned long long)SECTOR_SIZE
642 * fields[__STAT_WRITE_SECTORS]
643 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
644 / divisor;
645 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
646 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
647 / divisor;
648 }
649
650 unsigned queue = (fields[__STAT_IN_QUEUE]
651 + (fields[__STAT_IO_TICKS] >> 1))
652 / fields[__STAT_IO_TICKS];
653
654 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700655 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 -0800656 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700657 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 -0800658 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800659 }
660
661 /* bugreport timeout factor adjustment */
662 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
663 worst_write_perf = write_perf;
664 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700665 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700666 return 0;
667}
668
Yao Chenbe3bbc12018-01-17 16:31:10 -0800669static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
670
671/* timeout in ms to read a list of buffers */
672static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
673 unsigned long timeout_ms = 0;
674 for (const auto& buffer : buffers) {
675 log_id_t id = android_name_to_log_id(buffer.c_str());
676 unsigned long property_size = __android_logger_get_buffer_size(id);
677 /* Engineering margin is ten-fold our guess */
678 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
679 }
680 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700681}
682
Nandana Duttd2f5f082019-01-18 17:13:52 +0000683Dumpstate::ConsentCallback::ConsentCallback() : result_(UNAVAILABLE), start_time_(Nanotime()) {
684}
685
686android::binder::Status Dumpstate::ConsentCallback::onReportApproved() {
687 std::lock_guard<std::mutex> lock(lock_);
688 result_ = APPROVED;
689 MYLOGD("User approved consent to share bugreport\n");
690 return android::binder::Status::ok();
691}
692
693android::binder::Status Dumpstate::ConsentCallback::onReportDenied() {
694 std::lock_guard<std::mutex> lock(lock_);
695 result_ = DENIED;
696 MYLOGW("User denied consent to share bugreport\n");
697 return android::binder::Status::ok();
698}
699
700UserConsentResult Dumpstate::ConsentCallback::getResult() {
701 std::lock_guard<std::mutex> lock(lock_);
702 return result_;
703}
704
705uint64_t Dumpstate::ConsentCallback::getElapsedTimeMs() const {
706 return Nanotime() - start_time_;
707}
708
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700709void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700710 std::string build, fingerprint, radio, bootloader, network;
711 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700712
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700713 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
714 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700715 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
716 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
717 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700718 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700719
Felipe Lemed8b94e52016-12-08 10:21:44 -0800720 printf("========================================================\n");
721 printf("== dumpstate: %s\n", date);
722 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700723
Felipe Lemed8b94e52016-12-08 10:21:44 -0800724 printf("\n");
725 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700726 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800727 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
728 printf("Bootloader: %s\n", bootloader.c_str());
729 printf("Radio: %s\n", radio.c_str());
730 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700731
Felipe Lemed8b94e52016-12-08 10:21:44 -0800732 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800733 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800734 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800735 printf("Uptime: ");
736 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
737 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800738 printf("Bugreport format version: %s\n", version_.c_str());
739 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 +0100740 PropertiesHelper::IsDryRun(), options_->args.c_str(), options_->extra_options.c_str());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800741 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800742}
743
Felipe Leme24b66ee2016-06-16 10:55:26 -0700744// List of file extensions that can cause a zip file attachment to be rejected by some email
745// service providers.
746static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
747 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
748 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
749 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
750};
751
Vishnu Naire97d6122018-01-18 13:58:56 -0800752status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
753 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700754 if (!IsZipping()) {
755 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
756 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800757 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800758 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700759 std::string valid_name = entry_name;
760
761 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700762 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700763 if (idx != std::string::npos) {
764 std::string extension = entry_name.substr(idx);
765 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
766 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
767 valid_name = entry_name + ".renamed";
768 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
769 }
770 }
771
Felipe Leme6fe9db62016-02-12 09:04:16 -0800772 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
773 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700774 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
775 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700777 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700778 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800779 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800780 }
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000781 bool finished_entry = false;
782 auto finish_entry = [this, &finished_entry] {
783 if (!finished_entry) {
784 // This should only be called when we're going to return an earlier error,
785 // which would've been logged. This may imply the file is already corrupt
786 // and any further logging from FinishEntry is more likely to mislead than
787 // not.
788 this->zip_writer_->FinishEntry();
789 }
790 };
791 auto scope_guard = android::base::make_scope_guard(finish_entry);
Vishnu Naire97d6122018-01-18 13:58:56 -0800792 auto start = std::chrono::steady_clock::now();
793 auto end = start + timeout;
794 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800795
Felipe Leme770410d2016-01-26 17:07:14 -0800796 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800797 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800798 if (timeout.count() > 0) {
799 // lambda to recalculate the timeout.
800 auto time_left_ms = [end]() {
801 auto now = std::chrono::steady_clock::now();
802 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
803 return std::max(diff.count(), 0LL);
804 };
805
806 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
807 if (rc < 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000808 MYLOGE("Error in poll while adding from fd to zip entry %s:%s\n",
809 entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800810 return -errno;
811 } else if (rc == 0) {
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000812 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms\n",
Vishnu Naire97d6122018-01-18 13:58:56 -0800813 entry_name.c_str(), strerror(errno), timeout.count());
814 return TIMED_OUT;
815 }
816 }
817
Zach Riggle22200402016-08-18 01:01:24 -0400818 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800819 if (bytes_read == 0) {
820 break;
821 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800822 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800823 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800824 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700825 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800826 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700827 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800828 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800829 }
830 }
831
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700832 err = zip_writer_->FinishEntry();
Narayan Kamath895f8fc2019-02-08 18:18:08 +0000833 finished_entry = true;
Felipe Leme1d486fe2016-10-14 18:06:47 -0700834 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700835 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800836 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800837 }
838
Vishnu Naire97d6122018-01-18 13:58:56 -0800839 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800840}
841
Felipe Leme1d486fe2016-10-14 18:06:47 -0700842bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
843 android::base::unique_fd fd(
844 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700845 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800846 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800847 return false;
848 }
849
Vishnu Naire97d6122018-01-18 13:58:56 -0800850 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800851}
852
853/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700854static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800855 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800856}
857
Felipe Leme1d486fe2016-10-14 18:06:47 -0700858void Dumpstate::AddDir(const std::string& dir, bool recursive) {
859 if (!IsZipping()) {
860 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800861 return;
862 }
Felipe Leme678727a2016-09-21 17:22:11 -0700863 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800864 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700865 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800866}
867
Felipe Leme1d486fe2016-10-14 18:06:47 -0700868bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
869 if (!IsZipping()) {
870 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
871 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800872 return false;
873 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800874 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700875 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700876 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700877 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700878 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800879 return false;
880 }
881
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700882 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700883 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700884 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700885 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800886 return false;
887 }
888
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700889 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700890 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700891 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800892 return false;
893 }
894
895 return true;
896}
897
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800898static void DoKmsg() {
899 struct stat st;
900 if (!stat(PSTORE_LAST_KMSG, &st)) {
901 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
902 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
903 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
904 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
905 } else {
906 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
907 DumpFile("LAST KMSG", "/proc/last_kmsg");
908 }
909}
910
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800911static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800912 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800913 RunCommand(
914 "KERNEL LOG",
915 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
916 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
917}
918
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800919static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800920 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800921 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
922 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800923 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100924 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800925 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
926 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800927 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800928 RunCommand(
929 "EVENT LOG",
930 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
931 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800932 timeout_ms = logcat_timeout({"stats"});
933 RunCommand(
934 "STATS LOG",
935 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
936 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
937 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800938 RunCommand(
939 "RADIO LOG",
940 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
941 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800942
943 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
944
945 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800946 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
947 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800948}
949
Jayachandran Ca94c7172017-06-10 15:08:12 -0700950static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700951 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
952 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900953 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700954 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900955 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
956 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
957 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
958 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700959}
960
Narayan Kamath8f788292017-05-25 13:20:39 +0100961static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
962 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
963 anr_traces_dir.c_str());
964
965 // If we're here, dump_traces_path will always be a temporary file
966 // (created with mkostemp or similar) that contains dumps taken earlier
967 // on in the process.
968 if (dump_traces_path != nullptr) {
969 if (add_to_zip) {
970 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
971 } else {
972 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
973 dump_traces_path);
974 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
975 }
976
977 const int ret = unlink(dump_traces_path);
978 if (ret == -1) {
979 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
980 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700981 }
982 }
983
Narayan Kamathbd863722017-06-01 18:50:12 +0100984 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700985 if (ds.anr_data_.size() > 0) {
986 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +0100987 "VM TRACES AT LAST ANR", add_to_zip);
988
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100989 // The "last" ANR will always be included as separate entry in the zip file. In addition,
990 // it will be present in the body of the main entry if |add_to_zip| == false.
991 //
992 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700993 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100994 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100995 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100996 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
997 }
998}
999
1000static void AddAnrTraceFiles() {
1001 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1002
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001003 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +01001004
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001005 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +01001006
Makoto Onuki83ec63f2019-01-31 17:08:59 -08001007 RunCommand("ANR FILES", {"ls", "-lt", ANR_DIR});
1008
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001009 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -07001010 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001011 int i = 0;
1012 while (true) {
1013 const std::string slow_trace_path =
1014 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1015 if (stat(slow_trace_path.c_str(), &st)) {
1016 // No traces file at this index, done with the files.
1017 break;
Felipe Lemee184f662016-10-27 10:04:47 -07001018 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -07001019 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
1020 i++;
Felipe Lemee184f662016-10-27 10:04:47 -07001021 }
1022}
1023
Wei Wang509bb5d2017-06-09 14:42:12 -07001024static void DumpBlockStatFiles() {
1025 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001026
Wei Wang1dc1ef52017-06-12 11:28:37 -07001027 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1028
1029 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001030 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1031 return;
1032 }
1033
1034 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001035 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001036 if ((d->d_name[0] == '.')
1037 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1038 || (d->d_name[1] == '\0'))) {
1039 continue;
1040 }
1041 const std::string new_path =
1042 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1043 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1044 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1045 printf("\n");
1046 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001047 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001048}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001049
1050static void DumpPacketStats() {
1051 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1052 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1053 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1054 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1055 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1056}
1057
1058static void DumpIpAddrAndRules() {
1059 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1060 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1061 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1062 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1063 RunCommand("IP RULES", {"ip", "rule", "show"});
1064 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1065}
1066
Vishnu Nair64afc022018-02-01 15:29:34 -08001067static void RunDumpsysTextByPriority(const std::string& title, int priority,
1068 std::chrono::milliseconds timeout,
1069 std::chrono::milliseconds service_timeout) {
1070 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001071 sp<android::IServiceManager> sm = defaultServiceManager();
1072 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001073 Vector<String16> args;
1074 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001075 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1076 for (const String16& service : services) {
1077 std::string path(title);
1078 path.append(" - ").append(String8(service).c_str());
1079 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1080 size_t bytes_written = 0;
1081 status_t status = dumpsys.startDumpThread(service, args);
1082 if (status == OK) {
1083 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1084 std::chrono::duration<double> elapsed_seconds;
1085 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1086 /* as_proto = */ false, elapsed_seconds, bytes_written);
1087 section_reporter.setSize(bytes_written);
1088 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1089 bool dump_complete = (status == OK);
1090 dumpsys.stopDumpThread(dump_complete);
1091 }
1092 section_reporter.setStatus(status);
1093
1094 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1095 std::chrono::steady_clock::now() - start);
1096 if (elapsed_duration > timeout) {
1097 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1098 elapsed_duration.count());
1099 break;
1100 }
1101 }
1102}
1103
Vishnu Nair64afc022018-02-01 15:29:34 -08001104static void RunDumpsysText(const std::string& title, int priority,
1105 std::chrono::milliseconds timeout,
1106 std::chrono::milliseconds service_timeout) {
1107 DurationReporter duration_reporter(title);
1108 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1109 fsync(STDOUT_FILENO);
1110 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1111}
1112
1113/* Dump all services registered with Normal or Default priority. */
1114static void RunDumpsysTextNormalPriority(const std::string& title,
1115 std::chrono::milliseconds timeout,
1116 std::chrono::milliseconds service_timeout) {
1117 DurationReporter duration_reporter(title);
1118 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1119 fsync(STDOUT_FILENO);
1120 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1121 service_timeout);
1122 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1123 service_timeout);
1124}
1125
1126static void RunDumpsysProto(const std::string& title, int priority,
1127 std::chrono::milliseconds timeout,
1128 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001129 if (!ds.IsZipping()) {
1130 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1131 return;
1132 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001133 sp<android::IServiceManager> sm = defaultServiceManager();
1134 Dumpsys dumpsys(sm.get());
1135 Vector<String16> args;
1136 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1137 DurationReporter duration_reporter(title);
1138
1139 auto start = std::chrono::steady_clock::now();
1140 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1141 for (const String16& service : services) {
1142 std::string path(kProtoPath);
1143 path.append(String8(service).c_str());
1144 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1145 path.append("_CRITICAL");
1146 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1147 path.append("_HIGH");
1148 }
1149 path.append(kProtoExt);
1150 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1151 status_t status = dumpsys.startDumpThread(service, args);
1152 if (status == OK) {
1153 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1154 bool dumpTerminated = (status == OK);
1155 dumpsys.stopDumpThread(dumpTerminated);
1156 }
1157 ZipWriter::FileEntry file_entry;
1158 ds.zip_writer_->GetLastEntry(&file_entry);
1159 section_reporter.setSize(file_entry.compressed_size);
1160 section_reporter.setStatus(status);
1161
1162 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1163 std::chrono::steady_clock::now() - start);
1164 if (elapsed_duration > timeout) {
1165 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1166 elapsed_duration.count());
1167 break;
1168 }
1169 }
1170}
1171
Nandana Dutta7db6342018-11-21 14:53:34 +00001172// Runs dumpsys on services that must dump first and will take less than 100ms to dump.
Vishnu Nair780b1282017-10-10 13:57:24 -07001173static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001174 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1175 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1176 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1177 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001178}
1179
1180// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1181static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001182 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1183 // high priority. Reduce timeout once they are able to dump in a shorter time or
1184 // moved to a parallel task.
1185 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1186 /* timeout= */ 90s, /* service_timeout= */ 30s);
1187 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1188 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001189}
1190
1191// Runs dumpsys on services that must dump but can take up to 10s to dump.
1192static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001193 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1194 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1195 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001196}
1197
Steven Moreland44cd9482018-01-04 16:24:13 -08001198static void DumpHals() {
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001199 if (!ds.IsZipping()) {
1200 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1201 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
1202 return;
1203 }
1204 DurationReporter duration_reporter("DUMP HALS");
1205 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1206 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1207
Steven Moreland44cd9482018-01-04 16:24:13 -08001208 using android::hidl::manager::V1_0::IServiceManager;
1209 using android::hardware::defaultServiceManager;
1210
1211 sp<IServiceManager> sm = defaultServiceManager();
1212 if (sm == nullptr) {
1213 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1214 return;
1215 }
1216
1217 auto ret = sm->list([&](const auto& interfaces) {
1218 for (const std::string& interface : interfaces) {
1219 std::string cleanName = interface;
1220 std::replace_if(cleanName.begin(),
1221 cleanName.end(),
1222 [](char c) {
1223 return !isalnum(c) &&
1224 std::string("@-_:.").find(c) == std::string::npos;
1225 }, '_');
Nandana Dutt979388e2018-11-30 16:48:55 +00001226 const std::string path = ds.bugreport_internal_dir_ + "/lshal_debug_" + cleanName;
Steven Moreland44cd9482018-01-04 16:24:13 -08001227
1228 {
1229 auto fd = android::base::unique_fd(
1230 TEMP_FAILURE_RETRY(open(path.c_str(),
1231 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1232 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1233 if (fd < 0) {
1234 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1235 continue;
1236 }
1237 RunCommandToFd(fd,
1238 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001239 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001240 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1241
1242 bool empty = 0 == lseek(fd, 0, SEEK_END);
1243 if (!empty) {
1244 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1245 }
1246 }
1247
1248 unlink(path.c_str());
1249 }
1250 });
1251
1252 if (!ret.isOk()) {
1253 MYLOGE("Could not list hals from hwservicemanager.\n");
1254 }
1255}
1256
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001257static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001258 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001259
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001260 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001261 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001262 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001263 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001264 DumpFile("MEMORY INFO", "/proc/meminfo");
1265 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001266 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001267 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001268 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1269 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1270 DumpFile("SLAB INFO", "/proc/slabinfo");
1271 DumpFile("ZONEINFO", "/proc/zoneinfo");
1272 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1273 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1274 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001275
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001276 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1277 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1278 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001279
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001280 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001281 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001282 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001283
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001284 DumpHals();
Steven Moreland81b429e2017-01-31 19:50:46 -08001285
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001286 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001287 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001288 struct stat s;
1289 if (stat("/proc/modules", &s) != 0) {
1290 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1291 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001292 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001293 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001294
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001295 if (__android_logger_property_get_bool(
1296 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1297 DoKernelLogcat();
1298 } else {
1299 do_dmesg();
1300 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001301
Felipe Lemef0292972016-11-22 13:57:05 -08001302 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001303 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1304 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001305 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001307 /* Dump Bluetooth HCI logs */
1308 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001309
Felipe Leme9a523ae2016-10-20 15:10:33 -07001310 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001311 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001312 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001313 }
1314
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001315 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001316
Felipe Lemee184f662016-10-27 10:04:47 -07001317 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001318
Narayan Kamath8f788292017-05-25 13:20:39 +01001319 // NOTE: tombstones are always added as separate entries in the zip archive
1320 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001321 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001322 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001323 if (!tombstones_dumped) {
1324 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001325 }
1326
Jayachandran Ca94c7172017-06-10 15:08:12 -07001327 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001328
Chenbo Feng276a3b62018-08-07 11:44:49 -07001329 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1330
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001331 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001332
Jayachandran Ca94c7172017-06-10 15:08:12 -07001333 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001334
1335 dump_route_tables();
1336
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001337 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1338 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1339 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001340
Vishnu Nair780b1282017-10-10 13:57:24 -07001341 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001342
Elliott Hughes23ccc622017-02-28 10:14:22 -08001343 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001344
Jin Qianf334d662017-10-10 14:41:37 -07001345 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001346
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001347 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001348
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001349 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001350
Colin Crossf45fa6b2012-03-26 12:38:26 -07001351 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001352 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1353 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1354 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1355 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1356 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001357
Nataniel Borgesbc73f522019-01-25 16:37:16 -08001358 RunDumpsys("WINSCOPE TRACE", {"window", "trace"});
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001359 /* Add window and surface trace files. */
1360 if (!PropertiesHelper::IsUserBuild()) {
1361 ds.AddDir(WMTRACE_DATA_DIR, false);
1362 }
1363
Felipe Leme6f674ae2016-11-18 17:10:33 -08001364 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001365
Steven Moreland7440ddb2016-12-15 16:13:39 -08001366 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001367 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1368 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001369 // su does not exist on user builds, so try running without it.
1370 // This way any implementations of vril-dump that do not require
1371 // root can run on user builds.
1372 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001373 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001374 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001375 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001376 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001377 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001378 }
1379
Felipe Lemed8b94e52016-12-08 10:21:44 -08001380 printf("========================================================\n");
1381 printf("== Android Framework Services\n");
1382 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001383
Vishnu Nair780b1282017-10-10 13:57:24 -07001384 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001385
Felipe Lemed8b94e52016-12-08 10:21:44 -08001386 printf("========================================================\n");
1387 printf("== Checkins\n");
1388 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001389
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001390 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1391 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1392 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1393 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1394 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1395 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001396
Felipe Lemed8b94e52016-12-08 10:21:44 -08001397 printf("========================================================\n");
1398 printf("== Running Application Activities\n");
1399 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001400
Makoto Onuki60780982018-04-16 15:34:00 -07001401 // The following dumpsys internally collects output from running apps, so it can take a long
1402 // time. So let's extend the timeout.
1403
1404 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1405
1406 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001407
Felipe Lemed8b94e52016-12-08 10:21:44 -08001408 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001409 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001410 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001411
Vishnu Nairc6e6ea72018-07-02 14:20:06 -07001412 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001413 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001414
Felipe Lemed8b94e52016-12-08 10:21:44 -08001415 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001416 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001417 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001418
Makoto Onuki60780982018-04-16 15:34:00 -07001419 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1420 DUMPSYS_COMPONENTS_OPTIONS);
1421
1422 printf("========================================================\n");
1423 printf("== Running Application Providers (platform)\n");
1424 printf("========================================================\n");
1425
1426 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1427 DUMPSYS_COMPONENTS_OPTIONS);
1428
1429 printf("========================================================\n");
1430 printf("== Running Application Providers (non-platform)\n");
1431 printf("========================================================\n");
1432
1433 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1434 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001435
Adrian Roos8b397ab2017-04-04 16:35:44 -07001436 printf("========================================================\n");
1437 printf("== Dropbox crashes\n");
1438 printf("========================================================\n");
1439
1440 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1441 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1442
Felipe Lemed8b94e52016-12-08 10:21:44 -08001443 printf("========================================================\n");
1444 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1445 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1446 printf("========================================================\n");
1447 printf("== dumpstate: done (id %d)\n", ds.id_);
1448 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001449}
1450
Nandana Dutt4be45d12018-09-26 15:04:23 +01001451/* Dumps state for the default case. Returns true if everything went fine. */
1452static bool DumpstateDefault() {
Primiano Tucci2d7f5c22019-01-17 15:51:14 +00001453 // Try to dump anrd trace if the daemon is running.
1454 dump_anrd_trace();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001455
1456 // Invoking the following dumpsys calls before dump_traces() to try and
1457 // keep the system stats as close to its initial state as possible.
1458 RunDumpsysCritical();
1459
1460 /* collect stack traces from Dalvik and native processes (needs root) */
Nandana Duttfaafd522019-03-11 09:23:09 +00001461 dump_traces_path = ds.DumpTraces();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001462
1463 /* Run some operations that require root. */
1464 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1465 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1466
1467 ds.AddDir(RECOVERY_DIR, true);
1468 ds.AddDir(RECOVERY_DATA_DIR, true);
1469 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1470 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1471 if (!PropertiesHelper::IsUserBuild()) {
1472 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1473 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1474 }
1475 add_mountinfo();
1476 DumpIpTablesAsRoot();
1477
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001478 // Capture any IPSec policies in play. No keys are exposed here.
Nandana Dutt4be45d12018-09-26 15:04:23 +01001479 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1480
Benedict Wong8f9d8a42019-01-03 16:19:38 -08001481 // Dump IPsec stats. No keys are exposed here.
1482 DumpFile("XFRM STATS", XFRM_STAT_PROC_FILE);
1483
Nandana Dutt4be45d12018-09-26 15:04:23 +01001484 // Run ss as root so we can see socket marks.
1485 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1486
1487 // Run iotop as root to show top 100 IO threads
1488 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1489
Erick Reyese68df822019-02-11 14:46:36 -08001490 // Gather shared memory buffer info if the product implements it
1491 struct stat st;
1492 if (!stat("/product/bin/dmabuf_dump", &st)) {
1493 RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
1494 }
1495
Nandana Dutt4be45d12018-09-26 15:04:23 +01001496 if (!DropRootUser()) {
1497 return false;
1498 }
1499
1500 dumpstate();
1501 return true;
1502}
1503
mukesh agrawal253dad42018-01-23 21:59:59 -08001504// This method collects common dumpsys for telephony and wifi
1505static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001506 DumpIpTablesAsRoot();
1507
1508 if (!DropRootUser()) {
1509 return;
1510 }
1511
1512 do_dmesg();
1513 DoLogcat();
1514 DumpPacketStats();
1515 DoKmsg();
1516 DumpIpAddrAndRules();
1517 dump_route_tables();
1518
1519 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1520 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001521}
1522
1523// This method collects dumpsys for telephony debugging only
1524static void DumpstateTelephonyOnly() {
1525 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001526 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001527
1528 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001529
1530 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1531
1532 printf("========================================================\n");
1533 printf("== Android Framework Services\n");
1534 printf("========================================================\n");
1535
Vishnu Nair652cc802017-11-30 15:18:30 -08001536 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1537 SEC_TO_MSEC(10));
1538 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1539 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001540 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1541 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001542 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1543 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001544
1545 printf("========================================================\n");
1546 printf("== Running Application Services\n");
1547 printf("========================================================\n");
1548
1549 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1550
1551 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001552 printf("== Running Application Services (non-platform)\n");
1553 printf("========================================================\n");
1554
1555 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1556 DUMPSYS_COMPONENTS_OPTIONS);
1557
1558 printf("========================================================\n");
Kelly Rossmoyer769babb2018-08-21 18:06:38 -07001559 printf("== Checkins\n");
1560 printf("========================================================\n");
1561
1562 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1563
1564 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001565 printf("== dumpstate: done (id %d)\n", ds.id_);
1566 printf("========================================================\n");
1567}
1568
mukesh agrawal253dad42018-01-23 21:59:59 -08001569// This method collects dumpsys for wifi debugging only
1570static void DumpstateWifiOnly() {
1571 DurationReporter duration_reporter("DUMPSTATE");
1572
1573 DumpstateRadioCommon();
1574
1575 printf("========================================================\n");
1576 printf("== Android Framework Services\n");
1577 printf("========================================================\n");
1578
1579 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1580 SEC_TO_MSEC(10));
1581 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1582 SEC_TO_MSEC(10));
1583
Nandana Dutt6ad9a602019-03-11 16:33:24 +00001584 DumpHals();
Roger Wang70399032019-01-08 16:10:37 +08001585
mukesh agrawal253dad42018-01-23 21:59:59 -08001586 printf("========================================================\n");
1587 printf("== dumpstate: done (id %d)\n", ds.id_);
1588 printf("========================================================\n");
1589}
1590
Nandana Duttfaafd522019-03-11 09:23:09 +00001591const char* Dumpstate::DumpTraces() {
1592 DurationReporter duration_reporter("DUMP TRACES");
1593
1594 const std::string temp_file_pattern = "/data/anr/dumptrace_XXXXXX";
1595 const size_t buf_size = temp_file_pattern.length() + 1;
1596 std::unique_ptr<char[]> file_name_buf(new char[buf_size]);
1597 memcpy(file_name_buf.get(), temp_file_pattern.c_str(), buf_size);
1598
1599 // Create a new, empty file to receive all trace dumps.
1600 //
1601 // TODO: This can be simplified once we remove support for the old style
1602 // dumps. We can have a file descriptor passed in to dump_traces instead
1603 // of creating a file, closing it and then reopening it again.
1604 android::base::unique_fd fd(mkostemp(file_name_buf.get(), O_APPEND | O_CLOEXEC));
1605 if (fd < 0) {
1606 MYLOGE("mkostemp on pattern %s: %s\n", file_name_buf.get(), strerror(errno));
1607 return nullptr;
1608 }
1609
1610 // Nobody should have access to this temporary file except dumpstate, but we
1611 // temporarily grant 'read' to 'others' here because this file is created
1612 // when tombstoned is still running as root, but dumped after dropping. This
1613 // can go away once support for old style dumping has.
1614 const int chmod_ret = fchmod(fd, 0666);
1615 if (chmod_ret < 0) {
1616 MYLOGE("fchmod on %s failed: %s\n", file_name_buf.get(), strerror(errno));
1617 return nullptr;
1618 }
1619
1620 std::unique_ptr<DIR, decltype(&closedir)> proc(opendir("/proc"), closedir);
1621 if (proc.get() == nullptr) {
1622 MYLOGE("opendir /proc failed: %s\n", strerror(errno));
1623 return nullptr;
1624 }
1625
1626 // Number of times process dumping has timed out. If we encounter too many
1627 // failures, we'll give up.
1628 int timeout_failures = 0;
1629 bool dalvik_found = false;
1630
1631 const std::set<int> hal_pids = get_interesting_hal_pids();
1632
1633 struct dirent* d;
1634 while ((d = readdir(proc.get()))) {
1635 int pid = atoi(d->d_name);
1636 if (pid <= 0) {
1637 continue;
1638 }
1639
1640 const std::string link_name = android::base::StringPrintf("/proc/%d/exe", pid);
1641 std::string exe;
1642 if (!android::base::Readlink(link_name, &exe)) {
1643 continue;
1644 }
1645
1646 bool is_java_process;
1647 if (exe == "/system/bin/app_process32" || exe == "/system/bin/app_process64") {
1648 // Don't bother dumping backtraces for the zygote.
1649 if (IsZygote(pid)) {
1650 continue;
1651 }
1652
1653 dalvik_found = true;
1654 is_java_process = true;
1655 } else if (should_dump_native_traces(exe.c_str()) || hal_pids.find(pid) != hal_pids.end()) {
1656 is_java_process = false;
1657 } else {
1658 // Probably a native process we don't care about, continue.
1659 continue;
1660 }
1661
1662 // If 3 backtrace dumps fail in a row, consider debuggerd dead.
1663 if (timeout_failures == 3) {
1664 dprintf(fd, "ERROR: Too many stack dump failures, exiting.\n");
1665 break;
1666 }
1667
1668 const uint64_t start = Nanotime();
1669 const int ret = dump_backtrace_to_file_timeout(
1670 pid, is_java_process ? kDebuggerdJavaBacktrace : kDebuggerdNativeBacktrace,
1671 is_java_process ? 5 : 20, fd);
1672
1673 if (ret == -1) {
1674 // For consistency, the header and footer to this message match those
1675 // dumped by debuggerd in the success case.
1676 dprintf(fd, "\n---- pid %d at [unknown] ----\n", pid);
1677 dprintf(fd, "Dump failed, likely due to a timeout.\n");
1678 dprintf(fd, "---- end %d ----", pid);
1679 timeout_failures++;
1680 continue;
1681 }
1682
1683 // We've successfully dumped stack traces, reset the failure count
1684 // and write a summary of the elapsed time to the file and continue with the
1685 // next process.
1686 timeout_failures = 0;
1687
1688 dprintf(fd, "[dump %s stack %d: %.3fs elapsed]\n", is_java_process ? "dalvik" : "native",
1689 pid, (float)(Nanotime() - start) / NANOS_PER_SEC);
1690 }
1691
1692 if (!dalvik_found) {
1693 MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
1694 }
1695
1696 return file_name_buf.release();
1697}
1698
Felipe Leme6f674ae2016-11-18 17:10:33 -08001699void Dumpstate::DumpstateBoard() {
1700 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001701 printf("========================================================\n");
1702 printf("== Board\n");
1703 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001704
Felipe Leme6f674ae2016-11-18 17:10:33 -08001705 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001706 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001707 return;
1708 }
1709
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001710 std::vector<std::string> paths;
1711 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001712 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Nandana Dutt979388e2018-11-30 16:48:55 +00001713 paths.emplace_back(StringPrintf("%s/%s", ds.bugreport_internal_dir_.c_str(),
1714 kDumpstateBoardFiles[i].c_str()));
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001715 remover.emplace_back(android::base::make_scope_guard(
1716 std::bind([](std::string path) { android::os::UnlinkAndLogOnError(path); }, paths[i])));
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001717 }
Jie Song9fbfad02017-06-20 16:29:42 -07001718
Wei Wang587eac92018-04-05 12:17:20 -07001719 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1720 if (dumpstate_device == nullptr) {
1721 MYLOGE("No IDumpstateDevice implementation\n");
1722 return;
1723 }
1724
1725 using ScopedNativeHandle =
1726 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1727 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1728 [](native_handle_t* handle) {
1729 native_handle_close(handle);
1730 native_handle_delete(handle);
1731 });
1732 if (handle == nullptr) {
1733 MYLOGE("Could not create native_handle\n");
1734 return;
1735 }
1736
1737 for (size_t i = 0; i < paths.size(); i++) {
1738 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1739
1740 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1741 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1742 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1743 if (fd < 0) {
1744 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1745 return;
1746 }
1747 handle.get()->data[i] = fd.release();
1748 }
1749
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001750 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001751 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1752 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1753 // and grab whatever dumped
1754 std::packaged_task<bool()>
1755 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001756 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1757 if (!status.isOk()) {
1758 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001759 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001760 }
Wei Wang587eac92018-04-05 12:17:20 -07001761 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001762 });
Wei Wang587eac92018-04-05 12:17:20 -07001763
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001764 auto result = dumpstate_task.get_future();
1765 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001766
1767 constexpr size_t timeout_sec = 30;
1768 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1769 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1770 if (!android::base::SetProperty("ctl.interface_restart",
1771 android::base::StringPrintf("%s/default",
1772 IDumpstateDevice::descriptor))) {
1773 MYLOGE("Couldn't restart dumpstate HAL\n");
1774 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001775 }
Wei Wang587eac92018-04-05 12:17:20 -07001776 // Wait some time for init to kill dumpstate vendor HAL
1777 constexpr size_t killing_timeout_sec = 10;
1778 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1779 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1780 "there might be racing in content\n", killing_timeout_sec);
1781 }
1782
1783 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1784 for (size_t i = 0; i < paths.size(); i++) {
1785 struct stat s;
1786 if (fstat(handle.get()->data[i], &s) == -1) {
1787 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1788 strerror(errno));
1789 file_sizes[i] = -1;
1790 continue;
1791 }
1792 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001793 }
1794
1795 for (size_t i = 0; i < paths.size(); i++) {
1796 if (file_sizes[i] == -1) {
1797 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001798 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001799 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001800 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001801 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001802 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001803 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001804 }
1805
Felipe Lemed8b94e52016-12-08 10:21:44 -08001806 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001807}
1808
Nandana Dutt12ae14a2019-01-09 10:35:53 +00001809static void ShowUsage() {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001810 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001811 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001812 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1813 " -h: display this help message\n"
1814 " -b: play sound file instead of vibrate, at beginning of job\n"
1815 " -e: play sound file instead of vibrate, at end of job\n"
1816 " -o: write to file (instead of stdout)\n"
1817 " -d: append date to filename (requires -o)\n"
1818 " -p: capture screenshot to filename.png (requires -o)\n"
1819 " -z: generate zipped file (requires -o)\n"
1820 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001821 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001822 " -q: disable vibrate\n"
1823 " -B: send broadcast when finished (requires -o)\n"
1824 " -P: send broadcast when started and update system properties on "
1825 "progress (requires -o and -B)\n"
1826 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1827 "shouldn't be used with -P)\n"
Nandana Dutt235864b2019-01-22 12:10:16 +00001828 " -w: start binder service and make it wait for a call to startBugreport\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001829 " -v: prints the dumpstate header and exit\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001830}
1831
Wei Liuf87959e2016-08-26 14:51:42 -07001832static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001833 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001834}
1835
Felipe Leme1d486fe2016-10-14 18:06:47 -07001836bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001837 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001838 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001839 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001840 // Final timestamp
1841 char date[80];
1842 time_t the_real_now_please_stand_up = time(nullptr);
1843 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001844 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001845 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001846
Felipe Leme9a523ae2016-10-20 15:10:33 -07001847 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001848 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001849 return false;
1850 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001851 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001852 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001853 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001854 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001855
Felipe Leme0f3fb202016-06-10 17:10:53 -07001856 // Add log file (which contains stderr output) to zip...
1857 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001858 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001859 MYLOGE("Failed to add dumpstate log to .zip file\n");
1860 return false;
1861 }
Nandana Dutt979388e2018-11-30 16:48:55 +00001862 // TODO: Should truncate the existing file.
1863 // ... and re-open it for further logging.
Nandana Dutta344cb62019-02-22 15:12:35 +00001864 if (!redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()))) {
1865 return false;
1866 }
Felipe Leme0f3fb202016-06-10 17:10:53 -07001867 fprintf(stderr, "\n");
1868
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001869 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001870 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001871 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001872 return false;
1873 }
1874
Felipe Leme1d486fe2016-10-14 18:06:47 -07001875 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1876 ds.zip_file.reset(nullptr);
1877
Felipe Lemee9d2c542016-11-15 11:48:26 -08001878 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
Nandana Dutt16d1aee2019-02-15 16:13:53 +00001879 android::os::UnlinkAndLogOnError(tmp_path_);
Felipe Lemec4eee562016-04-21 15:42:55 -07001880
Felipe Leme1e9edc62015-12-21 16:02:13 -08001881 return true;
1882}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001883
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001884static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001885 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1886 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001887 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001888 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001889 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001890 }
1891
1892 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001893 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001894
1895 std::vector<uint8_t> buffer(65536);
1896 while (1) {
1897 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1898 if (bytes_read == 0) {
1899 break;
1900 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001901 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001902 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001903 }
1904
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001905 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001906 }
1907
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001908 uint8_t hash[SHA256_DIGEST_LENGTH];
1909 SHA256_Final(hash, &ctx);
1910
1911 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1912 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001913 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001914 }
1915 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1916 return std::string(hash_buffer);
1917}
1918
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001919static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1920 // clang-format off
1921 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1922 "--receiver-foreground", "--receiver-include-background", "-a", action};
1923 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001924
1925 am.insert(am.end(), args.begin(), args.end());
1926
Felipe Leme8d2410e2017-02-08 09:46:08 -08001927 RunCommand("", am,
1928 CommandOptions::WithTimeout(20)
1929 .Log("Sending broadcast: '%s'\n")
1930 .Always()
1931 .DropRoot()
1932 .RedirectStderr()
1933 .Build());
1934}
1935
Felipe Leme35b8cf12017-02-10 15:47:29 -08001936static void Vibrate(int duration_ms) {
1937 // clang-format off
1938 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1939 CommandOptions::WithTimeout(10)
1940 .Log("Vibrate: '%s'\n")
1941 .Always()
1942 .Build());
1943 // clang-format on
1944}
1945
Nandana Dutt979388e2018-11-30 16:48:55 +00001946static void MaybeResolveSymlink(std::string* path) {
1947 std::string resolved_path;
1948 if (android::base::Readlink(*path, &resolved_path)) {
1949 *path = resolved_path;
1950 }
1951}
1952
Nandana Dutt4be45d12018-09-26 15:04:23 +01001953/*
1954 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
1955 * if we are writing zip files and adds the version file.
1956 */
1957static void PrepareToWriteToFile() {
Nandana Dutt979388e2018-11-30 16:48:55 +00001958 MaybeResolveSymlink(&ds.bugreport_internal_dir_);
1959
Nandana Dutt4be45d12018-09-26 15:04:23 +01001960 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1961 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Nandana Dutt9a76d202019-01-21 15:56:48 +00001962 ds.base_name_ = StringPrintf("bugreport-%s-%s", device_name.c_str(), build_id.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001963 if (ds.options_->do_add_date) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001964 char date[80];
1965 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
1966 ds.name_ = date;
1967 } else {
1968 ds.name_ = "undated";
1969 }
1970
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001971 if (ds.options_->telephony_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001972 ds.base_name_ += "-telephony";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001973 } else if (ds.options_->wifi_only) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001974 ds.base_name_ += "-wifi";
1975 }
1976
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001977 if (ds.options_->do_fb) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001978 ds.screenshot_path_ = ds.GetPath(".png");
1979 }
1980 ds.tmp_path_ = ds.GetPath(".tmp");
1981 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
1982
Nandana Dutt54dbd672019-01-11 12:58:05 +00001983 std::string destination = ds.options_->bugreport_fd.get() != -1
1984 ? StringPrintf("[fd:%d]", ds.options_->bugreport_fd.get())
Nandana Dutt9a76d202019-01-21 15:56:48 +00001985 : ds.bugreport_internal_dir_.c_str();
Nandana Dutt4be45d12018-09-26 15:04:23 +01001986 MYLOGD(
1987 "Bugreport dir: %s\n"
1988 "Base name: %s\n"
1989 "Suffix: %s\n"
1990 "Log path: %s\n"
1991 "Temporary path: %s\n"
1992 "Screenshot path: %s\n",
Nandana Dutt9a76d202019-01-21 15:56:48 +00001993 destination.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
1994 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01001995
Nandana Dutt5fb117b2018-09-27 09:23:36 +01001996 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01001997 ds.path_ = ds.GetPath(".zip");
1998 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1999 create_parent_dirs(ds.path_.c_str());
2000 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
2001 if (ds.zip_file == nullptr) {
2002 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
2003 } else {
2004 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
2005 }
2006 ds.AddTextZipEntry("version.txt", ds.version_);
2007 }
2008}
2009
2010/*
2011 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
2012 * printing zipped file status, etc.
2013 */
2014static void FinalizeFile() {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002015 /* check if user changed the suffix using system properties */
2016 std::string name =
2017 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
2018 bool change_suffix = false;
2019 if (!name.empty()) {
2020 /* must whitelist which characters are allowed, otherwise it could cross directories */
2021 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
2022 if (std::regex_match(name.c_str(), valid_regex)) {
2023 change_suffix = true;
2024 } else {
2025 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
2026 }
2027 }
2028 if (change_suffix) {
2029 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2030 ds.name_ = name;
2031 if (!ds.screenshot_path_.empty()) {
2032 std::string new_screenshot_path = ds.GetPath(".png");
2033 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2034 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2035 new_screenshot_path.c_str(), strerror(errno));
2036 } else {
2037 ds.screenshot_path_ = new_screenshot_path;
2038 }
2039 }
2040 }
2041
2042 bool do_text_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002043 if (ds.options_->do_zip_file) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002044 if (!ds.FinishZipFile()) {
2045 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
2046 do_text_file = true;
2047 } else {
2048 do_text_file = false;
Nandana Dutt383d0c12018-11-30 15:54:56 +00002049 // If the user has changed the suffix, we need to change the zip file name.
2050 std::string new_path = ds.GetPath(".zip");
2051 if (ds.path_ != new_path) {
2052 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2053 if (rename(ds.path_.c_str(), new_path.c_str())) {
2054 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
2055 strerror(errno));
2056 } else {
2057 ds.path_ = new_path;
2058 }
2059 }
Nandana Dutt4be45d12018-09-26 15:04:23 +01002060 }
2061 }
2062 if (do_text_file) {
2063 ds.path_ = ds.GetPath(".txt");
2064 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
2065 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2066 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
2067 ds.path_.clear();
2068 }
2069 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002070 if (ds.options_->use_control_socket) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002071 if (do_text_file) {
2072 dprintf(ds.control_socket_fd_,
2073 "FAIL:could not create zip file, check %s "
2074 "for more details\n",
2075 ds.log_path_.c_str());
2076 } else {
2077 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
2078 }
2079 }
2080}
2081
2082/* Broadcasts that we are done with the bugreport */
2083static void SendBugreportFinishedBroadcast() {
Nandana Dutt979388e2018-11-30 16:48:55 +00002084 // TODO(b/111441001): use callback instead of broadcast.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002085 if (!ds.path_.empty()) {
2086 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Nandana Dutt4be45d12018-09-26 15:04:23 +01002087 // clang-format off
2088
2089 std::vector<std::string> am_args = {
2090 "--receiver-permission", "android.permission.DUMP",
2091 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
2092 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
2093 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Nandana Dutt9a76d202019-01-21 15:56:48 +00002094 "--es", "android.intent.extra.BUGREPORT", ds.path_,
Nandana Dutt4be45d12018-09-26 15:04:23 +01002095 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
2096 };
2097 // clang-format on
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002098 if (ds.options_->do_fb && !android::os::IsFileEmpty(ds.screenshot_path_)) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002099 am_args.push_back("--es");
2100 am_args.push_back("android.intent.extra.SCREENSHOT");
2101 am_args.push_back(ds.screenshot_path_);
2102 }
Nandana Dutt15b89d72018-11-16 14:14:12 +00002103 if (!ds.options_->notification_title.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002104 am_args.push_back("--es");
2105 am_args.push_back("android.intent.extra.TITLE");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002106 am_args.push_back(ds.options_->notification_title);
2107 if (!ds.options_->notification_description.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002108 am_args.push_back("--es");
2109 am_args.push_back("android.intent.extra.DESCRIPTION");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002110 am_args.push_back(ds.options_->notification_description);
Nandana Dutt4be45d12018-09-26 15:04:23 +01002111 }
2112 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002113 if (ds.options_->is_remote_mode) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002114 am_args.push_back("--es");
2115 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Nandana Dutt9a76d202019-01-21 15:56:48 +00002116 am_args.push_back(SHA256_file_hash(ds.path_));
Nandana Dutt4be45d12018-09-26 15:04:23 +01002117 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
2118 } else {
2119 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
2120 }
2121 } else {
2122 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
2123 }
2124}
2125
Nandana Dutt58d72e22018-11-16 10:30:48 +00002126static inline const char* ModeToString(Dumpstate::BugreportMode mode) {
2127 switch (mode) {
2128 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2129 return "BUGREPORT_FULL";
2130 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
2131 return "BUGREPORT_INTERACTIVE";
2132 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
2133 return "BUGREPORT_REMOTE";
2134 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
2135 return "BUGREPORT_WEAR";
2136 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
2137 return "BUGREPORT_TELEPHONY";
2138 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
2139 return "BUGREPORT_WIFI";
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002140 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2141 return "BUGREPORT_DEFAULT";
Nandana Dutt58d72e22018-11-16 10:30:48 +00002142 }
2143}
2144
2145static void SetOptionsFromMode(Dumpstate::BugreportMode mode, Dumpstate::DumpOptions* options) {
Abhijeet Kaur8ca245e2018-12-12 10:34:21 +00002146 options->extra_options = ModeToString(mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +00002147 switch (mode) {
2148 case Dumpstate::BugreportMode::BUGREPORT_FULL:
2149 options->do_broadcast = true;
2150 options->do_fb = true;
2151 break;
2152 case Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002153 // Currently, the dumpstate binder is only used by Shell to update progress.
2154 options->do_start_service = true;
2155 options->do_progress_updates = true;
2156 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002157 options->do_broadcast = true;
2158 break;
2159 case Dumpstate::BugreportMode::BUGREPORT_REMOTE:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002160 options->do_vibrate = false;
2161 options->is_remote_mode = true;
2162 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002163 options->do_broadcast = true;
2164 break;
2165 case Dumpstate::BugreportMode::BUGREPORT_WEAR:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002166 options->do_start_service = true;
2167 options->do_progress_updates = true;
2168 options->do_zip_file = true;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002169 options->do_fb = true;
2170 options->do_broadcast = true;
2171 break;
2172 case Dumpstate::BugreportMode::BUGREPORT_TELEPHONY:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002173 options->telephony_only = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002174 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002175 options->do_broadcast = true;
2176 break;
2177 case Dumpstate::BugreportMode::BUGREPORT_WIFI:
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002178 options->wifi_only = true;
2179 options->do_zip_file = true;
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +00002180 options->do_fb = false;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002181 options->do_broadcast = true;
2182 break;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002183 case Dumpstate::BugreportMode::BUGREPORT_DEFAULT:
2184 break;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002185 }
2186}
2187
2188static Dumpstate::BugreportMode getBugreportModeFromProperty() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002189 // If the system property is not set, it's assumed to be a default bugreport.
2190 Dumpstate::BugreportMode mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002191
2192 std::string extra_options = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
2193 if (!extra_options.empty()) {
2194 // Framework uses a system property to override some command-line args.
2195 // Currently, it contains the type of the requested bugreport.
2196 if (extra_options == "bugreportplus") {
2197 mode = Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE;
Abhijeet Kaur904e0e02018-12-05 14:03:01 +00002198 } else if (extra_options == "bugreportfull") {
2199 mode = Dumpstate::BugreportMode::BUGREPORT_FULL;
Nandana Dutt58d72e22018-11-16 10:30:48 +00002200 } else if (extra_options == "bugreportremote") {
2201 mode = Dumpstate::BugreportMode::BUGREPORT_REMOTE;
2202 } else if (extra_options == "bugreportwear") {
2203 mode = Dumpstate::BugreportMode::BUGREPORT_WEAR;
2204 } else if (extra_options == "bugreporttelephony") {
2205 mode = Dumpstate::BugreportMode::BUGREPORT_TELEPHONY;
2206 } else if (extra_options == "bugreportwifi") {
2207 mode = Dumpstate::BugreportMode::BUGREPORT_WIFI;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002208 } else {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002209 MYLOGE("Unknown extra option: %s\n", extra_options.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002210 }
2211 // Reset the property
2212 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2213 }
Nandana Dutt58d72e22018-11-16 10:30:48 +00002214 return mode;
2215}
2216
2217// TODO: Move away from system properties when we have options passed via binder calls.
2218/* Sets runtime options from the system properties and then clears those properties. */
2219static void SetOptionsFromProperties(Dumpstate::DumpOptions* options) {
2220 Dumpstate::BugreportMode mode = getBugreportModeFromProperty();
2221 SetOptionsFromMode(mode, options);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002222
2223 options->notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2224 if (!options->notification_title.empty()) {
2225 // Reset the property
2226 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2227
Nandana Duttdd8cca32018-11-14 10:10:29 +00002228 options->notification_description =
2229 android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002230 if (!options->notification_description.empty()) {
2231 // Reset the property
2232 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2233 }
2234 MYLOGD("notification (title: %s, description: %s)\n", options->notification_title.c_str(),
2235 options->notification_description.c_str());
2236 }
2237}
2238
Nandana Dutt58d72e22018-11-16 10:30:48 +00002239static void LogDumpOptions(const Dumpstate::DumpOptions& options) {
2240 MYLOGI("do_zip_file: %d\n", options.do_zip_file);
2241 MYLOGI("do_add_date: %d\n", options.do_add_date);
2242 MYLOGI("do_vibrate: %d\n", options.do_vibrate);
2243 MYLOGI("use_socket: %d\n", options.use_socket);
2244 MYLOGI("use_control_socket: %d\n", options.use_control_socket);
2245 MYLOGI("do_fb: %d\n", options.do_fb);
2246 MYLOGI("do_broadcast: %d\n", options.do_broadcast);
2247 MYLOGI("is_remote_mode: %d\n", options.is_remote_mode);
2248 MYLOGI("show_header_only: %d\n", options.show_header_only);
2249 MYLOGI("do_start_service: %d\n", options.do_start_service);
2250 MYLOGI("telephony_only: %d\n", options.telephony_only);
2251 MYLOGI("wifi_only: %d\n", options.wifi_only);
2252 MYLOGI("do_progress_updates: %d\n", options.do_progress_updates);
Nandana Dutt54dbd672019-01-11 12:58:05 +00002253 MYLOGI("fd: %d\n", options.bugreport_fd.get());
Nandana Dutt58d72e22018-11-16 10:30:48 +00002254 MYLOGI("extra_options: %s\n", options.extra_options.c_str());
2255 MYLOGI("args: %s\n", options.args.c_str());
2256 MYLOGI("notification_title: %s\n", options.notification_title.c_str());
2257 MYLOGI("notification_description: %s\n", options.notification_description.c_str());
2258}
2259
Nandana Dutt54dbd672019-01-11 12:58:05 +00002260void Dumpstate::DumpOptions::Initialize(BugreportMode bugreport_mode,
2261 const android::base::unique_fd& bugreport_fd_in,
2262 const android::base::unique_fd& screenshot_fd_in) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002263 // In the new API world, date is always added; output is always a zip file.
2264 // TODO(111441001): remove these options once they are obsolete.
2265 do_add_date = true;
2266 do_zip_file = true;
2267
Nandana Dutt54dbd672019-01-11 12:58:05 +00002268 // Duplicate the fds because the passed in fds don't outlive the binder transaction.
2269 bugreport_fd.reset(dup(bugreport_fd_in.get()));
2270 screenshot_fd.reset(dup(screenshot_fd_in.get()));
Nandana Dutt58d72e22018-11-16 10:30:48 +00002271
2272 extra_options = ModeToString(bugreport_mode);
2273 SetOptionsFromMode(bugreport_mode, this);
2274}
2275
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002276Dumpstate::RunStatus Dumpstate::DumpOptions::Initialize(int argc, char* argv[]) {
2277 RunStatus status = RunStatus::OK;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002278 int c;
Nandana Dutt235864b2019-01-22 12:10:16 +00002279 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:w")) != -1) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002280 switch (c) {
2281 // clang-format off
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002282 case 'd': do_add_date = true; break;
2283 case 'z': do_zip_file = true; break;
Nandana Dutt9a76d202019-01-21 15:56:48 +00002284 // o=use_outfile not supported anymore.
2285 // TODO(b/111441001): Remove when all callers have migrated.
2286 case 'o': break;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002287 case 's': use_socket = true; break;
2288 case 'S': use_control_socket = true; break;
2289 case 'v': show_header_only = true; break;
2290 case 'q': do_vibrate = false; break;
2291 case 'p': do_fb = true; break;
2292 case 'P': do_progress_updates = true; break;
2293 case 'R': is_remote_mode = true; break;
2294 case 'B': do_broadcast = true; break;
2295 case 'V': break; // compatibility no-op
Nandana Dutt235864b2019-01-22 12:10:16 +00002296 case 'w':
2297 // This was already processed
2298 break;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002299 case 'h':
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002300 status = RunStatus::HELP;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002301 break;
2302 default:
2303 fprintf(stderr, "Invalid option: %c\n", c);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002304 status = RunStatus::INVALID_INPUT;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002305 break;
2306 // clang-format on
2307 }
2308 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08002309
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002310 // TODO: use helper function to convert argv into a string
2311 for (int i = 0; i < argc; i++) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002312 args += argv[i];
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002313 if (i < argc - 1) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002314 args += " ";
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002315 }
2316 }
2317
2318 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
2319 optind = 1;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002320
2321 SetOptionsFromProperties(this);
2322 return status;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002323}
2324
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002325bool Dumpstate::DumpOptions::ValidateOptions() const {
Nandana Dutt54dbd672019-01-11 12:58:05 +00002326 if (bugreport_fd.get() != -1 && !do_zip_file) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002327 return false;
2328 }
2329
Nandana Dutt9a76d202019-01-21 15:56:48 +00002330 if ((do_zip_file || do_add_date || do_progress_updates || do_broadcast) && !OutputToFile()) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002331 return false;
2332 }
2333
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002334 if (use_control_socket && !do_zip_file) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002335 return false;
2336 }
2337
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002338 if (do_progress_updates && !do_broadcast) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002339 return false;
2340 }
2341
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002342 if (is_remote_mode && (do_progress_updates || !do_broadcast || !do_zip_file || !do_add_date)) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002343 return false;
2344 }
2345 return true;
2346}
2347
Nandana Dutt197661d2018-11-16 16:40:21 +00002348void Dumpstate::SetOptions(std::unique_ptr<DumpOptions> options) {
2349 options_ = std::move(options);
2350}
2351
Nandana Duttd2f5f082019-01-18 17:13:52 +00002352Dumpstate::RunStatus Dumpstate::Run(int32_t calling_uid, const std::string& calling_package) {
2353 Dumpstate::RunStatus status = RunInternal(calling_uid, calling_package);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002354 if (listener_ != nullptr) {
2355 switch (status) {
2356 case Dumpstate::RunStatus::OK:
Nandana Duttcc4ead82019-01-23 08:29:23 +00002357 listener_->onFinished();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002358 break;
2359 case Dumpstate::RunStatus::HELP:
2360 break;
2361 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002362 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_INVALID_INPUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002363 break;
2364 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002365 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_RUNTIME_ERROR);
2366 break;
2367 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2368 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_DENIED_CONSENT);
2369 break;
2370 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
2371 listener_->onError(IDumpstateListener::BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT);
Nandana Duttbabf6c72019-01-15 14:11:12 +00002372 break;
2373 }
2374 }
2375 return status;
2376}
2377
Nandana Dutt979388e2018-11-30 16:48:55 +00002378/*
2379 * Dumps relevant information to a bugreport based on the given options.
2380 *
2381 * The bugreport can be dumped to a file or streamed to a socket.
2382 *
2383 * How dumping to file works:
2384 * stdout is redirected to a temporary file. This will later become the main bugreport entry.
2385 * stderr is redirected a log file.
2386 *
2387 * The temporary bugreport is then populated via printfs, dumping contents of files and
2388 * output of commands to stdout.
2389 *
2390 * If zipping, the temporary bugreport file is added to the zip archive. Else it's renamed to final
2391 * text file.
2392 *
2393 * If zipping, a bunch of other files and dumps also get added to the zip archive. The log file also
2394 * gets added to the archive.
2395 *
Nandana Dutt9a76d202019-01-21 15:56:48 +00002396 * Bugreports are first generated in a local directory and later copied to the caller's fd if
2397 * supplied.
Nandana Dutt979388e2018-11-30 16:48:55 +00002398 */
Nandana Duttd2f5f082019-01-18 17:13:52 +00002399Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid,
2400 const std::string& calling_package) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002401 LogDumpOptions(*options_);
Nandana Dutt197661d2018-11-16 16:40:21 +00002402 if (!options_->ValidateOptions()) {
Nandana Dutt58d72e22018-11-16 10:30:48 +00002403 MYLOGE("Invalid options specified\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002404 return RunStatus::INVALID_INPUT;
2405 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002406 /* set as high priority, and protect from OOM killer */
2407 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002408
Felipe Lemed071c682016-10-20 16:48:00 -07002409 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002410 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002411 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002412 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002413 } else {
2414 /* fallback to kernels <= 2.6.35 */
2415 oom_adj = fopen("/proc/self/oom_adj", "we");
2416 if (oom_adj) {
2417 fputs("-17", oom_adj);
2418 fclose(oom_adj);
2419 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002420 }
2421
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002422 if (version_ == VERSION_DEFAULT) {
2423 version_ = VERSION_CURRENT;
Michal Karpinski4db754f2015-12-11 18:04:32 +00002424 }
2425
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002426 if (version_ != VERSION_CURRENT && version_ != VERSION_SPLIT_ANR) {
Vishnu Nair64afc022018-02-01 15:29:34 -08002427 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002428 version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
Vishnu Nair64afc022018-02-01 15:29:34 -08002429 VERSION_SPLIT_ANR.c_str());
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002430 return RunStatus::INVALID_INPUT;
Felipe Lemed071c682016-10-20 16:48:00 -07002431 }
2432
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002433 if (options_->show_header_only) {
2434 PrintHeader();
2435 return RunStatus::OK;
Felipe Lemed071c682016-10-20 16:48:00 -07002436 }
2437
Nandana Duttd2f5f082019-01-18 17:13:52 +00002438 if (options_->bugreport_fd.get() != -1) {
2439 // If the output needs to be copied over to the caller's fd, get user consent.
2440 android::String16 package(calling_package.c_str());
2441 CheckUserConsent(calling_uid, package);
2442 }
2443
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002444 // Redirect output if needed
Nandana Dutt9a76d202019-01-21 15:56:48 +00002445 bool is_redirecting = options_->OutputToFile();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002446
2447 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002448 std::string stats_path =
Nandana Dutt979388e2018-11-30 16:48:55 +00002449 is_redirecting
2450 ? android::base::StringPrintf("%s/dumpstate-stats.txt", bugreport_internal_dir_.c_str())
2451 : "";
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002452 progress_.reset(new Progress(stats_path));
Felipe Leme7447d7c2016-11-03 18:12:22 -07002453
Felipe Lemed071c682016-10-20 16:48:00 -07002454 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002455 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002456 id_ = ++last_id;
Felipe Lemed071c682016-10-20 16:48:00 -07002457 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2458
2459 MYLOGI("begin\n");
2460
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002461 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002462
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002463 // TODO(b/111441001): maybe skip if already started?
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002464 if (options_->do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002465 MYLOGI("Starting 'dumpstate' service\n");
2466 android::status_t ret;
2467 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2468 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2469 }
2470 }
2471
Felipe Lemef0292972016-11-22 13:57:05 -08002472 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002473 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2474 }
2475
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002476 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", id_, options_->args.c_str(),
2477 options_->extra_options.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002478
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002479 MYLOGI("bugreport format version: %s\n", version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002480
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002481 do_early_screenshot_ = options_->do_progress_updates;
Felipe Lemee338bf62015-12-07 14:03:50 -08002482
Christopher Ferrised9354f2014-10-01 17:35:01 -07002483 // If we are going to use a socket, do it as early as possible
2484 // to avoid timeouts from bugreport.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002485 if (options_->use_socket) {
Nandana Dutta344cb62019-02-22 15:12:35 +00002486 if (!redirect_to_socket(stdout, "dumpstate")) {
2487 return ERROR;
2488 }
Christopher Ferrised9354f2014-10-01 17:35:01 -07002489 }
2490
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002491 if (options_->use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002492 MYLOGD("Opening control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002493 control_socket_fd_ = open_socket("dumpstate");
Nandana Dutta344cb62019-02-22 15:12:35 +00002494 if (control_socket_fd_ == -1) {
2495 return ERROR;
2496 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002497 options_->do_progress_updates = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002498 }
2499
Felipe Leme71bbfc52015-11-23 14:14:51 -08002500 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002501 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002502
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002503 if (options_->do_progress_updates) {
2504 if (options_->do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002505 // clang-format off
2506 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002507 "--receiver-permission", "android.permission.DUMP",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002508 "--es", "android.intent.extra.NAME", name_,
2509 "--ei", "android.intent.extra.ID", std::to_string(id_),
2510 "--ei", "android.intent.extra.PID", std::to_string(pid_),
2511 "--ei", "android.intent.extra.MAX", std::to_string(progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002512 };
2513 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002514 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002515 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002516 if (options_->use_control_socket) {
2517 dprintf(control_socket_fd_, "BEGIN:%s\n", path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002518 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002519 }
2520 }
2521
Nick Kralevichf3599b32016-01-25 15:05:16 -08002522 /* read /proc/cmdline before dropping root */
2523 FILE *cmdline = fopen("/proc/cmdline", "re");
2524 if (cmdline) {
2525 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2526 fclose(cmdline);
2527 }
2528
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002529 if (options_->do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002530 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002531 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002532
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002533 if (options_->do_fb && do_early_screenshot_) {
2534 if (screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002535 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002536 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002537 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002538 MYLOGI("taking early screenshot\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002539 TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002540 }
2541 }
2542
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002543 if (options_->do_zip_file && zip_file != nullptr) {
2544 if (chown(path_.c_str(), AID_SHELL, AID_SHELL)) {
2545 MYLOGE("Unable to change ownership of zip file %s: %s\n", path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002546 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002547 }
2548 }
2549
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002550 int dup_stdout_fd;
2551 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002552 if (is_redirecting) {
Nandana Dutt979388e2018-11-30 16:48:55 +00002553 // Redirect stderr to log_path_ for debugging.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002554 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Nandana Dutta344cb62019-02-22 15:12:35 +00002555 if (!redirect_to_file(stderr, const_cast<char*>(log_path_.c_str()))) {
2556 return ERROR;
2557 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002558 if (chown(log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2559 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", log_path_.c_str(),
2560 strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002561 }
Nandana Dutt979388e2018-11-30 16:48:55 +00002562
2563 // Redirect stdout to tmp_path_. This is the main bugreport entry and will be
2564 // moved into zip file later, if zipping.
Vishnu Nair20cf5032018-01-05 13:15:49 -08002565 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Nandana Dutt979388e2018-11-30 16:48:55 +00002566 // TODO: why not write to a file instead of stdout to overcome this problem?
Felipe Leme6e01fa62015-11-11 19:35:14 -08002567 /* TODO: rather than generating a text file now and zipping it later,
2568 it would be more efficient to redirect stdout to the zip entry
2569 directly, but the libziparchive doesn't support that option yet. */
Nandana Dutta344cb62019-02-22 15:12:35 +00002570 if (!redirect_to_file(stdout, const_cast<char*>(tmp_path_.c_str()))) {
2571 return ERROR;
2572 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002573 if (chown(tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002574 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002575 tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002576 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002577 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002578
2579 // Don't buffer stdout
2580 setvbuf(stdout, nullptr, _IONBF, 0);
2581
Felipe Leme608385d2016-02-01 10:35:38 -08002582 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2583 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002584 // duration is logged into MYLOG instead.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002585 PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002586
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002587 if (options_->telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002588 DumpstateTelephonyOnly();
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002589 DumpstateBoard();
2590 } else if (options_->wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002591 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002592 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002593 // Dump state for the default case. This also drops root.
2594 if (!DumpstateDefault()) {
2595 // Something went wrong.
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002596 return RunStatus::ERROR;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002597 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002598 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002599
Felipe Leme55b42a62015-11-10 17:39:08 -08002600 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002601 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002602 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002603 }
2604
Nandana Duttd2f5f082019-01-18 17:13:52 +00002605 // Rename, and/or zip the (now complete) .tmp file within the internal directory.
Nandana Dutt9a76d202019-01-21 15:56:48 +00002606 if (options_->OutputToFile()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002607 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002608 }
2609
Nandana Duttd2f5f082019-01-18 17:13:52 +00002610 // Share the final file with the caller if the user has consented.
2611 Dumpstate::RunStatus status = Dumpstate::RunStatus::OK;
2612 if (options_->bugreport_fd.get() != -1) {
2613 status = CopyBugreportIfUserConsented();
2614 if (status != Dumpstate::RunStatus::OK &&
2615 status != Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2616 // Do an early return if there were errors. We make an exception for consent
2617 // timing out because it's possible the user got distracted. In this case the
2618 // bugreport is not shared but made available for manual retrieval.
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002619 MYLOGI("User denied consent. Returning\n");
Nandana Duttd2f5f082019-01-18 17:13:52 +00002620 return status;
2621 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002622 if (options_->do_fb && options_->screenshot_fd.get() != -1) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002623 bool copy_succeeded = android::os::CopyFileToFd(screenshot_path_,
2624 options_->screenshot_fd.get());
2625 if (copy_succeeded) {
2626 android::os::UnlinkAndLogOnError(screenshot_path_);
2627 }
2628 }
Nandana Dutt16d1aee2019-02-15 16:13:53 +00002629 if (status == Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT) {
2630 MYLOGI(
2631 "Did not receive user consent yet."
2632 " Will not copy the bugreport artifacts to caller.\n");
2633 // TODO(b/111441001):
2634 // 1. cancel outstanding requests
2635 // 2. check for result more frequently
2636 }
Nandana Duttd2f5f082019-01-18 17:13:52 +00002637 }
2638
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002639 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002640 if (options_->do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002641 for (int i = 0; i < 3; i++) {
2642 Vibrate(75);
2643 usleep((75 + 50) * 1000);
2644 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002645 }
2646
Jeff Brown1dc94e32014-09-11 14:15:27 -07002647 /* tell activity manager we're done */
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002648 if (options_->do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002649 SendBugreportFinishedBroadcast();
Nandana Duttbabf6c72019-01-15 14:11:12 +00002650 // Note that listener_ is notified in Run();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002651 }
2652
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002653 MYLOGD("Final progress: %d/%d (estimated %d)\n", progress_->Get(), progress_->GetMax(),
2654 progress_->GetInitialMax());
2655 progress_->Save();
2656 MYLOGI("done (id %d)\n", id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002657
Felipe Leme107a05f2016-03-08 15:11:15 -08002658 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002659 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002660 }
2661
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002662 if (options_->use_control_socket && control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002663 MYLOGD("Closing control socket\n");
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002664 close(control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002665 }
2666
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002667 tombstone_data_.clear();
2668 anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002669
Nandana Duttd2f5f082019-01-18 17:13:52 +00002670 return (consent_callback_ != nullptr &&
2671 consent_callback_->getResult() == UserConsentResult::UNAVAILABLE)
2672 ? USER_CONSENT_TIMED_OUT
2673 : RunStatus::OK;
2674}
2675
2676void Dumpstate::CheckUserConsent(int32_t calling_uid, const android::String16& calling_package) {
2677 consent_callback_ = new ConsentCallback();
2678 const String16 incidentcompanion("incidentcompanion");
2679 sp<android::IBinder> ics(defaultServiceManager()->getService(incidentcompanion));
2680 if (ics != nullptr) {
2681 MYLOGD("Checking user consent via incidentcompanion service\n");
2682 android::interface_cast<android::os::IIncidentCompanion>(ics)->authorizeReport(
2683 calling_uid, calling_package, 0x1 /* FLAG_CONFIRMATION_DIALOG */,
2684 consent_callback_.get());
2685 } else {
2686 MYLOGD("Unable to check user consent; incidentcompanion service unavailable\n");
2687 }
2688}
2689
2690void Dumpstate::CleanupFiles() {
2691 android::os::UnlinkAndLogOnError(tmp_path_);
2692 android::os::UnlinkAndLogOnError(screenshot_path_);
2693 android::os::UnlinkAndLogOnError(path_);
2694}
2695
2696Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
2697 MYLOGD("User denied consent; deleting files and returning\n");
2698 CleanupFiles();
2699 return USER_CONSENT_DENIED;
2700}
2701
2702Dumpstate::RunStatus Dumpstate::CopyBugreportIfUserConsented() {
2703 // If the caller has asked to copy the bugreport over to their directory, we need explicit
2704 // user consent.
2705 UserConsentResult consent_result = consent_callback_->getResult();
2706 if (consent_result == UserConsentResult::UNAVAILABLE) {
2707 // User has not responded yet.
2708 uint64_t elapsed_ms = consent_callback_->getElapsedTimeMs();
2709 if (elapsed_ms < USER_CONSENT_TIMEOUT_MS) {
2710 uint delay_seconds = (USER_CONSENT_TIMEOUT_MS - elapsed_ms) / 1000;
2711 MYLOGD("Did not receive user consent yet; going to wait for %d seconds", delay_seconds);
2712 sleep(delay_seconds);
2713 }
2714 consent_result = consent_callback_->getResult();
2715 }
2716 if (consent_result == UserConsentResult::DENIED) {
2717 // User has explicitly denied sharing with the app. To be safe delete the
2718 // internal bugreport & tmp files.
2719 return HandleUserConsentDenied();
2720 }
2721 if (consent_result == UserConsentResult::APPROVED) {
Nandana Dutte78c3d72019-01-29 16:10:45 +00002722 bool copy_succeeded = android::os::CopyFileToFd(path_, options_->bugreport_fd.get());
2723 if (copy_succeeded) {
2724 android::os::UnlinkAndLogOnError(path_);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002725 }
2726 return copy_succeeded ? Dumpstate::RunStatus::OK : Dumpstate::RunStatus::ERROR;
2727 } else if (consent_result == UserConsentResult::UNAVAILABLE) {
2728 // consent_result is still UNAVAILABLE. The user has likely not responded yet.
2729 // Since we do not have user consent to share the bugreport it does not get
2730 // copied over to the calling app but remains in the internal directory from
2731 // where the user can manually pull it.
2732 return Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT;
2733 }
2734 // Unknown result; must be a programming error.
2735 MYLOGE("Unknown user consent result:%d\n", consent_result);
2736 return Dumpstate::RunStatus::ERROR;
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002737}
2738
Nandana Duttf02564e2019-02-15 15:24:24 +00002739Dumpstate::RunStatus Dumpstate::ParseCommandlineAndRun(int argc, char* argv[]) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002740 std::unique_ptr<Dumpstate::DumpOptions> options = std::make_unique<Dumpstate::DumpOptions>();
2741 Dumpstate::RunStatus status = options->Initialize(argc, argv);
2742 if (status == Dumpstate::RunStatus::OK) {
Nandana Duttf02564e2019-02-15 15:24:24 +00002743 SetOptions(std::move(options));
Nandana Duttd2f5f082019-01-18 17:13:52 +00002744 // When directly running dumpstate binary, the output is not expected to be written
2745 // to any external file descriptor.
Nandana Duttf02564e2019-02-15 15:24:24 +00002746 assert(options_->bugreport_fd.get() == -1);
Nandana Duttd2f5f082019-01-18 17:13:52 +00002747
2748 // calling_uid and calling_package are for user consent to share the bugreport with
2749 // an app; they are irrelvant here because bugreport is only written to a local
2750 // directory, and not shared.
Nandana Duttf02564e2019-02-15 15:24:24 +00002751 status = Run(-1 /* calling_uid */, "" /* calling_package */);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002752 }
Nandana Duttf02564e2019-02-15 15:24:24 +00002753 return status;
2754}
2755
2756/* Main entry point for dumpstate binary. */
2757int run_main(int argc, char* argv[]) {
2758 Dumpstate::RunStatus status = ds.ParseCommandlineAndRun(argc, argv);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002759
2760 switch (status) {
2761 case Dumpstate::RunStatus::OK:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002762 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002763 case Dumpstate::RunStatus::HELP:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002764 ShowUsage();
2765 exit(0);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002766 case Dumpstate::RunStatus::INVALID_INPUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002767 fprintf(stderr, "Invalid combination of args\n");
2768 ShowUsage();
2769 exit(1);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002770 case Dumpstate::RunStatus::ERROR:
Nandana Duttd2f5f082019-01-18 17:13:52 +00002771 FALLTHROUGH_INTENDED;
2772 case Dumpstate::RunStatus::USER_CONSENT_DENIED:
2773 FALLTHROUGH_INTENDED;
2774 case Dumpstate::RunStatus::USER_CONSENT_TIMED_OUT:
Nandana Dutt12ae14a2019-01-09 10:35:53 +00002775 exit(2);
Nandana Dutt5fb117b2018-09-27 09:23:36 +01002776 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002777}