blob: 024cf98f0e40a2ea2ee2094b9b0e483d16b2cbf6 [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 Kong19d5c002018-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 Kong19d5c002018-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 Kong19d5c002018-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
Makoto Onuki60780982018-04-16 15:34:00 -07001340 RunDumpsys("APP SERVICES PLATFORM", {"activity", "service", "all-platform"},
1341 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
Nandana Dutt4be45d12018-09-26 15:04:23 +01001379/* Dumps state for the default case. Returns true if everything went fine. */
1380static bool DumpstateDefault() {
1381 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1382 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1383 // the raw trace.
1384 if (!dump_anrd_trace()) {
1385 dump_systrace();
1386 }
1387
1388 // Invoking the following dumpsys calls before dump_traces() to try and
1389 // keep the system stats as close to its initial state as possible.
1390 RunDumpsysCritical();
1391
1392 /* collect stack traces from Dalvik and native processes (needs root) */
1393 dump_traces_path = dump_traces();
1394
1395 /* Run some operations that require root. */
1396 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1397 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
1398
1399 ds.AddDir(RECOVERY_DIR, true);
1400 ds.AddDir(RECOVERY_DATA_DIR, true);
1401 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
1402 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1403 if (!PropertiesHelper::IsUserBuild()) {
1404 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1405 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1406 }
1407 add_mountinfo();
1408 DumpIpTablesAsRoot();
1409
1410 // Capture any IPSec policies in play. No keys are exposed here.
1411 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, CommandOptions::WithTimeout(10).Build());
1412
1413 // Run ss as root so we can see socket marks.
1414 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
1415
1416 // Run iotop as root to show top 100 IO threads
1417 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1418
1419 if (!DropRootUser()) {
1420 return false;
1421 }
1422
1423 dumpstate();
1424 return true;
1425}
1426
mukesh agrawal253dad42018-01-23 21:59:59 -08001427// This method collects common dumpsys for telephony and wifi
1428static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001429 DumpIpTablesAsRoot();
1430
1431 if (!DropRootUser()) {
1432 return;
1433 }
1434
1435 do_dmesg();
1436 DoLogcat();
1437 DumpPacketStats();
1438 DoKmsg();
1439 DumpIpAddrAndRules();
1440 dump_route_tables();
1441
1442 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1443 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001444}
1445
1446// This method collects dumpsys for telephony debugging only
1447static void DumpstateTelephonyOnly() {
1448 DurationReporter duration_reporter("DUMPSTATE");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001449 const CommandOptions DUMPSYS_COMPONENTS_OPTIONS = CommandOptions::WithTimeout(60).Build();
mukesh agrawal253dad42018-01-23 21:59:59 -08001450
1451 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001452
1453 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1454
1455 printf("========================================================\n");
1456 printf("== Android Framework Services\n");
1457 printf("========================================================\n");
1458
Vishnu Nair652cc802017-11-30 15:18:30 -08001459 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1460 SEC_TO_MSEC(10));
1461 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1462 SEC_TO_MSEC(10));
Amruth Ramachandrand25a9142018-04-02 16:16:09 -07001463 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1464 SEC_TO_MSEC(10));
Sooraj Sasindrane8d98912018-04-20 11:31:55 -07001465 RunDumpsys("BATTERYSTATS", {"batterystats"}, CommandOptions::WithTimeout(90).Build(),
1466 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001467
1468 printf("========================================================\n");
1469 printf("== Running Application Services\n");
1470 printf("========================================================\n");
1471
1472 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1473
1474 printf("========================================================\n");
Sooraj Sasindrana0829e72018-05-19 15:52:17 -07001475 printf("== Running Application Services (non-platform)\n");
1476 printf("========================================================\n");
1477
1478 RunDumpsys("APP SERVICES NON-PLATFORM", {"activity", "service", "all-non-platform"},
1479 DUMPSYS_COMPONENTS_OPTIONS);
1480
1481 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001482 printf("== dumpstate: done (id %d)\n", ds.id_);
1483 printf("========================================================\n");
1484}
1485
mukesh agrawal253dad42018-01-23 21:59:59 -08001486// This method collects dumpsys for wifi debugging only
1487static void DumpstateWifiOnly() {
1488 DurationReporter duration_reporter("DUMPSTATE");
1489
1490 DumpstateRadioCommon();
1491
1492 printf("========================================================\n");
1493 printf("== Android Framework Services\n");
1494 printf("========================================================\n");
1495
1496 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1497 SEC_TO_MSEC(10));
1498 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1499 SEC_TO_MSEC(10));
1500
1501 printf("========================================================\n");
1502 printf("== dumpstate: done (id %d)\n", ds.id_);
1503 printf("========================================================\n");
1504}
1505
Felipe Leme6f674ae2016-11-18 17:10:33 -08001506void Dumpstate::DumpstateBoard() {
1507 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001508 printf("========================================================\n");
1509 printf("== Board\n");
1510 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001511
Felipe Leme6f674ae2016-11-18 17:10:33 -08001512 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001513 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001514 return;
1515 }
1516
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001517 std::vector<std::string> paths;
1518 std::vector<android::base::ScopeGuard<std::function<void()>>> remover;
Jie Song9fbfad02017-06-20 16:29:42 -07001519 for (int i = 0; i < NUM_OF_DUMPS; i++) {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001520 paths.emplace_back(kDumpstateBoardPath + kDumpstateBoardFiles[i]);
1521 remover.emplace_back(android::base::make_scope_guard(std::bind(
1522 [](std::string path) {
1523 if (remove(path.c_str()) != 0 && errno != ENOENT) {
1524 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1525 }
1526 },
1527 paths[i])));
1528 }
Jie Song9fbfad02017-06-20 16:29:42 -07001529
Wei Wang587eac92018-04-05 12:17:20 -07001530 sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
1531 if (dumpstate_device == nullptr) {
1532 MYLOGE("No IDumpstateDevice implementation\n");
1533 return;
1534 }
1535
1536 using ScopedNativeHandle =
1537 std::unique_ptr<native_handle_t, std::function<void(native_handle_t*)>>;
1538 ScopedNativeHandle handle(native_handle_create(static_cast<int>(paths.size()), 0),
1539 [](native_handle_t* handle) {
1540 native_handle_close(handle);
1541 native_handle_delete(handle);
1542 });
1543 if (handle == nullptr) {
1544 MYLOGE("Could not create native_handle\n");
1545 return;
1546 }
1547
1548 for (size_t i = 0; i < paths.size(); i++) {
1549 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", paths[i].c_str());
1550
1551 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
1552 open(paths[i].c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1553 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1554 if (fd < 0) {
1555 MYLOGE("Could not open file %s: %s\n", paths[i].c_str(), strerror(errno));
1556 return;
1557 }
1558 handle.get()->data[i] = fd.release();
1559 }
1560
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001561 // Given that bugreport is required to diagnose failures, it's better to
Wei Wang587eac92018-04-05 12:17:20 -07001562 // set an arbitrary amount of timeout for IDumpstateDevice than to block the
1563 // rest of bugreport. In the timeout case, we will kill dumpstate board HAL
1564 // and grab whatever dumped
1565 std::packaged_task<bool()>
1566 dumpstate_task([paths, dumpstate_device, &handle]() -> bool {
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001567 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle.get());
1568 if (!status.isOk()) {
1569 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
Wei Wang587eac92018-04-05 12:17:20 -07001570 return false;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001571 }
Wei Wang587eac92018-04-05 12:17:20 -07001572 return true;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001573 });
Wei Wang587eac92018-04-05 12:17:20 -07001574
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001575 auto result = dumpstate_task.get_future();
1576 std::thread(std::move(dumpstate_task)).detach();
Wei Wang587eac92018-04-05 12:17:20 -07001577
1578 constexpr size_t timeout_sec = 30;
1579 if (result.wait_for(std::chrono::seconds(timeout_sec)) != std::future_status::ready) {
1580 MYLOGE("dumpstateBoard timed out after %zus, killing dumpstate vendor HAL\n", timeout_sec);
1581 if (!android::base::SetProperty("ctl.interface_restart",
1582 android::base::StringPrintf("%s/default",
1583 IDumpstateDevice::descriptor))) {
1584 MYLOGE("Couldn't restart dumpstate HAL\n");
1585 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001586 }
Wei Wang587eac92018-04-05 12:17:20 -07001587 // Wait some time for init to kill dumpstate vendor HAL
1588 constexpr size_t killing_timeout_sec = 10;
1589 if (result.wait_for(std::chrono::seconds(killing_timeout_sec)) != std::future_status::ready) {
1590 MYLOGE("killing dumpstateBoard timed out after %zus, continue and "
1591 "there might be racing in content\n", killing_timeout_sec);
1592 }
1593
1594 auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
1595 for (size_t i = 0; i < paths.size(); i++) {
1596 struct stat s;
1597 if (fstat(handle.get()->data[i], &s) == -1) {
1598 MYLOGE("Failed to fstat %s: %s\n", kDumpstateBoardFiles[i].c_str(),
1599 strerror(errno));
1600 file_sizes[i] = -1;
1601 continue;
1602 }
1603 file_sizes[i] = s.st_size;
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001604 }
1605
1606 for (size_t i = 0; i < paths.size(); i++) {
1607 if (file_sizes[i] == -1) {
1608 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001609 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001610 if (file_sizes[i] == 0) {
Jie Song9fbfad02017-06-20 16:29:42 -07001611 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001612 continue;
Jie Song9fbfad02017-06-20 16:29:42 -07001613 }
Luis Hector Chavez7aecd382018-03-19 11:16:59 -07001614 AddZipEntry(kDumpstateBoardFiles[i], paths[i]);
Jie Song9fbfad02017-06-20 16:29:42 -07001615 }
1616
Felipe Lemed8b94e52016-12-08 10:21:44 -08001617 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001618}
1619
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001620static void ShowUsageAndExit(int exitCode = 1) {
1621 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001622 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001623 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1624 " -h: display this help message\n"
1625 " -b: play sound file instead of vibrate, at beginning of job\n"
1626 " -e: play sound file instead of vibrate, at end of job\n"
1627 " -o: write to file (instead of stdout)\n"
1628 " -d: append date to filename (requires -o)\n"
1629 " -p: capture screenshot to filename.png (requires -o)\n"
1630 " -z: generate zipped file (requires -o)\n"
1631 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001632 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001633 " -q: disable vibrate\n"
1634 " -B: send broadcast when finished (requires -o)\n"
1635 " -P: send broadcast when started and update system properties on "
1636 "progress (requires -o and -B)\n"
1637 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1638 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001639 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001640 exit(exitCode);
1641}
1642
1643static void ExitOnInvalidArgs() {
1644 fprintf(stderr, "invalid combination of args\n");
1645 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001646}
1647
Wei Liuf87959e2016-08-26 14:51:42 -07001648static void register_sig_handler() {
Luis Hector Chavez558e1ef2018-03-22 15:39:17 -07001649 signal(SIGPIPE, SIG_IGN);
Wei Liuf87959e2016-08-26 14:51:42 -07001650}
1651
Felipe Leme1d486fe2016-10-14 18:06:47 -07001652bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001653 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001654 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001655 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001656 // Final timestamp
1657 char date[80];
1658 time_t the_real_now_please_stand_up = time(nullptr);
1659 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001660 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001661 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001662
Felipe Leme9a523ae2016-10-20 15:10:33 -07001663 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001664 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001665 return false;
1666 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001667 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001668 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001669 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001670 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001671
Felipe Leme0f3fb202016-06-10 17:10:53 -07001672 // Add log file (which contains stderr output) to zip...
1673 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001674 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001675 MYLOGE("Failed to add dumpstate log to .zip file\n");
1676 return false;
1677 }
1678 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001679 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001680 fprintf(stderr, "\n");
1681
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001682 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001683 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001684 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001685 return false;
1686 }
1687
Felipe Leme1d486fe2016-10-14 18:06:47 -07001688 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1689 ds.zip_file.reset(nullptr);
1690
Felipe Lemee9d2c542016-11-15 11:48:26 -08001691 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1692 if (remove(tmp_path_.c_str()) != 0) {
1693 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001694 }
1695
Felipe Leme1e9edc62015-12-21 16:02:13 -08001696 return true;
1697}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001698
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001699static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001700 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1701 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001702 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001703 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001704 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001705 }
1706
1707 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001708 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001709
1710 std::vector<uint8_t> buffer(65536);
1711 while (1) {
1712 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1713 if (bytes_read == 0) {
1714 break;
1715 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001716 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Yi Kong19d5c002018-07-20 13:39:55 -07001717 return nullptr;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001718 }
1719
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001720 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001721 }
1722
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001723 uint8_t hash[SHA256_DIGEST_LENGTH];
1724 SHA256_Final(hash, &ctx);
1725
1726 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1727 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001728 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001729 }
1730 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1731 return std::string(hash_buffer);
1732}
1733
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001734static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1735 // clang-format off
1736 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1737 "--receiver-foreground", "--receiver-include-background", "-a", action};
1738 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001739
1740 am.insert(am.end(), args.begin(), args.end());
1741
Felipe Leme8d2410e2017-02-08 09:46:08 -08001742 RunCommand("", am,
1743 CommandOptions::WithTimeout(20)
1744 .Log("Sending broadcast: '%s'\n")
1745 .Always()
1746 .DropRoot()
1747 .RedirectStderr()
1748 .Build());
1749}
1750
Felipe Leme35b8cf12017-02-10 15:47:29 -08001751static void Vibrate(int duration_ms) {
1752 // clang-format off
1753 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1754 CommandOptions::WithTimeout(10)
1755 .Log("Vibrate: '%s'\n")
1756 .Always()
1757 .Build());
1758 // clang-format on
1759}
1760
Nandana Dutt4be45d12018-09-26 15:04:23 +01001761/*
1762 * Prepares state like filename, screenshot path, etc in Dumpstate. Also initializes ZipWriter
1763 * if we are writing zip files and adds the version file.
1764 */
1765static void PrepareToWriteToFile() {
1766 const Dumpstate::DumpOptions& options = ds.options_;
1767 ds.bugreport_dir_ = dirname(options.use_outfile.c_str());
1768 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1769 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
1770 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(options.use_outfile.c_str()),
1771 device_name.c_str(), build_id.c_str());
1772 if (options.do_add_date) {
1773 char date[80];
1774 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
1775 ds.name_ = date;
1776 } else {
1777 ds.name_ = "undated";
1778 }
1779
1780 if (options.telephony_only) {
1781 ds.base_name_ += "-telephony";
1782 } else if (options.wifi_only) {
1783 ds.base_name_ += "-wifi";
1784 }
1785
1786 if (options.do_fb) {
1787 ds.screenshot_path_ = ds.GetPath(".png");
1788 }
1789 ds.tmp_path_ = ds.GetPath(".tmp");
1790 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
1791
1792 MYLOGD(
1793 "Bugreport dir: %s\n"
1794 "Base name: %s\n"
1795 "Suffix: %s\n"
1796 "Log path: %s\n"
1797 "Temporary path: %s\n"
1798 "Screenshot path: %s\n",
1799 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), ds.log_path_.c_str(),
1800 ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
1801
1802 if (options.do_zip_file) {
1803 ds.path_ = ds.GetPath(".zip");
1804 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1805 create_parent_dirs(ds.path_.c_str());
1806 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
1807 if (ds.zip_file == nullptr) {
1808 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
1809 } else {
1810 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
1811 }
1812 ds.AddTextZipEntry("version.txt", ds.version_);
1813 }
1814}
1815
1816/*
1817 * Finalizes writing to the file by renaming or zipping the tmp file to the final location,
1818 * printing zipped file status, etc.
1819 */
1820static void FinalizeFile() {
1821 const Dumpstate::DumpOptions& options = ds.options_;
1822 /* check if user changed the suffix using system properties */
1823 std::string name =
1824 android::base::GetProperty(android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
1825 bool change_suffix = false;
1826 if (!name.empty()) {
1827 /* must whitelist which characters are allowed, otherwise it could cross directories */
1828 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1829 if (std::regex_match(name.c_str(), valid_regex)) {
1830 change_suffix = true;
1831 } else {
1832 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
1833 }
1834 }
1835 if (change_suffix) {
1836 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1837 ds.name_ = name;
1838 if (!ds.screenshot_path_.empty()) {
1839 std::string new_screenshot_path = ds.GetPath(".png");
1840 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1841 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1842 new_screenshot_path.c_str(), strerror(errno));
1843 } else {
1844 ds.screenshot_path_ = new_screenshot_path;
1845 }
1846 }
1847 }
1848
1849 bool do_text_file = true;
1850 if (options.do_zip_file) {
1851 if (!ds.FinishZipFile()) {
1852 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
1853 do_text_file = true;
1854 } else {
1855 do_text_file = false;
1856 // Since zip file is already created, it needs to be renamed.
1857 std::string new_path = ds.GetPath(".zip");
1858 if (ds.path_ != new_path) {
1859 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1860 if (rename(ds.path_.c_str(), new_path.c_str())) {
1861 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
1862 strerror(errno));
1863 } else {
1864 ds.path_ = new_path;
1865 }
1866 }
1867 }
1868 }
1869 if (do_text_file) {
1870 ds.path_ = ds.GetPath(".txt");
1871 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), ds.tmp_path_.c_str());
1872 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1873 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), strerror(errno));
1874 ds.path_.clear();
1875 }
1876 }
1877 if (options.use_control_socket) {
1878 if (do_text_file) {
1879 dprintf(ds.control_socket_fd_,
1880 "FAIL:could not create zip file, check %s "
1881 "for more details\n",
1882 ds.log_path_.c_str());
1883 } else {
1884 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
1885 }
1886 }
1887}
1888
1889/* Broadcasts that we are done with the bugreport */
1890static void SendBugreportFinishedBroadcast() {
1891 const Dumpstate::DumpOptions& options = ds.options_;
1892 if (!ds.path_.empty()) {
1893 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
1894 // clang-format off
1895
1896 std::vector<std::string> am_args = {
1897 "--receiver-permission", "android.permission.DUMP",
1898 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
1899 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
1900 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
1901 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1902 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
1903 };
1904 // clang-format on
1905 if (options.do_fb) {
1906 am_args.push_back("--es");
1907 am_args.push_back("android.intent.extra.SCREENSHOT");
1908 am_args.push_back(ds.screenshot_path_);
1909 }
1910 if (!ds.notification_title.empty()) {
1911 am_args.push_back("--es");
1912 am_args.push_back("android.intent.extra.TITLE");
1913 am_args.push_back(ds.notification_title);
1914 if (!ds.notification_description.empty()) {
1915 am_args.push_back("--es");
1916 am_args.push_back("android.intent.extra.DESCRIPTION");
1917 am_args.push_back(ds.notification_description);
1918 }
1919 }
1920 if (options.is_remote_mode) {
1921 am_args.push_back("--es");
1922 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1923 am_args.push_back(SHA256_file_hash(ds.path_));
1924 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1925 } else {
1926 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
1927 }
1928 } else {
1929 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
1930 }
1931}
1932
Nandana Dutt3f8c7172018-09-25 12:01:54 +01001933int Dumpstate::ParseCommandlineOptions(int argc, char* argv[]) {
1934 int ret = -1; // success
1935 int c;
1936 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
1937 switch (c) {
1938 // clang-format off
1939 case 'd': options_.do_add_date = true; break;
1940 case 'z': options_.do_zip_file = true; break;
1941 case 'o': options_.use_outfile = optarg; break;
1942 case 's': options_.use_socket = true; break;
1943 case 'S': options_.use_control_socket = true; break;
1944 case 'v': options_.show_header_only = true; break;
1945 case 'q': options_.do_vibrate = false; break;
1946 case 'p': options_.do_fb = true; break;
1947 case 'P': update_progress_ = true; break;
1948 case 'R': options_.is_remote_mode = true; break;
1949 case 'B': options_.do_broadcast = true; break;
1950 case 'V': break; // compatibility no-op
1951 case 'h':
1952 ret = 0;
1953 break;
1954 default:
1955 fprintf(stderr, "Invalid option: %c\n", c);
1956 ret = 1;
1957 break;
1958 // clang-format on
1959 }
1960 }
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001961
Nandana Dutt3f8c7172018-09-25 12:01:54 +01001962 // TODO: use helper function to convert argv into a string
1963 for (int i = 0; i < argc; i++) {
1964 args_ += argv[i];
1965 if (i < argc - 1) {
1966 args_ += " ";
1967 }
1968 }
1969
1970 // Reset next index used by getopt so this can be called multiple times, for eg, in tests.
1971 optind = 1;
1972 return ret;
1973}
1974
1975// TODO: Move away from system properties when we have binder.
1976void Dumpstate::SetOptionsFromProperties() {
1977 extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1978 if (!extra_options_.empty()) {
1979 // Framework uses a system property to override some command-line args.
1980 // Currently, it contains the type of the requested bugreport.
1981 if (extra_options_ == "bugreportplus") {
1982 // Currently, the dumpstate binder is only used by Shell to update progress.
1983 options_.do_start_service = true;
1984 update_progress_ = true;
1985 options_.do_fb = false;
1986 } else if (extra_options_ == "bugreportremote") {
1987 options_.do_vibrate = false;
1988 options_.is_remote_mode = true;
1989 options_.do_fb = false;
1990 } else if (extra_options_ == "bugreportwear") {
1991 options_.do_start_service = true;
1992 update_progress_ = true;
1993 options_.do_zip_file = true;
1994 } else if (extra_options_ == "bugreporttelephony") {
1995 options_.telephony_only = true;
1996 } else if (extra_options_ == "bugreportwifi") {
1997 options_.wifi_only = true;
1998 options_.do_zip_file = true;
1999 } else {
2000 MYLOGE("Unknown extra option: %s\n", extra_options_.c_str());
2001 }
2002 // Reset the property
2003 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
2004 }
2005
2006 notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
2007 if (!notification_title.empty()) {
2008 // Reset the property
2009 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
2010
2011 notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2012 if (!notification_description.empty()) {
2013 // Reset the property
2014 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
2015 }
2016 MYLOGD("notification (title: %s, description: %s)\n", notification_title.c_str(),
2017 notification_description.c_str());
2018 }
2019}
2020
2021bool Dumpstate::ValidateOptions() {
2022 if ((options_.do_zip_file || options_.do_add_date || ds.update_progress_ ||
2023 options_.do_broadcast) &&
2024 options_.use_outfile.empty()) {
2025 return false;
2026 }
2027
2028 if (options_.use_control_socket && !options_.do_zip_file) {
2029 return false;
2030 }
2031
2032 if (ds.update_progress_ && !options_.do_broadcast) {
2033 return false;
2034 }
2035
2036 if (options_.is_remote_mode && (ds.update_progress_ || !options_.do_broadcast ||
2037 !options_.do_zip_file || !options_.do_add_date)) {
2038 return false;
2039 }
2040 return true;
2041}
2042
2043/* Main entry point for dumpstate. */
2044int run_main(int argc, char* argv[]) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07002045 /* set as high priority, and protect from OOM killer */
2046 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002047
Felipe Lemed071c682016-10-20 16:48:00 -07002048 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07002049 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002050 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002051 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07002052 } else {
2053 /* fallback to kernels <= 2.6.35 */
2054 oom_adj = fopen("/proc/self/oom_adj", "we");
2055 if (oom_adj) {
2056 fputs("-17", oom_adj);
2057 fclose(oom_adj);
2058 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002059 }
2060
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002061 int status = ds.ParseCommandlineOptions(argc, argv);
2062 if (status != -1) {
2063 ShowUsageAndExit(status);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002064 }
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002065 ds.SetOptionsFromProperties();
2066 if (!ds.ValidateOptions()) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07002067 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00002068 }
2069
Felipe Lemed071c682016-10-20 16:48:00 -07002070 if (ds.version_ == VERSION_DEFAULT) {
2071 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08002072 }
2073
Vishnu Nair64afc022018-02-01 15:29:34 -08002074 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
2075 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
2076 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
2077 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07002078 exit(1);
2079 }
2080
Nandana Dutt4be45d12018-09-26 15:04:23 +01002081 const Dumpstate::DumpOptions& options = ds.options_;
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002082 if (options.show_header_only) {
Felipe Lemed071c682016-10-20 16:48:00 -07002083 ds.PrintHeader();
2084 exit(0);
2085 }
2086
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002087 // Redirect output if needed
2088 bool is_redirecting = !options.use_socket && !options.use_outfile.empty();
Felipe Leme7447d7c2016-11-03 18:12:22 -07002089
2090 // TODO: temporarily set progress until it's part of the Dumpstate constructor
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002091 std::string stats_path = is_redirecting
2092 ? android::base::StringPrintf("%s/dumpstate-stats.txt",
2093 dirname(options.use_outfile.c_str()))
2094 : "";
Felipe Leme7447d7c2016-11-03 18:12:22 -07002095 ds.progress_.reset(new Progress(stats_path));
2096
Felipe Lemed071c682016-10-20 16:48:00 -07002097 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07002098 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07002099 ds.id_ = ++last_id;
2100 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
2101
2102 MYLOGI("begin\n");
2103
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08002104 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07002105
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002106 if (options.do_start_service) {
Felipe Leme75876a22016-10-27 16:31:27 -07002107 MYLOGI("Starting 'dumpstate' service\n");
2108 android::status_t ret;
2109 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
2110 MYLOGE("Unable to start DumpstateService: %d\n", ret);
2111 }
2112 }
2113
Felipe Lemef0292972016-11-22 13:57:05 -08002114 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07002115 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
2116 }
2117
Felipe Leme7447d7c2016-11-03 18:12:22 -07002118 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07002119 ds.extra_options_.c_str());
2120
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002121 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08002122
Felipe Leme9a523ae2016-10-20 15:10:33 -07002123 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08002124
Christopher Ferrised9354f2014-10-01 17:35:01 -07002125 // If we are going to use a socket, do it as early as possible
2126 // to avoid timeouts from bugreport.
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002127 if (options.use_socket) {
Christopher Ferrised9354f2014-10-01 17:35:01 -07002128 redirect_to_socket(stdout, "dumpstate");
2129 }
2130
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002131 if (options.use_control_socket) {
Felipe Leme2628e9e2016-04-12 16:36:51 -07002132 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002133 ds.control_socket_fd_ = open_socket("dumpstate");
2134 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07002135 }
2136
Felipe Leme71bbfc52015-11-23 14:14:51 -08002137 if (is_redirecting) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002138 PrepareToWriteToFile();
Felipe Leme1e9edc62015-12-21 16:02:13 -08002139
Felipe Leme9a523ae2016-10-20 15:10:33 -07002140 if (ds.update_progress_) {
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002141 if (options.do_broadcast) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002142 // clang-format off
2143 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002144 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002145 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002146 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002147 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002148 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002149 };
2150 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002151 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002152 }
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002153 if (options.use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002154 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002155 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002156 }
2157 }
2158
Nick Kralevichf3599b32016-01-25 15:05:16 -08002159 /* read /proc/cmdline before dropping root */
2160 FILE *cmdline = fopen("/proc/cmdline", "re");
2161 if (cmdline) {
2162 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2163 fclose(cmdline);
2164 }
2165
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002166 if (options.do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002167 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002168 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002169
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002170 if (options.do_fb && ds.do_early_screenshot_) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002171 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002172 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002173 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002174 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002175 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002176 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002177 }
2178 }
2179
Nandana Dutt4be45d12018-09-26 15:04:23 +01002180 if (options.do_zip_file && ds.zip_file != nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002181 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2182 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002183 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002184 }
2185 }
2186
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002187 int dup_stdout_fd;
2188 int dup_stderr_fd;
Felipe Leme71bbfc52015-11-23 14:14:51 -08002189 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002190 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002191 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2192 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2193 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2194 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002195 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002196 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002197 /* TODO: rather than generating a text file now and zipping it later,
2198 it would be more efficient to redirect stdout to the zip entry
2199 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07002200 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2201 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002202 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002203 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002204 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002205 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002206
2207 // Don't buffer stdout
2208 setvbuf(stdout, nullptr, _IONBF, 0);
2209
Felipe Leme608385d2016-02-01 10:35:38 -08002210 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2211 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002212 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002213 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002214
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002215 if (options.telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002216 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002217 ds.DumpstateBoard();
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002218 } else if (options.wifi_only) {
mukesh agrawal253dad42018-01-23 21:59:59 -08002219 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002220 } else {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002221 // Dump state for the default case. This also drops root.
2222 if (!DumpstateDefault()) {
2223 // Something went wrong.
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002224 return -1;
2225 }
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002226 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002227
Felipe Leme55b42a62015-11-10 17:39:08 -08002228 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002229 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002230 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002231 }
2232
Felipe Leme6e01fa62015-11-11 19:35:14 -08002233 /* rename or zip the (now complete) .tmp file to its final location */
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002234 if (!options.use_outfile.empty()) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002235 FinalizeFile();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002236 }
2237
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002238 /* vibrate a few but shortly times to let user know it's finished */
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002239 if (options.do_vibrate) {
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002240 for (int i = 0; i < 3; i++) {
2241 Vibrate(75);
2242 usleep((75 + 50) * 1000);
2243 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002244 }
2245
Jeff Brown1dc94e32014-09-11 14:15:27 -07002246 /* tell activity manager we're done */
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002247 if (options.do_broadcast) {
Nandana Dutt4be45d12018-09-26 15:04:23 +01002248 SendBugreportFinishedBroadcast();
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002249 }
2250
Felipe Leme7447d7c2016-11-03 18:12:22 -07002251 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2252 ds.progress_->GetInitialMax());
2253 ds.progress_->Save();
2254 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002255
Felipe Leme107a05f2016-03-08 15:11:15 -08002256 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002257 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002258 }
2259
Nandana Dutt3f8c7172018-09-25 12:01:54 +01002260 if (options.use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002261 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002262 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002263 }
2264
Luis Hector Chavez5f6ee4a2018-03-14 15:12:46 -07002265 ds.tombstone_data_.clear();
2266 ds.anr_data_.clear();
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002267
Colin Crossf45fa6b2012-03-26 12:38:26 -07002268 return 0;
2269}