blob: ff15794c05ca3e22252e45d03392640ce337b990 [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080022#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070023#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070024#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080028#include <sys/poll.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070029#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <sys/resource.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/wait.h>
34#include <unistd.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070035
36#include <chrono>
37#include <functional>
38#include <future>
Narayan Kamath8f788292017-05-25 13:20:39 +010039#include <memory>
40#include <regex>
41#include <set>
42#include <string>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070043#include <utility>
Narayan Kamath8f788292017-05-25 13:20:39 +010044#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070045
Felipe Leme96c2bbb2016-09-26 09:21:21 -070046#include <android-base/file.h>
47#include <android-base/properties.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070048#include <android-base/scopeguard.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080049#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070050#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070051#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080052#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080053#include <android/hidl/manager/1.0/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080054#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070055#include <cutils/properties.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080056#include <dumpsys.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080057#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070058#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070059#include <private/android_filesystem_config.h>
60#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080061#include <serviceutils/PriorityDumper.h>
Luis Hector Chavez7aecd382018-03-19 11:16:59 -070062#include <utils/StrongPointer.h>
Felipe Lemef0292972016-11-22 13:57:05 -080063#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080064#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070065#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070066#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080067
Steven Morelandcb7ef822016-11-29 13:20:37 -080068using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080069using ::std::literals::chrono_literals::operator""ms;
70using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080071
Felipe Leme47e9be22016-12-21 15:37:07 -080072// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080073using android::defaultServiceManager;
74using android::Dumpsys;
75using android::INVALID_OPERATION;
76using android::IServiceManager;
77using android::OK;
78using android::sp;
79using android::status_t;
80using android::String16;
81using android::String8;
82using android::TIMED_OUT;
83using android::UNKNOWN_ERROR;
84using android::Vector;
Felipe Leme47e9be22016-12-21 15:37:07 -080085using android::os::dumpstate::CommandOptions;
86using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080087using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080088using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080089using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080090
Colin Crossf45fa6b2012-03-26 12:38:26 -070091/* read before root is shed */
92static char cmdline_buf[16384] = "(unknown)";
Yi Kongc67f9a42018-07-20 13:39:55 -070093static const char *dump_traces_path = nullptr;
Colin Crossf45fa6b2012-03-26 12:38:26 -070094
Felipe Leme1d486fe2016-10-14 18:06:47 -070095// TODO: variables and functions below should be part of dumpstate object
96
Felipe Leme635ca312016-01-05 14:23:02 -080097static std::set<std::string> mount_points;
98void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080099
Todd Poynor2a83daa2013-11-22 15:44:22 -0800100#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700101#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -0700102#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -0800103
Felipe Lemee82a27d2016-01-05 13:35:44 -0800104#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -0700105#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -0700106#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700107#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100108#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
109#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +0900110#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800111#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700112
Narayan Kamath8f788292017-05-25 13:20:39 +0100113// TODO(narayan): Since this information has to be kept in sync
114// with tombstoned, we should just put it in a common header.
115//
116// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100117static const std::string TOMBSTONE_DIR = "/data/tombstones/";
118static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
119static const std::string ANR_DIR = "/data/anr/";
120static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700121
Felipe Lemee844a9d2016-09-21 15:01:39 -0700122// TODO: temporary variables and functions used during C++ refactoring
123static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700124static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
125 const CommandOptions& options = CommandOptions::DEFAULT) {
126 return ds.RunCommand(title, fullCommand, options);
127}
128static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800129 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800130 long dumpsysTimeoutMs = 0) {
131 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700132}
133static int DumpFile(const std::string& title, const std::string& path) {
134 return ds.DumpFile(title, path);
135}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800136
Felipe Lemee844a9d2016-09-21 15:01:39 -0700137// Relative directory (inside the zip) for all files copied as-is into the bugreport.
138static const std::string ZIP_ROOT_DIR = "FS";
139
Steven Moreland7440ddb2016-12-15 16:13:39 -0800140// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700141static const std::string kDumpstateBoardPath = "/bugreports/";
Vishnu Naire97d6122018-01-18 13:58:56 -0800142static const std::string kProtoPath = "proto/";
143static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700144static const std::string kDumpstateBoardFiles[] = {
145 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700146 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700147};
148static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
149
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700150static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700151static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700152static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700153static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
154static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700155
Felipe Lemef0292972016-11-22 13:57:05 -0800156static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
157
Narayan Kamath8f788292017-05-25 13:20:39 +0100158/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100159 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
160 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
161 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700162 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100163 */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700164static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
165 const std::string& file_prefix,
166 bool limit_by_mtime,
167 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100168 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
169
Narayan Kamathbd863722017-06-01 18:50:12 +0100170 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100171
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700172 if (dump_dir == nullptr) {
173 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700174 return std::vector<DumpData>();
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700175 }
176
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700177 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100178 struct dirent* entry = nullptr;
179 while ((entry = readdir(dump_dir.get()))) {
180 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100181 continue;
182 }
183
Narayan Kamathbd863722017-06-01 18:50:12 +0100184 const std::string base_name(entry->d_name);
185 if (base_name.find(file_prefix) != 0) {
186 continue;
187 }
188
189 const std::string abs_path = dir_path + base_name;
190 android::base::unique_fd fd(
191 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
192 if (fd == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700193 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100194 break;
195 }
196
197 struct stat st = {};
198 if (fstat(fd, &st) == -1) {
Luis Hector Chavezd0512712018-03-14 12:15:56 -0700199 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100200 continue;
201 }
202
Narayan Kamath3f31b632018-02-22 19:42:36 +0000203 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100204 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100205 continue;
206 }
207
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700208 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700209 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100210
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700211 // Sort in descending modification time so that we only keep the newest
212 // reports if |limit_by_count| is true.
213 std::sort(dump_data.begin(), dump_data.end(),
214 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100215
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700216 if (limit_by_count && dump_data.size() > 10) {
217 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gamped0d76952017-08-22 13:08:37 -0700218 }
219
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700220 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100221}
222
Narayan Kamathbd863722017-06-01 18:50:12 +0100223static bool AddDumps(const std::vector<DumpData>::const_iterator start,
224 const std::vector<DumpData>::const_iterator end,
225 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100226 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100227 for (auto it = start; it != end; ++it) {
228 const std::string& name = it->name;
229 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100230 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100231
232 // Seek to the beginning of the file before dumping any data. A given
233 // DumpData entry might be dumped multiple times in the report.
234 //
235 // For example, the most recent ANR entry is dumped to the body of the
236 // main entry and it also shows up as a separate entry in the bugreport
237 // ZIP file.
238 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
239 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
240 strerror(errno));
241 }
242
Narayan Kamath8f788292017-05-25 13:20:39 +0100243 if (ds.IsZipping() && add_to_zip) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800244 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100245 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100246 }
247 } else {
248 dump_file_from_fd(type_name, name.c_str(), fd);
249 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100250 }
251
252 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700253}
254
Felipe Leme635ca312016-01-05 14:23:02 -0800255// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700256void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800257 char path[PATH_MAX];
258
259 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
260 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700261 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800262 char linkname[PATH_MAX];
263 ssize_t r = readlink(path, linkname, PATH_MAX);
264 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800265 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800266 return;
267 }
268 linkname[r] = '\0';
269
270 if (mount_points.find(linkname) == mount_points.end()) {
271 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700272 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700273 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800274 mount_points.insert(linkname);
275 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800276 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800277 }
278 }
279}
280
281void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700282 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700283 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800284 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800285 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700286 for_each_pid(do_mountinfo, nullptr);
287 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800288}
289
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700290static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
291{
292 DIR *d;
293 struct dirent *de;
294 char path[PATH_MAX];
295
296 d = opendir(driverpath);
Yi Kongc67f9a42018-07-20 13:39:55 -0700297 if (d == nullptr) {
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700298 return;
299 }
300
301 while ((de = readdir(d))) {
302 if (de->d_type != DT_LNK) {
303 continue;
304 }
305 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700306 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700307 }
308
309 closedir(d);
310}
311
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700312
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700313
314// dump anrd's trace and add to the zip file.
315// 1. check if anrd is running on this device.
316// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
317// 3. wait until the trace generation completes and add to the zip file.
318static bool dump_anrd_trace() {
319 unsigned int pid;
320 char buf[50], path[PATH_MAX];
321 struct dirent *trace;
322 struct stat st;
323 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700324 int retry = 5;
325 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700326 long long cur_size = 0;
327 const char *trace_path = "/data/misc/anrd/";
328
Felipe Leme1d486fe2016-10-14 18:06:47 -0700329 if (!ds.IsZipping()) {
330 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700331 return false;
332 }
333
334 // find anrd's pid if it is running.
Dan Willemsen4a0a8342018-05-04 13:05:01 -0700335 pid = GetPidByName("/system/bin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700336
337 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700338 if (stat(trace_path, &st) == 0) {
339 old_mtime = st.st_mtime;
340 } else {
341 MYLOGE("Failed to find: %s\n", trace_path);
342 return false;
343 }
344
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700345 // send SIGUSR1 to the anrd to generate a trace.
346 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700347 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700348 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700349 MYLOGE("anrd signal timed out. Please manually collect trace\n");
350 return false;
351 }
352
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700353 while (retry-- > 0 && old_mtime == st.st_mtime) {
354 sleep(1);
355 stat(trace_path, &st);
356 }
357
358 if (retry < 0 && old_mtime == st.st_mtime) {
359 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
360 return false;
361 }
362
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700363 // identify the trace file by its creation time.
364 if (!(trace_dir = opendir(trace_path))) {
365 MYLOGE("Can't open trace file under %s\n", trace_path);
366 }
367 while ((trace = readdir(trace_dir))) {
368 if (strcmp(trace->d_name, ".") == 0
369 || strcmp(trace->d_name, "..") == 0) {
370 continue;
371 }
372 sprintf(path, "%s%s", trace_path, trace->d_name);
373 if (stat(path, &st) == 0) {
374 if (st.st_ctime > max_ctime) {
375 max_ctime = st.st_ctime;
376 sprintf(buf, "%s", trace->d_name);
377 }
378 }
379 }
380 closedir(trace_dir);
381
382 // Wait until the dump completes by checking the size of the trace.
383 if (max_ctime > 0) {
384 sprintf(path, "%s%s", trace_path, buf);
385 while(true) {
386 sleep(1);
387 if (stat(path, &st) == 0) {
388 if (st.st_size == cur_size) {
389 break;
390 } else if (st.st_size > cur_size) {
391 cur_size = st.st_size;
392 } else {
393 return false;
394 }
395 } else {
396 MYLOGE("Cant stat() %s anymore\n", path);
397 return false;
398 }
399 }
400 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700401 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700402 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
403 } else {
404 if (remove(path)) {
405 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
406 }
407 return true;
408 }
409 } else {
410 MYLOGE("Can't stats any trace file under %s\n", trace_path);
411 }
412 }
413 return false;
414}
415
Felipe Lemeefd7e272016-05-18 09:27:16 -0700416static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700417 if (!ds.IsZipping()) {
418 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700419 return;
420 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700421 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700422 if (systrace_path.empty()) {
423 MYLOGE("Not dumping systrace because path is empty\n");
424 return;
425 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700426 const char* path = "/sys/kernel/debug/tracing/tracing_on";
427 long int is_tracing;
428 if (read_file_as_long(path, &is_tracing)) {
429 return; // error already logged
430 }
431 if (is_tracing <= 0) {
432 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
433 return;
434 }
435
Felipe Leme14e034a2016-03-30 18:51:03 -0700436 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
437 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700438 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700439 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700440 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700441 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700442 // peacefully; ideally, we should call strace to stop itself, but there is no such option
443 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700444 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700445 // MYLOGE("could not stop systrace ");
446 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700447 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700449 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700450 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700451 if (remove(systrace_path.c_str())) {
452 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
453 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700454 }
455}
456
Mark Salyzyn326842f2015-04-30 09:49:41 -0700457static bool skip_not_stat(const char *path) {
458 static const char stat[] = "/stat";
459 size_t len = strlen(path);
460 if (path[len - 1] == '/') { /* Directory? */
461 return false;
462 }
463 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
464}
465
Felipe Leme4c2d6632016-09-28 14:32:00 -0700466static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800467 return false;
468}
469
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700470unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700471
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800472//
473// stat offsets
474// Name units description
475// ---- ----- -----------
476// read I/Os requests number of read I/Os processed
477#define __STAT_READ_IOS 0
478// read merges requests number of read I/Os merged with in-queue I/O
479#define __STAT_READ_MERGES 1
480// read sectors sectors number of sectors read
481#define __STAT_READ_SECTORS 2
482// read ticks milliseconds total wait time for read requests
483#define __STAT_READ_TICKS 3
484// write I/Os requests number of write I/Os processed
485#define __STAT_WRITE_IOS 4
486// write merges requests number of write I/Os merged with in-queue I/O
487#define __STAT_WRITE_MERGES 5
488// write sectors sectors number of sectors written
489#define __STAT_WRITE_SECTORS 6
490// write ticks milliseconds total wait time for write requests
491#define __STAT_WRITE_TICKS 7
492// in_flight requests number of I/Os currently in flight
493#define __STAT_IN_FLIGHT 8
494// io_ticks milliseconds total time this block device has been active
495#define __STAT_IO_TICKS 9
496// time_in_queue milliseconds total wait time for all requests
497#define __STAT_IN_QUEUE 10
498#define __STAT_NUMBER_FIELD 11
499//
500// read I/Os, write I/Os
501// =====================
502//
503// These values increment when an I/O request completes.
504//
505// read merges, write merges
506// =========================
507//
508// These values increment when an I/O request is merged with an
509// already-queued I/O request.
510//
511// read sectors, write sectors
512// ===========================
513//
514// These values count the number of sectors read from or written to this
515// block device. The "sectors" in question are the standard UNIX 512-byte
516// sectors, not any device- or filesystem-specific block size. The
517// counters are incremented when the I/O completes.
518#define SECTOR_SIZE 512
519//
520// read ticks, write ticks
521// =======================
522//
523// These values count the number of milliseconds that I/O requests have
524// waited on this block device. If there are multiple I/O requests waiting,
525// these values will increase at a rate greater than 1000/second; for
526// example, if 60 read requests wait for an average of 30 ms, the read_ticks
527// field will increase by 60*30 = 1800.
528//
529// in_flight
530// =========
531//
532// This value counts the number of I/O requests that have been issued to
533// the device driver but have not yet completed. It does not include I/O
534// requests that are in the queue but not yet issued to the device driver.
535//
536// io_ticks
537// ========
538//
539// This value counts the number of milliseconds during which the device has
540// had I/O requests queued.
541//
542// time_in_queue
543// =============
544//
545// This value counts the number of milliseconds that I/O requests have waited
546// on this block device. If there are multiple I/O requests waiting, this
547// value will increase as the product of the number of milliseconds times the
548// number of requests waiting (see "read ticks" above for an example).
549#define S_TO_MS 1000
550//
551
Mark Salyzyn326842f2015-04-30 09:49:41 -0700552static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800553 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700554 bool z;
Yi Kongc67f9a42018-07-20 13:39:55 -0700555 char *cp, *buffer = nullptr;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700556 size_t i = 0;
Josh Gao7c4258c2018-06-25 13:40:08 -0700557 FILE *fp = fdopen(dup(fd), "rb");
Mark Salyzyn326842f2015-04-30 09:49:41 -0700558 getline(&buffer, &i, fp);
559 fclose(fp);
560 if (!buffer) {
561 return -errno;
562 }
563 i = strlen(buffer);
564 while ((i > 0) && (buffer[i - 1] == '\n')) {
565 buffer[--i] = '\0';
566 }
567 if (!*buffer) {
568 free(buffer);
569 return 0;
570 }
571 z = true;
572 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800573 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700574 if (fields[i] != 0) {
575 z = false;
576 }
577 }
578 if (z) { /* never accessed */
579 free(buffer);
580 return 0;
581 }
582
Wei Wang509bb5d2017-06-09 14:42:12 -0700583 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
584 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700585 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700586
587 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
588 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
589 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700590 free(buffer);
591
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800592 if (fields[__STAT_IO_TICKS]) {
593 unsigned long read_perf = 0;
594 unsigned long read_ios = 0;
595 if (fields[__STAT_READ_TICKS]) {
596 unsigned long long divisor = fields[__STAT_READ_TICKS]
597 * fields[__STAT_IO_TICKS];
598 read_perf = ((unsigned long long)SECTOR_SIZE
599 * fields[__STAT_READ_SECTORS]
600 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
601 / divisor;
602 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
603 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
604 / divisor;
605 }
606
607 unsigned long write_perf = 0;
608 unsigned long write_ios = 0;
609 if (fields[__STAT_WRITE_TICKS]) {
610 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
611 * fields[__STAT_IO_TICKS];
612 write_perf = ((unsigned long long)SECTOR_SIZE
613 * fields[__STAT_WRITE_SECTORS]
614 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
615 / divisor;
616 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
617 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
618 / divisor;
619 }
620
621 unsigned queue = (fields[__STAT_IN_QUEUE]
622 + (fields[__STAT_IO_TICKS] >> 1))
623 / fields[__STAT_IO_TICKS];
624
625 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700626 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 -0800627 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700628 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 -0800629 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800630 }
631
632 /* bugreport timeout factor adjustment */
633 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
634 worst_write_perf = write_perf;
635 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700636 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700637 return 0;
638}
639
Yao Chenbe3bbc12018-01-17 16:31:10 -0800640static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
641
642/* timeout in ms to read a list of buffers */
643static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
644 unsigned long timeout_ms = 0;
645 for (const auto& buffer : buffers) {
646 log_id_t id = android_name_to_log_id(buffer.c_str());
647 unsigned long property_size = __android_logger_get_buffer_size(id);
648 /* Engineering margin is ten-fold our guess */
649 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
650 }
651 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700652}
653
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700654void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700655 std::string build, fingerprint, radio, bootloader, network;
656 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700657
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700658 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
659 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700660 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
661 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
662 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700663 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700664
Felipe Lemed8b94e52016-12-08 10:21:44 -0800665 printf("========================================================\n");
666 printf("== dumpstate: %s\n", date);
667 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700668
Felipe Lemed8b94e52016-12-08 10:21:44 -0800669 printf("\n");
670 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700671 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800672 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
673 printf("Bootloader: %s\n", bootloader.c_str());
674 printf("Radio: %s\n", radio.c_str());
675 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700676
Felipe Lemed8b94e52016-12-08 10:21:44 -0800677 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800678 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800679 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800680 printf("Uptime: ");
681 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
682 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800683 printf("Bugreport format version: %s\n", version_.c_str());
684 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
685 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
686 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800687}
688
Felipe Leme24b66ee2016-06-16 10:55:26 -0700689// List of file extensions that can cause a zip file attachment to be rejected by some email
690// service providers.
691static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
692 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
693 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
694 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
695};
696
Vishnu Naire97d6122018-01-18 13:58:56 -0800697status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
698 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700699 if (!IsZipping()) {
700 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
701 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800702 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800703 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700704 std::string valid_name = entry_name;
705
706 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700707 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700708 if (idx != std::string::npos) {
709 std::string extension = entry_name.substr(idx);
710 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
711 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
712 valid_name = entry_name + ".renamed";
713 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
714 }
715 }
716
Felipe Leme6fe9db62016-02-12 09:04:16 -0800717 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
718 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700719 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
720 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700721 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700722 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700723 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800724 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800725 }
Vishnu Naire97d6122018-01-18 13:58:56 -0800726 auto start = std::chrono::steady_clock::now();
727 auto end = start + timeout;
728 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800729
Felipe Leme770410d2016-01-26 17:07:14 -0800730 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800731 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800732 if (timeout.count() > 0) {
733 // lambda to recalculate the timeout.
734 auto time_left_ms = [end]() {
735 auto now = std::chrono::steady_clock::now();
736 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
737 return std::max(diff.count(), 0LL);
738 };
739
740 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
741 if (rc < 0) {
742 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
743 strerror(errno));
744 return -errno;
745 } else if (rc == 0) {
746 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
747 entry_name.c_str(), strerror(errno), timeout.count());
748 return TIMED_OUT;
749 }
750 }
751
Zach Riggle22200402016-08-18 01:01:24 -0400752 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800753 if (bytes_read == 0) {
754 break;
755 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800756 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800757 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800758 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700759 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800760 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700761 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800762 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800763 }
764 }
765
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700766 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700767 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700768 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800769 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800770 }
771
Vishnu Naire97d6122018-01-18 13:58:56 -0800772 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800773}
774
Felipe Leme1d486fe2016-10-14 18:06:47 -0700775bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
776 android::base::unique_fd fd(
777 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700778 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800779 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800780 return false;
781 }
782
Vishnu Naire97d6122018-01-18 13:58:56 -0800783 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800784}
785
786/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700787static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800788 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800789}
790
Felipe Leme1d486fe2016-10-14 18:06:47 -0700791void Dumpstate::AddDir(const std::string& dir, bool recursive) {
792 if (!IsZipping()) {
793 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800794 return;
795 }
Felipe Leme678727a2016-09-21 17:22:11 -0700796 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800797 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700798 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800799}
800
Felipe Leme1d486fe2016-10-14 18:06:47 -0700801bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
802 if (!IsZipping()) {
803 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
804 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800805 return false;
806 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800807 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700808 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700809 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700810 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700811 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800812 return false;
813 }
814
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700815 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700816 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700817 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700818 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800819 return false;
820 }
821
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700822 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700823 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700824 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800825 return false;
826 }
827
828 return true;
829}
830
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800831static void DoKmsg() {
832 struct stat st;
833 if (!stat(PSTORE_LAST_KMSG, &st)) {
834 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
835 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
836 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
837 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
838 } else {
839 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
840 DumpFile("LAST KMSG", "/proc/last_kmsg");
841 }
842}
843
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800844static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800845 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800846 RunCommand(
847 "KERNEL LOG",
848 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
849 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
850}
851
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800852static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800853 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800854 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
855 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800856 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100857 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800858 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
859 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800860 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800861 RunCommand(
862 "EVENT LOG",
863 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
864 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800865 timeout_ms = logcat_timeout({"stats"});
866 RunCommand(
867 "STATS LOG",
868 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
869 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
870 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800871 RunCommand(
872 "RADIO LOG",
873 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
874 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800875
876 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
877
878 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800879 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
880 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800881}
882
Jayachandran Ca94c7172017-06-10 15:08:12 -0700883static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700884 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
885 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900886 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700887 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900888 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
889 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
890 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
891 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700892}
893
Narayan Kamath8f788292017-05-25 13:20:39 +0100894static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
895 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
896 anr_traces_dir.c_str());
897
898 // If we're here, dump_traces_path will always be a temporary file
899 // (created with mkostemp or similar) that contains dumps taken earlier
900 // on in the process.
901 if (dump_traces_path != nullptr) {
902 if (add_to_zip) {
903 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
904 } else {
905 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
906 dump_traces_path);
907 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
908 }
909
910 const int ret = unlink(dump_traces_path);
911 if (ret == -1) {
912 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
913 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700914 }
915 }
916
Narayan Kamathbd863722017-06-01 18:50:12 +0100917 // Add a specific message for the first ANR Dump.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700918 if (ds.anr_data_.size() > 0) {
919 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +0100920 "VM TRACES AT LAST ANR", add_to_zip);
921
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100922 // The "last" ANR will always be included as separate entry in the zip file. In addition,
923 // it will be present in the body of the main entry if |add_to_zip| == false.
924 //
925 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -0700926 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100927 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100928 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100929 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
930 }
931}
932
933static void AddAnrTraceFiles() {
934 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
935
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700936 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +0100937
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700938 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100939
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700940 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -0700941 struct stat st;
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700942 int i = 0;
943 while (true) {
944 const std::string slow_trace_path =
945 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
946 if (stat(slow_trace_path.c_str(), &st)) {
947 // No traces file at this index, done with the files.
948 break;
Felipe Lemee184f662016-10-27 10:04:47 -0700949 }
Elliott Hughes69fe5ec2018-03-23 11:04:25 -0700950 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
951 i++;
Felipe Lemee184f662016-10-27 10:04:47 -0700952 }
953}
954
Wei Wang509bb5d2017-06-09 14:42:12 -0700955static void DumpBlockStatFiles() {
956 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700957
Wei Wang1dc1ef52017-06-12 11:28:37 -0700958 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
959
960 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700961 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
962 return;
963 }
964
965 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -0700966 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700967 if ((d->d_name[0] == '.')
968 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
969 || (d->d_name[1] == '\0'))) {
970 continue;
971 }
972 const std::string new_path =
973 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
974 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
975 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
976 printf("\n");
977 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700978 return;
Wei Wang509bb5d2017-06-09 14:42:12 -0700979}
Jayachandran Ca94c7172017-06-10 15:08:12 -0700980
981static void DumpPacketStats() {
982 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
983 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
984 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
985 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
986 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
987}
988
989static void DumpIpAddrAndRules() {
990 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
991 RunCommand("NETWORK INTERFACES", {"ip", "link"});
992 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
993 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
994 RunCommand("IP RULES", {"ip", "rule", "show"});
995 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
996}
997
Vishnu Nair64afc022018-02-01 15:29:34 -0800998static void RunDumpsysTextByPriority(const std::string& title, int priority,
999 std::chrono::milliseconds timeout,
1000 std::chrono::milliseconds service_timeout) {
1001 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001002 sp<android::IServiceManager> sm = defaultServiceManager();
1003 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001004 Vector<String16> args;
1005 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001006 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1007 for (const String16& service : services) {
1008 std::string path(title);
1009 path.append(" - ").append(String8(service).c_str());
1010 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1011 size_t bytes_written = 0;
1012 status_t status = dumpsys.startDumpThread(service, args);
1013 if (status == OK) {
1014 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1015 std::chrono::duration<double> elapsed_seconds;
1016 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1017 /* as_proto = */ false, elapsed_seconds, bytes_written);
1018 section_reporter.setSize(bytes_written);
1019 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1020 bool dump_complete = (status == OK);
1021 dumpsys.stopDumpThread(dump_complete);
1022 }
1023 section_reporter.setStatus(status);
1024
1025 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1026 std::chrono::steady_clock::now() - start);
1027 if (elapsed_duration > timeout) {
1028 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1029 elapsed_duration.count());
1030 break;
1031 }
1032 }
1033}
1034
Vishnu Nair64afc022018-02-01 15:29:34 -08001035static void RunDumpsysText(const std::string& title, int priority,
1036 std::chrono::milliseconds timeout,
1037 std::chrono::milliseconds service_timeout) {
1038 DurationReporter duration_reporter(title);
1039 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1040 fsync(STDOUT_FILENO);
1041 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1042}
1043
1044/* Dump all services registered with Normal or Default priority. */
1045static void RunDumpsysTextNormalPriority(const std::string& title,
1046 std::chrono::milliseconds timeout,
1047 std::chrono::milliseconds service_timeout) {
1048 DurationReporter duration_reporter(title);
1049 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1050 fsync(STDOUT_FILENO);
1051 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1052 service_timeout);
1053 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1054 service_timeout);
1055}
1056
1057static void RunDumpsysProto(const std::string& title, int priority,
1058 std::chrono::milliseconds timeout,
1059 std::chrono::milliseconds service_timeout) {
Luis Hector Chavez1e27b082018-03-22 15:36:42 -07001060 if (!ds.IsZipping()) {
1061 MYLOGD("Not dumping %s because it's not a zipped bugreport\n", title.c_str());
1062 return;
1063 }
Vishnu Naire97d6122018-01-18 13:58:56 -08001064 sp<android::IServiceManager> sm = defaultServiceManager();
1065 Dumpsys dumpsys(sm.get());
1066 Vector<String16> args;
1067 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1068 DurationReporter duration_reporter(title);
1069
1070 auto start = std::chrono::steady_clock::now();
1071 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1072 for (const String16& service : services) {
1073 std::string path(kProtoPath);
1074 path.append(String8(service).c_str());
1075 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1076 path.append("_CRITICAL");
1077 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1078 path.append("_HIGH");
1079 }
1080 path.append(kProtoExt);
1081 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1082 status_t status = dumpsys.startDumpThread(service, args);
1083 if (status == OK) {
1084 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1085 bool dumpTerminated = (status == OK);
1086 dumpsys.stopDumpThread(dumpTerminated);
1087 }
1088 ZipWriter::FileEntry file_entry;
1089 ds.zip_writer_->GetLastEntry(&file_entry);
1090 section_reporter.setSize(file_entry.compressed_size);
1091 section_reporter.setStatus(status);
1092
1093 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1094 std::chrono::steady_clock::now() - start);
1095 if (elapsed_duration > timeout) {
1096 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1097 elapsed_duration.count());
1098 break;
1099 }
1100 }
1101}
1102
Vishnu Nair780b1282017-10-10 13:57:24 -07001103// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1104static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001105 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1106 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1107 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1108 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001109}
1110
1111// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1112static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001113 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1114 // high priority. Reduce timeout once they are able to dump in a shorter time or
1115 // moved to a parallel task.
1116 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1117 /* timeout= */ 90s, /* service_timeout= */ 30s);
1118 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1119 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001120}
1121
1122// Runs dumpsys on services that must dump but can take up to 10s to dump.
1123static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001124 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1125 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1126 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001127}
1128
Steven Moreland44cd9482018-01-04 16:24:13 -08001129static void DumpHals() {
Steven Moreland44cd9482018-01-04 16:24:13 -08001130 using android::hidl::manager::V1_0::IServiceManager;
1131 using android::hardware::defaultServiceManager;
1132
1133 sp<IServiceManager> sm = defaultServiceManager();
1134 if (sm == nullptr) {
1135 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1136 return;
1137 }
1138
1139 auto ret = sm->list([&](const auto& interfaces) {
1140 for (const std::string& interface : interfaces) {
1141 std::string cleanName = interface;
1142 std::replace_if(cleanName.begin(),
1143 cleanName.end(),
1144 [](char c) {
1145 return !isalnum(c) &&
1146 std::string("@-_:.").find(c) == std::string::npos;
1147 }, '_');
1148 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1149
1150 {
1151 auto fd = android::base::unique_fd(
1152 TEMP_FAILURE_RETRY(open(path.c_str(),
1153 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1154 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1155 if (fd < 0) {
1156 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1157 continue;
1158 }
1159 RunCommandToFd(fd,
1160 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001161 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001162 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1163
1164 bool empty = 0 == lseek(fd, 0, SEEK_END);
1165 if (!empty) {
1166 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1167 }
1168 }
1169
1170 unlink(path.c_str());
1171 }
1172 });
1173
1174 if (!ret.isOk()) {
1175 MYLOGE("Could not list hals from hwservicemanager.\n");
1176 }
1177}
1178
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001179static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001180 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001181
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001182 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001183 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001184 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001185 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001186 DumpFile("MEMORY INFO", "/proc/meminfo");
1187 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001188 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001189 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001190 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1191 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1192 DumpFile("SLAB INFO", "/proc/slabinfo");
1193 DumpFile("ZONEINFO", "/proc/zoneinfo");
1194 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1195 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1196 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001197
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001198 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1199 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1200 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001201
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001202 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001203 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001204 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001205
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001206 if (ds.IsZipping()) {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001207 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z"},
1208 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
Steven Moreland44cd9482018-01-04 16:24:13 -08001209 DumpHals();
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001210 } else {
Yifan Hong90e8d8d2018-06-28 13:14:39 -07001211 RunCommand("HARDWARE HALS", {"lshal", "-lVSietrpc", "--types=b,c,l,z", "--debug"},
1212 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001213 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001214
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001215 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001216 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001217 struct stat s;
1218 if (stat("/proc/modules", &s) != 0) {
1219 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1220 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001221 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001222 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001223
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001224 if (__android_logger_property_get_bool(
1225 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1226 DoKernelLogcat();
1227 } else {
1228 do_dmesg();
1229 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230
Felipe Lemef0292972016-11-22 13:57:05 -08001231 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001232 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1233 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001234 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001235
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001236 /* Dump Bluetooth HCI logs */
1237 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001238
Felipe Leme9a523ae2016-10-20 15:10:33 -07001239 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001240 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001241 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001242 }
1243
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001244 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001245
Felipe Lemee184f662016-10-27 10:04:47 -07001246 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001247
Narayan Kamath8f788292017-05-25 13:20:39 +01001248 // NOTE: tombstones are always added as separate entries in the zip archive
1249 // and are not interspersed with the main report.
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07001250 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001251 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001252 if (!tombstones_dumped) {
1253 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001254 }
1255
Jayachandran Ca94c7172017-06-10 15:08:12 -07001256 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001257
Chenbo Feng276a3b62018-08-07 11:44:49 -07001258 RunDumpsys("EBPF MAP STATS", {"netd", "trafficcontroller"});
1259
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001260 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001261
Jayachandran Ca94c7172017-06-10 15:08:12 -07001262 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001263
1264 dump_route_tables();
1265
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001266 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1267 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1268 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001269
Vishnu Nair780b1282017-10-10 13:57:24 -07001270 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001271
Elliott Hughes23ccc622017-02-28 10:14:22 -08001272 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001273
Jin Qianf334d662017-10-10 14:41:37 -07001274 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001275
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001276 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001277
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001278 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001279
Colin Crossf45fa6b2012-03-26 12:38:26 -07001280 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001281 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1282 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1283 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1284 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1285 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001286
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001287 /* Add window and surface trace files. */
1288 if (!PropertiesHelper::IsUserBuild()) {
1289 ds.AddDir(WMTRACE_DATA_DIR, false);
1290 }
1291
Felipe Leme6f674ae2016-11-18 17:10:33 -08001292 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293
Steven Moreland7440ddb2016-12-15 16:13:39 -08001294 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001295 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1296 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001297 // su does not exist on user builds, so try running without it.
1298 // This way any implementations of vril-dump that do not require
1299 // root can run on user builds.
1300 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001301 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001302 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001303 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001304 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001305 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306 }
1307
Felipe Lemed8b94e52016-12-08 10:21:44 -08001308 printf("========================================================\n");
1309 printf("== Android Framework Services\n");
1310 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001311
Vishnu Nair780b1282017-10-10 13:57:24 -07001312 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001313
Felipe Lemed8b94e52016-12-08 10:21:44 -08001314 printf("========================================================\n");
1315 printf("== Checkins\n");
1316 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001317
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001318 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1319 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1320 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1321 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1322 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1323 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001324
Felipe Lemed8b94e52016-12-08 10:21:44 -08001325 printf("========================================================\n");
1326 printf("== Running Application Activities\n");
1327 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001328
Makoto Onuki60780982018-04-16 15:34:00 -07001329 // The following dumpsys internally collects output from running apps, so it can take a long
1330 // time. So let's extend the timeout.
1331
1332 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
1333
1334 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}, DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001335
Felipe Lemed8b94e52016-12-08 10:21:44 -08001336 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001337 printf("== Running Application Services (platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001338 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001339
Vishnu Naire3694e32018-07-02 14:20:06 -07001340 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform-non-critical"},
Makoto Onuki60780982018-04-16 15:34:00 -07001341 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001342
Felipe Lemed8b94e52016-12-08 10:21:44 -08001343 printf("========================================================\n");
Makoto Onuki60780982018-04-16 15:34:00 -07001344 printf("== Running Application Services (non-platform)\n");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001345 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001346
Makoto Onuki60780982018-04-16 15:34:00 -07001347 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1348 DUMPSYS_COMPONENTS_OPTIONS);
1349
1350 printf("========================================================\n");
1351 printf("== Running Application Providers (platform)\n");
1352 printf("========================================================\n");
1353
1354 RunDumpsys("APP PROVIDERS PLATFORM", {"activity", "provider", "all-platform"},
1355 DUMPSYS_COMPONENTS_OPTIONS);
1356
1357 printf("========================================================\n");
1358 printf("== Running Application Providers (non-platform)\n");
1359 printf("========================================================\n");
1360
1361 RunDumpsys("APP PROVIDERS NON-PLATFORM", {"activity", "provider", "all-non-platform"},
1362 DUMPSYS_COMPONENTS_OPTIONS);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001363
Adrian Roos8b397ab2017-04-04 16:35:44 -07001364 printf("========================================================\n");
1365 printf("== Dropbox crashes\n");
1366 printf("========================================================\n");
1367
1368 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1369 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1370
Felipe Lemed8b94e52016-12-08 10:21:44 -08001371 printf("========================================================\n");
1372 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1373 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1374 printf("========================================================\n");
1375 printf("== dumpstate: done (id %d)\n", ds.id_);
1376 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001377}
1378
mukesh agrawal253dad42018-01-23 21:59:59 -08001379// This method collects common dumpsys for telephony and wifi
1380static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001381 DumpIpTablesAsRoot();
1382
1383 if (!DropRootUser()) {
1384 return;
1385 }
1386
1387 do_dmesg();
1388 DoLogcat();
1389 DumpPacketStats();
1390 DoKmsg();
1391 DumpIpAddrAndRules();
1392 dump_route_tables();
1393
1394 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1395 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001396}
1397
1398// This method collects dumpsys for telephony debugging only
1399static void DumpstateTelephonyOnly() {
1400 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001401 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001402
1403 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001404
1405 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1406
1407 printf("========================================================\n");
1408 printf("== Android Framework Services\n");
1409 printf("========================================================\n");
1410
Vishnu Nair652cc802017-11-30 15:18:30 -08001411 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1412 SEC_TO_MSEC(10));
1413 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1414 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001415 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1416 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001417 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1418 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001419
1420 printf("========================================================\n");
1421 printf("== Running Application Services\n");
1422 printf("========================================================\n");
1423
1424 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1425
1426 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001427 printf("== Running Application Services (non-platform)\n");
1428 printf("========================================================\n");
1429
1430 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1431 DUMPSYS_COMPONENTS_OPTIONS);
1432
1433 printf("========================================================\n");
Kelly Rossmoyerbbd6fdb2018-08-21 18:06:38 -07001434 printf("== Checkins\n");
1435 printf("========================================================\n");
1436
1437 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1438
1439 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001440 printf("== dumpstate: done (id %d)\n", ds.id_);
1441 printf("========================================================\n");
1442}
1443
mukesh agrawal253dad42018-01-23 21:59:59 -08001444// This method collects dumpsys for wifi debugging only
1445static void DumpstateWifiOnly() {
1446 DurationReporter duration_reporter("DUMPSTATE");
1447
1448 DumpstateRadioCommon();
1449
1450 printf("========================================================\n");
1451 printf("== Android Framework Services\n");
1452 printf("========================================================\n");
1453
1454 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1455 SEC_TO_MSEC(10));
1456 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1457 SEC_TO_MSEC(10));
1458
1459 printf("========================================================\n");
1460 printf("== dumpstate: done (id %d)\n", ds.id_);
1461 printf("========================================================\n");
1462}
1463
Felipe Leme6f674ae2016-11-18 17:10:33 -08001464void Dumpstate::DumpstateBoard() {
1465 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001466 printf("========================================================\n");
1467 printf("== Board\n");
1468 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001469
Felipe Leme6f674ae2016-11-18 17:10:33 -08001470 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001471 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001472 return;
1473 }
1474
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001475 std::vector<std::string> paths;
1476 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001477 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001478 paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
1479 remover.emplace_back(android::base::make_scope_guard(std::bind(
1480 [](std::string path) {
1481 if (remove(path.c_str()) != 0 && errno != ENOENT) {
1482 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1483 }
1484 },
1485 paths[i])));
1486 }
Jie Song9fbfad02017-06-20 16:29:42 -07001487
Wei Wang587eac92018-04-05 12:17:20 -07001488 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1489 if (dumpstate_device == nullptr) {
1490 MYLOGE("No IDumpstateDevice implementation\n");
1491 return;
1492 }
1493
1494 using ScopedNativeHandle =
1495 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1496 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1497 [](native_handle_t* handle) {
1498 native_handle_close(handle);
1499 native_handle_delete(handle);
1500 });
1501 if (handle == nullptr) {
1502 MYLOGE("Could not create native_handle\n");
1503 return;
1504 }
1505
1506 for (size_t i = 0; i < paths.size(); i++) {
1507 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1508
1509 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1510 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1511 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1512 if (fd < 0) {
1513 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1514 return;
1515 }
1516 handle.get()->data[i] = fd.release();
1517 }
1518
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001519 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001520 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1521 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1522 // and grab whatever dumped
1523 std::packaged_task<bool()>
1524 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001525 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1526 if (!status.isOk()) {
1527 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001528 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001529 }
Wei Wang587eac92018-04-05 12:17:20 -07001530 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001531 });
Wei Wang587eac92018-04-05 12:17:20 -07001532
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001533 auto result = dumpstate_task.get_future();
1534 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001535
1536 constexpr size_t timeout_sec = 30;
1537 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1538 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1539 if (!android::base::SetProperty("ctl.interface_restart",
1540 android::base::StringPrintf("%s/default",
1541 IDumpstateDevice::descriptor))) {
1542 MYLOGE("Couldn't restart dumpstate HAL\n");
1543 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001544 }
Wei Wang587eac92018-04-05 12:17:20 -07001545 // Wait some time for init to kill dumpstate vendor HAL
1546 constexpr size_t killing_timeout_sec = 10;
1547 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1548 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1549 "there might be racing in content\n", killing_timeout_sec);
1550 }
1551
1552 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1553 for (size_t i = 0; i < paths.size(); i++) {
1554 struct stat s;
1555 if (fstat(handle.get()->data[i], &s) == -1) {
1556 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1557 strerror(errno));
1558 file_sizes[i] = -1;
1559 continue;
1560 }
1561 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001562 }
1563
1564 for (size_t i = 0; i < paths.size(); i++) {
1565 if (file_sizes[i] == -1) {
1566 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001567 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001568 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001569 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001570 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001571 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001572 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001573 }
1574
Felipe Lemed8b94e52016-12-08 10:21:44 -08001575 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001576}
1577
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001578static void ShowUsageAndExit(int exitCode = 1) {
1579 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001580 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001581 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1582 " -h: display this help message\n"
1583 " -b: play sound file instead of vibrate, at beginning of job\n"
1584 " -e: play sound file instead of vibrate, at end of job\n"
1585 " -o: write to file (instead of stdout)\n"
1586 " -d: append date to filename (requires -o)\n"
1587 " -p: capture screenshot to filename.png (requires -o)\n"
1588 " -z: generate zipped file (requires -o)\n"
1589 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001590 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001591 " -q: disable vibrate\n"
1592 " -B: send broadcast when finished (requires -o)\n"
1593 " -P: send broadcast when started and update system properties on "
1594 "progress (requires -o and -B)\n"
1595 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1596 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001597 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001598 exit(exitCode);
1599}
1600
1601static void ExitOnInvalidArgs() {
1602 fprintf(stderr, "invalid combination of args\n");
1603 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001604}
1605
Wei Liuf87959e2016-08-26 14:51:42 -07001606static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001607 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001608}
1609
Felipe Leme1d486fe2016-10-14 18:06:47 -07001610bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001611 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001612 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001613 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001614 // Final timestamp
1615 char date[80];
1616 time_t the_real_now_please_stand_up = time(nullptr);
1617 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001618 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001619 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001620
Felipe Leme9a523ae2016-10-20 15:10:33 -07001621 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001622 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001623 return false;
1624 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001625 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001626 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001627 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001628 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001629
Felipe Leme0f3fb202016-06-10 17:10:53 -07001630 // Add log file (which contains stderr output) to zip...
1631 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001632 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001633 MYLOGE("Failed to add dumpstate log to .zip file\n");
1634 return false;
1635 }
1636 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001637 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001638 fprintf(stderr, "\n");
1639
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001640 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001641 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001642 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001643 return false;
1644 }
1645
Felipe Leme1d486fe2016-10-14 18:06:47 -07001646 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1647 ds.zip_file.reset(nullptr);
1648
Felipe Lemee9d2c542016-11-15 11:48:26 -08001649 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1650 if (remove(tmp_path_.c_str()) != 0) {
1651 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001652 }
1653
Felipe Leme1e9edc62015-12-21 16:02:13 -08001654 return true;
1655}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001656
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001657static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001658 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1659 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001660 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001661 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kongc67f9a42018-07-20 13:39:55 -07001662 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001663 }
1664
1665 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001666 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001667
1668 std::vector<uint8_t> buffer(65536);
1669 while (1) {
1670 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1671 if (bytes_read == 0) {
1672 break;
1673 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001674 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kongc67f9a42018-07-20 13:39:55 -07001675 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001676 }
1677
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001678 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001679 }
1680
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001681 uint8_t hash[SHA256_DIGEST_LENGTH];
1682 SHA256_Final(hash, &ctx);
1683
1684 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1685 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001686 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001687 }
1688 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1689 return std::string(hash_buffer);
1690}
1691
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001692static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1693 // clang-format off
1694 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1695 "--receiver-foreground", "--receiver-include-background", "-a", action};
1696 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001697
1698 am.insert(am.end(), args.begin(), args.end());
1699
Felipe Leme8d2410e2017-02-08 09:46:08 -08001700 RunCommand("", am,
1701 CommandOptions::WithTimeout(20)
1702 .Log("Sending broadcast: '%s'\n")
1703 .Always()
1704 .DropRoot()
1705 .RedirectStderr()
1706 .Build());
1707}
1708
Felipe Leme35b8cf12017-02-10 15:47:29 -08001709static void Vibrate(int duration_ms) {
1710 // clang-format off
1711 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1712 CommandOptions::WithTimeout(10)
1713 .Log("Vibrate: '%s'\n")
1714 .Always()
1715 .Build());
1716 // clang-format on
1717}
1718
Vishnu Nair20cf5032018-01-05 13:15:49 -08001719/** Main entry point for dumpstate. */
1720int run_main(int argc, char* argv[]) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001721 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001722 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001723 int do_vibrate = 1;
Yi Kongc67f9a42018-07-20 13:39:55 -07001724 char* use_outfile = nullptr;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001725 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001726 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001727 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001728 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001729 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001730 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001731 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001732 bool telephony_only = false;
mukesh agrawal253dad42018-01-23 21:59:59 -08001733 bool wifi_only = false;
Vishnu Nair20cf5032018-01-05 13:15:49 -08001734 int dup_stdout_fd;
1735 int dup_stderr_fd;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001736
Colin Crossf45fa6b2012-03-26 12:38:26 -07001737 /* set as high priority, and protect from OOM killer */
1738 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001739
Felipe Lemed071c682016-10-20 16:48:00 -07001740 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001741 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001742 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001743 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001744 } else {
1745 /* fallback to kernels <= 2.6.35 */
1746 oom_adj = fopen("/proc/self/oom_adj", "we");
1747 if (oom_adj) {
1748 fputs("-17", oom_adj);
1749 fclose(oom_adj);
1750 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001751 }
1752
Jeff Brown1dc94e32014-09-11 14:15:27 -07001753 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001754 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001755 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001756 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001757 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001758 case 'd': do_add_date = 1; break;
1759 case 'z': do_zip_file = 1; break;
1760 case 'o': use_outfile = optarg; break;
1761 case 's': use_socket = 1; break;
1762 case 'S': use_control_socket = 1; break;
1763 case 'v': show_header_only = true; break;
1764 case 'q': do_vibrate = 0; break;
1765 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001766 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001767 case 'R': is_remote_mode = 1; break;
1768 case 'B': do_broadcast = 1; break;
1769 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001770 case 'h':
1771 ShowUsageAndExit(0);
1772 break;
1773 default:
1774 fprintf(stderr, "Invalid option: %c\n", c);
1775 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001776 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777 }
1778 }
1779
Felipe Lemed071c682016-10-20 16:48:00 -07001780 // TODO: use helper function to convert argv into a string
1781 for (int i = 0; i < argc; i++) {
1782 ds.args_ += argv[i];
1783 if (i < argc - 1) {
1784 ds.args_ += " ";
1785 }
1786 }
1787
1788 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001789 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001790 // Framework uses a system property to override some command-line args.
1791 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001792 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001793 // Currently, the dumpstate binder is only used by Shell to update progress.
1794 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001795 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001796 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001797 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001798 do_vibrate = 0;
1799 is_remote_mode = 1;
1800 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001801 } else if (ds.extra_options_ == "bugreportwear") {
lingfan44612512018-02-27 11:32:11 -08001802 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001803 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001804 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001805 } else if (ds.extra_options_ == "bugreporttelephony") {
1806 telephony_only = true;
mukesh agrawal253dad42018-01-23 21:59:59 -08001807 } else if (ds.extra_options_ == "bugreportwifi") {
1808 wifi_only = true;
1809 do_zip_file = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001810 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001811 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001812 }
1813 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001814 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001815 }
1816
Naveen Kallab53a1c92017-03-16 18:17:25 -07001817 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1818 if (!ds.notification_title.empty()) {
1819 // Reset the property
1820 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1821
1822 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1823 if (!ds.notification_description.empty()) {
1824 // Reset the property
1825 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1826 }
1827 MYLOGD("notification (title: %s, description: %s)\n",
1828 ds.notification_title.c_str(), ds.notification_description.c_str());
1829 }
1830
Felipe Leme9a523ae2016-10-20 15:10:33 -07001831 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001832 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001833 }
1834
Felipe Leme2628e9e2016-04-12 16:36:51 -07001835 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001836 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001837 }
1838
Felipe Leme9a523ae2016-10-20 15:10:33 -07001839 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001840 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001841 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001842
Felipe Leme9a523ae2016-10-20 15:10:33 -07001843 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001844 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001845 }
1846
Felipe Lemed071c682016-10-20 16:48:00 -07001847 if (ds.version_ == VERSION_DEFAULT) {
1848 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001849 }
1850
Vishnu Nair64afc022018-02-01 15:29:34 -08001851 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1852 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1853 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1854 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001855 exit(1);
1856 }
1857
1858 if (show_header_only) {
1859 ds.PrintHeader();
1860 exit(0);
1861 }
1862
Felipe Leme7447d7c2016-11-03 18:12:22 -07001863 /* redirect output if needed */
1864 bool is_redirecting = !use_socket && use_outfile;
1865
1866 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1867 std::string stats_path =
1868 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1869 : "";
1870 ds.progress_.reset(new Progress(stats_path));
1871
Felipe Lemed071c682016-10-20 16:48:00 -07001872 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001873 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001874 ds.id_ = ++last_id;
1875 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1876
1877 MYLOGI("begin\n");
1878
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001879 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001880
Felipe Leme75876a22016-10-27 16:31:27 -07001881 if (do_start_service) {
1882 MYLOGI("Starting 'dumpstate' service\n");
1883 android::status_t ret;
1884 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1885 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1886 }
1887 }
1888
Felipe Lemef0292972016-11-22 13:57:05 -08001889 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001890 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1891 }
1892
Felipe Leme7447d7c2016-11-03 18:12:22 -07001893 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001894 ds.extra_options_.c_str());
1895
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001896 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001897
Felipe Leme9a523ae2016-10-20 15:10:33 -07001898 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001899
Christopher Ferrised9354f2014-10-01 17:35:01 -07001900 // If we are going to use a socket, do it as early as possible
1901 // to avoid timeouts from bugreport.
1902 if (use_socket) {
1903 redirect_to_socket(stdout, "dumpstate");
1904 }
1905
Felipe Leme2628e9e2016-04-12 16:36:51 -07001906 if (use_control_socket) {
1907 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001908 ds.control_socket_fd_ = open_socket("dumpstate");
1909 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001910 }
1911
Felipe Leme71bbfc52015-11-23 14:14:51 -08001912 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001913 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001914 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001915 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001916 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1917 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001918 if (do_add_date) {
1919 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001920 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001921 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001922 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001923 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001924 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001925
1926 if (telephony_only) {
1927 ds.base_name_ += "-telephony";
mukesh agrawal253dad42018-01-23 21:59:59 -08001928 } else if (wifi_only) {
1929 ds.base_name_ += "-wifi";
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001930 }
1931
Felipe Leme71bbfc52015-11-23 14:14:51 -08001932 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001933 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001934 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001935 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001936 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001937
Felipe Lemee844a9d2016-09-21 15:01:39 -07001938 MYLOGD(
1939 "Bugreport dir: %s\n"
1940 "Base name: %s\n"
1941 "Suffix: %s\n"
1942 "Log path: %s\n"
1943 "Temporary path: %s\n"
1944 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001945 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1946 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001947
Felipe Leme1e9edc62015-12-21 16:02:13 -08001948 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001949 ds.path_ = ds.GetPath(".zip");
1950 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1951 create_parent_dirs(ds.path_.c_str());
1952 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001953 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001954 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001955 do_zip_file = 0;
1956 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001957 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001958 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001959 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001960 }
1961
Felipe Leme9a523ae2016-10-20 15:10:33 -07001962 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001963 if (do_broadcast) {
1964 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001965
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001966 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001967 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001968 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001969 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001970 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001971 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001972 };
1973 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001974 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001975 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001976 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001977 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001978 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001979 }
1980 }
1981
Nick Kralevichf3599b32016-01-25 15:05:16 -08001982 /* read /proc/cmdline before dropping root */
1983 FILE *cmdline = fopen("/proc/cmdline", "re");
1984 if (cmdline) {
1985 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1986 fclose(cmdline);
1987 }
1988
John Michelau1f794c42012-09-17 11:20:19 -05001989 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001990 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001991 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001992
Felipe Leme9a523ae2016-10-20 15:10:33 -07001993 if (do_fb && ds.do_early_screenshot_) {
1994 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001995 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001996 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001997 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001998 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001999 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002000 }
2001 }
2002
Felipe Leme1e9edc62015-12-21 16:02:13 -08002003 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002004 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2005 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002006 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002007 }
2008 }
2009
Felipe Leme71bbfc52015-11-23 14:14:51 -08002010 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002011 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002012 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2013 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2014 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2015 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002016 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002017 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002018 /* TODO: rather than generating a text file now and zipping it later,
2019 it would be more efficient to redirect stdout to the zip entry
2020 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07002021 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2022 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002023 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002024 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002025 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002026 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002027
2028 // Don't buffer stdout
2029 setvbuf(stdout, nullptr, _IONBF, 0);
2030
Felipe Leme608385d2016-02-01 10:35:38 -08002031 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2032 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002033 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002034 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002035
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002036 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002037 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002038 ds.DumpstateBoard();
mukesh agrawal253dad42018-01-23 21:59:59 -08002039 } else if (wifi_only) {
2040 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002041 } else {
2042 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
2043 // First try to dump anrd trace if the daemon is running. Otherwise, dump
2044 // the raw trace.
2045 if (!dump_anrd_trace()) {
2046 dump_systrace();
2047 }
2048
2049 // Invoking the following dumpsys calls before dump_traces() to try and
2050 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07002051 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002052
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002053 /* collect stack traces from Dalvik and native processes (needs root) */
2054 dump_traces_path = dump_traces();
2055
2056 /* Run some operations that require root. */
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07002057 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
2058 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
Narayan Kamath8f788292017-05-25 13:20:39 +01002059
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002060 ds.AddDir(RECOVERY_DIR, true);
2061 ds.AddDir(RECOVERY_DATA_DIR, true);
Tianjie Xu75d53362018-04-11 16:42:28 -07002062 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002063 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2064 if (!PropertiesHelper::IsUserBuild()) {
2065 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2066 ds.AddDir(PROFILE_DATA_DIR_REF, true);
2067 }
2068 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002069 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002070
2071 // Capture any IPSec policies in play. No keys are exposed here.
2072 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
2073 CommandOptions::WithTimeout(10).Build());
2074
2075 // Run ss as root so we can see socket marks.
2076 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
2077 CommandOptions::WithTimeout(10).Build());
2078
Jin Qian3cd671e2017-09-27 18:50:04 -07002079 // Run iotop as root to show top 100 IO threads
2080 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2081
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002082 if (!DropRootUser()) {
2083 return -1;
2084 }
2085
2086 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002087 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002088
Felipe Leme55b42a62015-11-10 17:39:08 -08002089 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002090 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002091 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002092 }
2093
Felipe Leme6e01fa62015-11-11 19:35:14 -08002094 /* rename or zip the (now complete) .tmp file to its final location */
2095 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002096
2097 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002098 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07002099 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08002100 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002101 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002102 /* must whitelist which characters are allowed, otherwise it could cross directories */
2103 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002104 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002105 change_suffix = true;
2106 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002107 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08002108 }
2109 }
2110 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002111 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2112 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07002113 if (!ds.screenshot_path_.empty()) {
2114 std::string new_screenshot_path = ds.GetPath(".png");
2115 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2116 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2117 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08002118 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002119 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08002120 }
2121 }
2122 }
2123
Felipe Leme6e01fa62015-11-11 19:35:14 -08002124 bool do_text_file = true;
2125 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07002126 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002127 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002128 do_text_file = true;
2129 } else {
2130 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08002131 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07002132 std::string new_path = ds.GetPath(".zip");
2133 if (ds.path_ != new_path) {
2134 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2135 if (rename(ds.path_.c_str(), new_path.c_str())) {
2136 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002137 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08002138 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002139 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08002140 }
2141 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002142 }
2143 }
2144 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002145 ds.path_ = ds.GetPath(".txt");
2146 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
2147 ds.tmp_path_.c_str());
2148 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2149 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002150 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002151 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08002152 }
2153 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002154 if (use_control_socket) {
2155 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002156 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002157 "FAIL:could not create zip file, check %s "
2158 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002159 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002160 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002161 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002162 }
2163 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002164 }
2165
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002166 /* vibrate a few but shortly times to let user know it's finished */
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002167 if (do_vibrate) {
2168 for (int i = 0; i < 3; i++) {
2169 Vibrate(75);
2170 usleep((75 + 50) * 1000);
2171 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002172 }
2173
Jeff Brown1dc94e32014-09-11 14:15:27 -07002174 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002175 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002176 if (!ds.path_.empty()) {
2177 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002178 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002179
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002180 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002181 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002182 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002183 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002184 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002185 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2186 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002187 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002188 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002189 if (do_fb) {
2190 am_args.push_back("--es");
2191 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002192 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002193 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002194 if (!ds.notification_title.empty()) {
2195 am_args.push_back("--es");
2196 am_args.push_back("android.intent.extra.TITLE");
2197 am_args.push_back(ds.notification_title);
2198 if (!ds.notification_description.empty()) {
2199 am_args.push_back("--es");
2200 am_args.push_back("android.intent.extra.DESCRIPTION");
2201 am_args.push_back(ds.notification_description);
2202 }
2203 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002204 if (is_remote_mode) {
2205 am_args.push_back("--es");
2206 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002207 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002208 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2209 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002210 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002211 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002212 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002213 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002214 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002215 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002216 }
2217
Felipe Leme7447d7c2016-11-03 18:12:22 -07002218 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2219 ds.progress_->GetInitialMax());
2220 ds.progress_->Save();
2221 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002222
Felipe Leme107a05f2016-03-08 15:11:15 -08002223 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002224 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002225 }
2226
Felipe Leme9a523ae2016-10-20 15:10:33 -07002227 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002228 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002229 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002230 }
2231
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07002232 ds.tombstone_data_.clear();
2233 ds.anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002234
Colin Crossf45fa6b2012-03-26 12:38:26 -07002235 return 0;
2236}