blob: f17ac5b98d9304974e5369a82f0c89faf4a74190 [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>
Narayan Kamath8f788292017-05-25 13:20:39 +010035#include <memory>
36#include <regex>
37#include <set>
38#include <string>
39#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070040
Felipe Leme96c2bbb2016-09-26 09:21:21 -070041#include <android-base/file.h>
42#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080043#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070044#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070045#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080046#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080047#include <android/hidl/manager/1.0/IServiceManager.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080048#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070049#include <cutils/properties.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080050#include <dumpsys.h>
Steven Moreland44cd9482018-01-04 16:24:13 -080051#include <hidl/ServiceManagement.h>
Felipe Leme75876a22016-10-27 16:31:27 -070052#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070053#include <private/android_filesystem_config.h>
54#include <private/android_logger.h>
Vishnu Naire97d6122018-01-18 13:58:56 -080055#include <serviceutils/PriorityDumper.h>
Felipe Lemef0292972016-11-22 13:57:05 -080056#include "DumpstateInternal.h"
Vishnu Naire97d6122018-01-18 13:58:56 -080057#include "DumpstateSectionReporter.h"
Felipe Leme75876a22016-10-27 16:31:27 -070058#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070059#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080060
Steven Morelandcb7ef822016-11-29 13:20:37 -080061using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Vishnu Naire97d6122018-01-18 13:58:56 -080062using ::std::literals::chrono_literals::operator""ms;
63using ::std::literals::chrono_literals::operator""s;
Steven Morelandcb7ef822016-11-29 13:20:37 -080064
Felipe Leme47e9be22016-12-21 15:37:07 -080065// TODO: remove once moved to namespace
Vishnu Naire97d6122018-01-18 13:58:56 -080066using android::defaultServiceManager;
67using android::Dumpsys;
68using android::INVALID_OPERATION;
69using android::IServiceManager;
70using android::OK;
71using android::sp;
72using android::status_t;
73using android::String16;
74using android::String8;
75using android::TIMED_OUT;
76using android::UNKNOWN_ERROR;
77using android::Vector;
Felipe Leme47e9be22016-12-21 15:37:07 -080078using android::os::dumpstate::CommandOptions;
79using android::os::dumpstate::DumpFileToFd;
Vishnu Naire97d6122018-01-18 13:58:56 -080080using android::os::dumpstate::DumpstateSectionReporter;
Felipe Leme47e9be22016-12-21 15:37:07 -080081using android::os::dumpstate::GetPidByName;
Vishnu Naire97d6122018-01-18 13:58:56 -080082using android::os::dumpstate::PropertiesHelper;
Felipe Leme47e9be22016-12-21 15:37:07 -080083
Colin Crossf45fa6b2012-03-26 12:38:26 -070084/* read before root is shed */
85static char cmdline_buf[16384] = "(unknown)";
86static const char *dump_traces_path = NULL;
87
Felipe Leme1d486fe2016-10-14 18:06:47 -070088// TODO: variables and functions below should be part of dumpstate object
89
Felipe Leme635ca312016-01-05 14:23:02 -080090static std::set<std::string> mount_points;
91void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080092
Todd Poynor2a83daa2013-11-22 15:44:22 -080093#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070094#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -070095#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -080096
Wei Liu341938b2016-04-27 16:18:17 -070097#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080098#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070099#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -0700100#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +0100101#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
102#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +0900103#define WLUTIL "/vendor/xbin/wlutil"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -0800104#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700105
Narayan Kamath8f788292017-05-25 13:20:39 +0100106// TODO(narayan): Since this information has to be kept in sync
107// with tombstoned, we should just put it in a common header.
108//
109// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +0100110static const std::string TOMBSTONE_DIR = "/data/tombstones/";
111static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
112static const std::string ANR_DIR = "/data/anr/";
113static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700114
Narayan Kamath8f788292017-05-25 13:20:39 +0100115struct DumpData {
116 std::string name;
117 int fd;
118 time_t mtime;
119};
120
121static bool operator<(const DumpData& d1, const DumpData& d2) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100122 return d1.mtime > d2.mtime;
Narayan Kamath8f788292017-05-25 13:20:39 +0100123}
124
125static std::unique_ptr<std::vector<DumpData>> tombstone_data;
126static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700127
Felipe Lemee844a9d2016-09-21 15:01:39 -0700128// TODO: temporary variables and functions used during C++ refactoring
129static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700130static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
131 const CommandOptions& options = CommandOptions::DEFAULT) {
132 return ds.RunCommand(title, fullCommand, options);
133}
134static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800135 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800136 long dumpsysTimeoutMs = 0) {
137 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700138}
139static int DumpFile(const std::string& title, const std::string& path) {
140 return ds.DumpFile(title, path);
141}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800142
Felipe Lemee844a9d2016-09-21 15:01:39 -0700143// Relative directory (inside the zip) for all files copied as-is into the bugreport.
144static const std::string ZIP_ROOT_DIR = "FS";
145
Steven Moreland7440ddb2016-12-15 16:13:39 -0800146// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700147static const std::string kDumpstateBoardPath = "/bugreports/";
Vishnu Naire97d6122018-01-18 13:58:56 -0800148static const std::string kProtoPath = "proto/";
149static const std::string kProtoExt = ".proto";
Jie Song9fbfad02017-06-20 16:29:42 -0700150static const std::string kDumpstateBoardFiles[] = {
151 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700152 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700153};
154static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
155
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700156static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700157static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700158static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700159static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
160static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700161
Felipe Lemef0292972016-11-22 13:57:05 -0800162static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
163
Narayan Kamath8f788292017-05-25 13:20:39 +0100164/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100165 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
166 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
167 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700168 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100169 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100170static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
171 const std::string& file_prefix,
Andreas Gamped0d76952017-08-22 13:08:37 -0700172 bool limit_by_mtime,
173 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100174 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
175
Narayan Kamath8f788292017-05-25 13:20:39 +0100176 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100177 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100178
Narayan Kamathbd863722017-06-01 18:50:12 +0100179 struct dirent* entry = nullptr;
180 while ((entry = readdir(dump_dir.get()))) {
181 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100182 continue;
183 }
184
Narayan Kamathbd863722017-06-01 18:50:12 +0100185 const std::string base_name(entry->d_name);
186 if (base_name.find(file_prefix) != 0) {
187 continue;
188 }
189
190 const std::string abs_path = dir_path + base_name;
191 android::base::unique_fd fd(
192 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
193 if (fd == -1) {
194 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
195 break;
196 }
197
198 struct stat st = {};
199 if (fstat(fd, &st) == -1) {
200 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100201 continue;
202 }
203
204 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100205 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100206 continue;
207 }
208
Narayan Kamathbd863722017-06-01 18:50:12 +0100209 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100210
211 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700212 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100213
214 std::sort(dump_data->begin(), dump_data->end());
215
Andreas Gamped0d76952017-08-22 13:08:37 -0700216 if (limit_by_count && dump_data->size() > 10) {
217 dump_data->erase(dump_data->begin() + 10, dump_data->end());
218 }
219
Narayan Kamath8f788292017-05-25 13:20:39 +0100220 return dump_data.release();
221}
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
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100255static void CloseDumpFds(const std::vector<DumpData>* dumps) {
256 for (auto it = dumps->begin(); it != dumps->end(); ++it) {
257 close(it->fd);
258 }
259}
260
Felipe Leme635ca312016-01-05 14:23:02 -0800261// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700262void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800263 char path[PATH_MAX];
264
265 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
266 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700267 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800268 char linkname[PATH_MAX];
269 ssize_t r = readlink(path, linkname, PATH_MAX);
270 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800271 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800272 return;
273 }
274 linkname[r] = '\0';
275
276 if (mount_points.find(linkname) == mount_points.end()) {
277 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700278 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700279 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800280 mount_points.insert(linkname);
281 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800282 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800283 }
284 }
285}
286
287void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700288 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700289 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800290 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800291 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700292 for_each_pid(do_mountinfo, nullptr);
293 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800294}
295
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700296static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
297{
298 DIR *d;
299 struct dirent *de;
300 char path[PATH_MAX];
301
302 d = opendir(driverpath);
303 if (d == NULL) {
304 return;
305 }
306
307 while ((de = readdir(d))) {
308 if (de->d_type != DT_LNK) {
309 continue;
310 }
311 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700312 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700313 }
314
315 closedir(d);
316}
317
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700318
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700319
320// dump anrd's trace and add to the zip file.
321// 1. check if anrd is running on this device.
322// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
323// 3. wait until the trace generation completes and add to the zip file.
324static bool dump_anrd_trace() {
325 unsigned int pid;
326 char buf[50], path[PATH_MAX];
327 struct dirent *trace;
328 struct stat st;
329 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700330 int retry = 5;
331 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700332 long long cur_size = 0;
333 const char *trace_path = "/data/misc/anrd/";
334
Felipe Leme1d486fe2016-10-14 18:06:47 -0700335 if (!ds.IsZipping()) {
336 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700337 return false;
338 }
339
340 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700341 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700342
343 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700344 if (stat(trace_path, &st) == 0) {
345 old_mtime = st.st_mtime;
346 } else {
347 MYLOGE("Failed to find: %s\n", trace_path);
348 return false;
349 }
350
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700351 // send SIGUSR1 to the anrd to generate a trace.
352 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700353 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700354 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700355 MYLOGE("anrd signal timed out. Please manually collect trace\n");
356 return false;
357 }
358
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700359 while (retry-- > 0 && old_mtime == st.st_mtime) {
360 sleep(1);
361 stat(trace_path, &st);
362 }
363
364 if (retry < 0 && old_mtime == st.st_mtime) {
365 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
366 return false;
367 }
368
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700369 // identify the trace file by its creation time.
370 if (!(trace_dir = opendir(trace_path))) {
371 MYLOGE("Can't open trace file under %s\n", trace_path);
372 }
373 while ((trace = readdir(trace_dir))) {
374 if (strcmp(trace->d_name, ".") == 0
375 || strcmp(trace->d_name, "..") == 0) {
376 continue;
377 }
378 sprintf(path, "%s%s", trace_path, trace->d_name);
379 if (stat(path, &st) == 0) {
380 if (st.st_ctime > max_ctime) {
381 max_ctime = st.st_ctime;
382 sprintf(buf, "%s", trace->d_name);
383 }
384 }
385 }
386 closedir(trace_dir);
387
388 // Wait until the dump completes by checking the size of the trace.
389 if (max_ctime > 0) {
390 sprintf(path, "%s%s", trace_path, buf);
391 while(true) {
392 sleep(1);
393 if (stat(path, &st) == 0) {
394 if (st.st_size == cur_size) {
395 break;
396 } else if (st.st_size > cur_size) {
397 cur_size = st.st_size;
398 } else {
399 return false;
400 }
401 } else {
402 MYLOGE("Cant stat() %s anymore\n", path);
403 return false;
404 }
405 }
406 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700407 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700408 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
409 } else {
410 if (remove(path)) {
411 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
412 }
413 return true;
414 }
415 } else {
416 MYLOGE("Can't stats any trace file under %s\n", trace_path);
417 }
418 }
419 return false;
420}
421
Felipe Lemeefd7e272016-05-18 09:27:16 -0700422static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700423 if (!ds.IsZipping()) {
424 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700425 return;
426 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700427 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700428 if (systrace_path.empty()) {
429 MYLOGE("Not dumping systrace because path is empty\n");
430 return;
431 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700432 const char* path = "/sys/kernel/debug/tracing/tracing_on";
433 long int is_tracing;
434 if (read_file_as_long(path, &is_tracing)) {
435 return; // error already logged
436 }
437 if (is_tracing <= 0) {
438 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
439 return;
440 }
441
Felipe Leme14e034a2016-03-30 18:51:03 -0700442 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
443 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700444 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700445 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700446 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700447 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700448 // peacefully; ideally, we should call strace to stop itself, but there is no such option
449 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700450 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700451 // MYLOGE("could not stop systrace ");
452 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700453 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700454 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700455 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700456 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700457 if (remove(systrace_path.c_str())) {
458 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
459 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700460 }
461}
462
Felipe Lemeefd7e272016-05-18 09:27:16 -0700463static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800464 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700465 return;
466 }
467
Felipe Leme1d486fe2016-10-14 18:06:47 -0700468 std::string raft_path = ds.GetPath("-raft_log.txt");
469 if (raft_path.empty()) {
470 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700471 return;
472 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700473
474 struct stat s;
475 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
476 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
477 return;
478 }
479
Felipe Leme30dbfa12016-09-02 12:43:26 -0700480 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700481 if (!ds.IsZipping()) {
482 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700483 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700484 return;
485 }
486
Felipe Leme1d486fe2016-10-14 18:06:47 -0700487 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
488 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
489 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700490 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700491 if (remove(raft_path.c_str())) {
492 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700493 }
494 }
495}
496
Mark Salyzyn326842f2015-04-30 09:49:41 -0700497static bool skip_not_stat(const char *path) {
498 static const char stat[] = "/stat";
499 size_t len = strlen(path);
500 if (path[len - 1] == '/') { /* Directory? */
501 return false;
502 }
503 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
504}
505
Felipe Leme4c2d6632016-09-28 14:32:00 -0700506static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800507 return false;
508}
509
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700510unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700511
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800512//
513// stat offsets
514// Name units description
515// ---- ----- -----------
516// read I/Os requests number of read I/Os processed
517#define __STAT_READ_IOS 0
518// read merges requests number of read I/Os merged with in-queue I/O
519#define __STAT_READ_MERGES 1
520// read sectors sectors number of sectors read
521#define __STAT_READ_SECTORS 2
522// read ticks milliseconds total wait time for read requests
523#define __STAT_READ_TICKS 3
524// write I/Os requests number of write I/Os processed
525#define __STAT_WRITE_IOS 4
526// write merges requests number of write I/Os merged with in-queue I/O
527#define __STAT_WRITE_MERGES 5
528// write sectors sectors number of sectors written
529#define __STAT_WRITE_SECTORS 6
530// write ticks milliseconds total wait time for write requests
531#define __STAT_WRITE_TICKS 7
532// in_flight requests number of I/Os currently in flight
533#define __STAT_IN_FLIGHT 8
534// io_ticks milliseconds total time this block device has been active
535#define __STAT_IO_TICKS 9
536// time_in_queue milliseconds total wait time for all requests
537#define __STAT_IN_QUEUE 10
538#define __STAT_NUMBER_FIELD 11
539//
540// read I/Os, write I/Os
541// =====================
542//
543// These values increment when an I/O request completes.
544//
545// read merges, write merges
546// =========================
547//
548// These values increment when an I/O request is merged with an
549// already-queued I/O request.
550//
551// read sectors, write sectors
552// ===========================
553//
554// These values count the number of sectors read from or written to this
555// block device. The "sectors" in question are the standard UNIX 512-byte
556// sectors, not any device- or filesystem-specific block size. The
557// counters are incremented when the I/O completes.
558#define SECTOR_SIZE 512
559//
560// read ticks, write ticks
561// =======================
562//
563// These values count the number of milliseconds that I/O requests have
564// waited on this block device. If there are multiple I/O requests waiting,
565// these values will increase at a rate greater than 1000/second; for
566// example, if 60 read requests wait for an average of 30 ms, the read_ticks
567// field will increase by 60*30 = 1800.
568//
569// in_flight
570// =========
571//
572// This value counts the number of I/O requests that have been issued to
573// the device driver but have not yet completed. It does not include I/O
574// requests that are in the queue but not yet issued to the device driver.
575//
576// io_ticks
577// ========
578//
579// This value counts the number of milliseconds during which the device has
580// had I/O requests queued.
581//
582// time_in_queue
583// =============
584//
585// This value counts the number of milliseconds that I/O requests have waited
586// on this block device. If there are multiple I/O requests waiting, this
587// value will increase as the product of the number of milliseconds times the
588// number of requests waiting (see "read ticks" above for an example).
589#define S_TO_MS 1000
590//
591
Mark Salyzyn326842f2015-04-30 09:49:41 -0700592static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800593 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700594 bool z;
595 char *cp, *buffer = NULL;
596 size_t i = 0;
597 FILE *fp = fdopen(fd, "rb");
598 getline(&buffer, &i, fp);
599 fclose(fp);
600 if (!buffer) {
601 return -errno;
602 }
603 i = strlen(buffer);
604 while ((i > 0) && (buffer[i - 1] == '\n')) {
605 buffer[--i] = '\0';
606 }
607 if (!*buffer) {
608 free(buffer);
609 return 0;
610 }
611 z = true;
612 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800613 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700614 if (fields[i] != 0) {
615 z = false;
616 }
617 }
618 if (z) { /* never accessed */
619 free(buffer);
620 return 0;
621 }
622
Wei Wang509bb5d2017-06-09 14:42:12 -0700623 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
624 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700625 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700626
627 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
628 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
629 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700630 free(buffer);
631
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800632 if (fields[__STAT_IO_TICKS]) {
633 unsigned long read_perf = 0;
634 unsigned long read_ios = 0;
635 if (fields[__STAT_READ_TICKS]) {
636 unsigned long long divisor = fields[__STAT_READ_TICKS]
637 * fields[__STAT_IO_TICKS];
638 read_perf = ((unsigned long long)SECTOR_SIZE
639 * fields[__STAT_READ_SECTORS]
640 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
641 / divisor;
642 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
643 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
644 / divisor;
645 }
646
647 unsigned long write_perf = 0;
648 unsigned long write_ios = 0;
649 if (fields[__STAT_WRITE_TICKS]) {
650 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
651 * fields[__STAT_IO_TICKS];
652 write_perf = ((unsigned long long)SECTOR_SIZE
653 * fields[__STAT_WRITE_SECTORS]
654 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
655 / divisor;
656 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
657 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
658 / divisor;
659 }
660
661 unsigned queue = (fields[__STAT_IN_QUEUE]
662 + (fields[__STAT_IO_TICKS] >> 1))
663 / fields[__STAT_IO_TICKS];
664
665 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700666 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 -0800667 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700668 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 -0800669 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800670 }
671
672 /* bugreport timeout factor adjustment */
673 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
674 worst_write_perf = write_perf;
675 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700676 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700677 return 0;
678}
679
Yao Chenbe3bbc12018-01-17 16:31:10 -0800680static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000;
681
682/* timeout in ms to read a list of buffers */
683static unsigned long logcat_timeout(const std::vector<std::string>& buffers) {
684 unsigned long timeout_ms = 0;
685 for (const auto& buffer : buffers) {
686 log_id_t id = android_name_to_log_id(buffer.c_str());
687 unsigned long property_size = __android_logger_get_buffer_size(id);
688 /* Engineering margin is ten-fold our guess */
689 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf;
690 }
691 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS;
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700692}
693
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700694void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700695 std::string build, fingerprint, radio, bootloader, network;
696 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700697
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700698 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
699 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700700 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
701 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
702 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700703 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700704
Felipe Lemed8b94e52016-12-08 10:21:44 -0800705 printf("========================================================\n");
706 printf("== dumpstate: %s\n", date);
707 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700708
Felipe Lemed8b94e52016-12-08 10:21:44 -0800709 printf("\n");
710 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700711 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800712 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
713 printf("Bootloader: %s\n", bootloader.c_str());
714 printf("Radio: %s\n", radio.c_str());
715 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700716
Felipe Lemed8b94e52016-12-08 10:21:44 -0800717 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800718 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800719 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme7709f8a2017-12-05 09:30:09 -0800720 printf("Uptime: ");
721 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"},
722 CommandOptions::WithTimeout(1).Always().Build());
Felipe Lemed8b94e52016-12-08 10:21:44 -0800723 printf("Bugreport format version: %s\n", version_.c_str());
724 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
725 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
726 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800727}
728
Felipe Leme24b66ee2016-06-16 10:55:26 -0700729// List of file extensions that can cause a zip file attachment to be rejected by some email
730// service providers.
731static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
732 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
733 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
734 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
735};
736
Vishnu Naire97d6122018-01-18 13:58:56 -0800737status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd,
738 std::chrono::milliseconds timeout = 0ms) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700739 if (!IsZipping()) {
740 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
741 entry_name.c_str());
Vishnu Naire97d6122018-01-18 13:58:56 -0800742 return INVALID_OPERATION;
Felipe Leme111b9d02016-02-03 09:28:24 -0800743 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700744 std::string valid_name = entry_name;
745
746 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700747 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700748 if (idx != std::string::npos) {
749 std::string extension = entry_name.substr(idx);
750 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
751 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
752 valid_name = entry_name + ".renamed";
753 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
754 }
755 }
756
Felipe Leme6fe9db62016-02-12 09:04:16 -0800757 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
758 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700759 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
760 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700761 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700762 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700763 ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800764 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800765 }
Vishnu Naire97d6122018-01-18 13:58:56 -0800766 auto start = std::chrono::steady_clock::now();
767 auto end = start + timeout;
768 struct pollfd pfd = {fd, POLLIN};
Felipe Lemee82a27d2016-01-05 13:35:44 -0800769
Felipe Leme770410d2016-01-26 17:07:14 -0800770 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800771 while (1) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800772 if (timeout.count() > 0) {
773 // lambda to recalculate the timeout.
774 auto time_left_ms = [end]() {
775 auto now = std::chrono::steady_clock::now();
776 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
777 return std::max(diff.count(), 0LL);
778 };
779
780 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
781 if (rc < 0) {
782 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(),
783 strerror(errno));
784 return -errno;
785 } else if (rc == 0) {
786 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms",
787 entry_name.c_str(), strerror(errno), timeout.count());
788 return TIMED_OUT;
789 }
790 }
791
Zach Riggle22200402016-08-18 01:01:24 -0400792 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800793 if (bytes_read == 0) {
794 break;
795 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800796 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Vishnu Naire97d6122018-01-18 13:58:56 -0800797 return -errno;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800798 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700799 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800800 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700801 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800802 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800803 }
804 }
805
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700806 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700807 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700808 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Vishnu Naire97d6122018-01-18 13:58:56 -0800809 return UNKNOWN_ERROR;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800810 }
811
Vishnu Naire97d6122018-01-18 13:58:56 -0800812 return OK;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800813}
814
Felipe Leme1d486fe2016-10-14 18:06:47 -0700815bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
816 android::base::unique_fd fd(
817 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700818 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800819 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800820 return false;
821 }
822
Vishnu Naire97d6122018-01-18 13:58:56 -0800823 return (AddZipEntryFromFd(entry_name, fd.get()) == OK);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800824}
825
826/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700827static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Vishnu Naire97d6122018-01-18 13:58:56 -0800828 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800829}
830
Felipe Leme1d486fe2016-10-14 18:06:47 -0700831void Dumpstate::AddDir(const std::string& dir, bool recursive) {
832 if (!IsZipping()) {
833 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800834 return;
835 }
Felipe Leme678727a2016-09-21 17:22:11 -0700836 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800837 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700838 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800839}
840
Felipe Leme1d486fe2016-10-14 18:06:47 -0700841bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
842 if (!IsZipping()) {
843 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
844 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800845 return false;
846 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800847 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700848 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700849 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700850 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700851 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800852 return false;
853 }
854
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700855 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700856 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700857 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700858 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800859 return false;
860 }
861
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700862 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700863 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700864 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800865 return false;
866 }
867
868 return true;
869}
870
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800871static void DoKmsg() {
872 struct stat st;
873 if (!stat(PSTORE_LAST_KMSG, &st)) {
874 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
875 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
876 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
877 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
878 } else {
879 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
880 DumpFile("LAST KMSG", "/proc/last_kmsg");
881 }
882}
883
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800884static void DoKernelLogcat() {
Yao Chenbe3bbc12018-01-17 16:31:10 -0800885 unsigned long timeout_ms = logcat_timeout({"kernel"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800886 RunCommand(
887 "KERNEL LOG",
888 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
889 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
890}
891
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800892static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800893 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800894 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
895 // calculate timeout
Yao Chenbe3bbc12018-01-17 16:31:10 -0800896 timeout_ms = logcat_timeout({"main", "system", "crash"});
Tony Makae737652017-03-30 17:47:09 +0100897 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800898 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
899 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800900 timeout_ms = logcat_timeout({"events"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800901 RunCommand(
902 "EVENT LOG",
903 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
904 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Yao Chenbe3bbc12018-01-17 16:31:10 -0800905 timeout_ms = logcat_timeout({"stats"});
906 RunCommand(
907 "STATS LOG",
908 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
909 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
910 timeout_ms = logcat_timeout({"radio"});
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800911 RunCommand(
912 "RADIO LOG",
913 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
914 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800915
916 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
917
918 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -0800919 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable",
920 "-v", "uid", "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800921}
922
Jayachandran Ca94c7172017-06-10 15:08:12 -0700923static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700924 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
925 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900926 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700927 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900928 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
929 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
930 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
931 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700932}
933
Narayan Kamath8f788292017-05-25 13:20:39 +0100934static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
935 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700936 std::string dump_traces_dir;
937
Felipe Lemee184f662016-10-27 10:04:47 -0700938 if (dump_traces_path != nullptr) {
939 if (add_to_zip) {
940 dump_traces_dir = dirname(dump_traces_path);
941 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
942 ds.AddDir(dump_traces_dir, true);
943 } else {
944 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
945 dump_traces_path);
946 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
947 }
948 }
949
Felipe Lemee184f662016-10-27 10:04:47 -0700950
951 // Make sure directory is not added twice.
952 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
953 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
954 // property - but in reality they're the same path (although the former could be nullptr).
955 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
956 // be revisited.
957 bool already_dumped = anr_traces_dir == dump_traces_dir;
958
Narayan Kamath8f788292017-05-25 13:20:39 +0100959 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700960 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
961
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100962 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
963 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
964 if (fd.get() < 0) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100965 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700966 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100967 if (add_to_zip) {
968 if (!already_dumped) {
969 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
970 anr_traces_dir.c_str());
971 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700972 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100973 } else {
974 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
975 anr_traces_file.c_str());
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100976 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
Narayan Kamath8f788292017-05-25 13:20:39 +0100977 }
978 }
979}
980
981static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
982 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
983 anr_traces_dir.c_str());
984
985 // If we're here, dump_traces_path will always be a temporary file
986 // (created with mkostemp or similar) that contains dumps taken earlier
987 // on in the process.
988 if (dump_traces_path != nullptr) {
989 if (add_to_zip) {
990 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
991 } else {
992 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
993 dump_traces_path);
994 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
995 }
996
997 const int ret = unlink(dump_traces_path);
998 if (ret == -1) {
999 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
1000 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -07001001 }
1002 }
1003
Narayan Kamathbd863722017-06-01 18:50:12 +01001004 // Add a specific message for the first ANR Dump.
1005 if (anr_data->size() > 0) {
1006 AddDumps(anr_data->begin(), anr_data->begin() + 1,
1007 "VM TRACES AT LAST ANR", add_to_zip);
1008
Narayan Kamath6b9516c2017-10-27 11:15:51 +01001009 // The "last" ANR will always be included as separate entry in the zip file. In addition,
1010 // it will be present in the body of the main entry if |add_to_zip| == false.
1011 //
1012 // Historical ANRs are always included as separate entries in the bugreport zip file.
1013 AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
1014 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +01001015 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +01001016 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
1017 }
1018}
1019
1020static void AddAnrTraceFiles() {
1021 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1022
1023 std::string anr_traces_file;
1024 std::string anr_traces_dir;
1025 bool is_global_trace_file = true;
1026
1027 // First check whether the stack-trace-dir property is set. When it's set,
1028 // each ANR trace will be written to a separate file and not to a global
1029 // stack trace file.
1030 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
1031 if (anr_traces_dir.empty()) {
1032 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
1033 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +01001034 anr_traces_dir = dirname(anr_traces_file.c_str());
1035 }
Narayan Kamathbd863722017-06-01 18:50:12 +01001036 } else {
1037 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +01001038 }
1039
1040 // We have neither configured a global trace file nor a trace directory,
1041 // there will be nothing to dump.
1042 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
1043 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -07001044 return;
1045 }
1046
Narayan Kamath8f788292017-05-25 13:20:39 +01001047 if (is_global_trace_file) {
1048 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
1049 } else {
1050 AddAnrTraceDir(add_to_zip, anr_traces_dir);
1051 }
1052
Felipe Lemee184f662016-10-27 10:04:47 -07001053 /* slow traces for slow operations */
1054 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001055 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001056 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001057 while (true) {
1058 const std::string slow_trace_path =
1059 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1060 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001061 // No traces file at this index, done with the files.
1062 break;
1063 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001064 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001065 i++;
1066 }
1067 }
1068}
1069
Wei Wang509bb5d2017-06-09 14:42:12 -07001070static void DumpBlockStatFiles() {
1071 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001072
Wei Wang1dc1ef52017-06-12 11:28:37 -07001073 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1074
1075 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001076 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1077 return;
1078 }
1079
1080 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001081 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001082 if ((d->d_name[0] == '.')
1083 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1084 || (d->d_name[1] == '\0'))) {
1085 continue;
1086 }
1087 const std::string new_path =
1088 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1089 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1090 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1091 printf("\n");
1092 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001093 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001094}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001095
1096static void DumpPacketStats() {
1097 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1098 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1099 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1100 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1101 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1102}
1103
1104static void DumpIpAddrAndRules() {
1105 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1106 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1107 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1108 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1109 RunCommand("IP RULES", {"ip", "rule", "show"});
1110 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1111}
1112
Vishnu Nair64afc022018-02-01 15:29:34 -08001113static void RunDumpsysTextByPriority(const std::string& title, int priority,
1114 std::chrono::milliseconds timeout,
1115 std::chrono::milliseconds service_timeout) {
1116 auto start = std::chrono::steady_clock::now();
Vishnu Naire97d6122018-01-18 13:58:56 -08001117 sp<android::IServiceManager> sm = defaultServiceManager();
1118 Dumpsys dumpsys(sm.get());
Vishnu Naire97d6122018-01-18 13:58:56 -08001119 Vector<String16> args;
1120 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority);
Vishnu Naire97d6122018-01-18 13:58:56 -08001121 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false);
1122 for (const String16& service : services) {
1123 std::string path(title);
1124 path.append(" - ").append(String8(service).c_str());
1125 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1126 size_t bytes_written = 0;
1127 status_t status = dumpsys.startDumpThread(service, args);
1128 if (status == OK) {
1129 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
1130 std::chrono::duration<double> elapsed_seconds;
1131 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout,
1132 /* as_proto = */ false, elapsed_seconds, bytes_written);
1133 section_reporter.setSize(bytes_written);
1134 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds);
1135 bool dump_complete = (status == OK);
1136 dumpsys.stopDumpThread(dump_complete);
1137 }
1138 section_reporter.setStatus(status);
1139
1140 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1141 std::chrono::steady_clock::now() - start);
1142 if (elapsed_duration > timeout) {
1143 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1144 elapsed_duration.count());
1145 break;
1146 }
1147 }
1148}
1149
Vishnu Nair64afc022018-02-01 15:29:34 -08001150static void RunDumpsysText(const std::string& title, int priority,
1151 std::chrono::milliseconds timeout,
1152 std::chrono::milliseconds service_timeout) {
1153 DurationReporter duration_reporter(title);
1154 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1155 fsync(STDOUT_FILENO);
1156 RunDumpsysTextByPriority(title, priority, timeout, service_timeout);
1157}
1158
1159/* Dump all services registered with Normal or Default priority. */
1160static void RunDumpsysTextNormalPriority(const std::string& title,
1161 std::chrono::milliseconds timeout,
1162 std::chrono::milliseconds service_timeout) {
1163 DurationReporter duration_reporter(title);
1164 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str());
1165 fsync(STDOUT_FILENO);
1166 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout,
1167 service_timeout);
1168 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout,
1169 service_timeout);
1170}
1171
1172static void RunDumpsysProto(const std::string& title, int priority,
1173 std::chrono::milliseconds timeout,
1174 std::chrono::milliseconds service_timeout) {
Vishnu Naire97d6122018-01-18 13:58:56 -08001175 sp<android::IServiceManager> sm = defaultServiceManager();
1176 Dumpsys dumpsys(sm.get());
1177 Vector<String16> args;
1178 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority);
1179 DurationReporter duration_reporter(title);
1180
1181 auto start = std::chrono::steady_clock::now();
1182 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true);
1183 for (const String16& service : services) {
1184 std::string path(kProtoPath);
1185 path.append(String8(service).c_str());
1186 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) {
1187 path.append("_CRITICAL");
1188 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) {
1189 path.append("_HIGH");
1190 }
1191 path.append(kProtoExt);
1192 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_);
1193 status_t status = dumpsys.startDumpThread(service, args);
1194 if (status == OK) {
1195 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout);
1196 bool dumpTerminated = (status == OK);
1197 dumpsys.stopDumpThread(dumpTerminated);
1198 }
1199 ZipWriter::FileEntry file_entry;
1200 ds.zip_writer_->GetLastEntry(&file_entry);
1201 section_reporter.setSize(file_entry.compressed_size);
1202 section_reporter.setStatus(status);
1203
1204 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
1205 std::chrono::steady_clock::now() - start);
1206 if (elapsed_duration > timeout) {
1207 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(),
1208 elapsed_duration.count());
1209 break;
1210 }
1211 }
1212}
1213
Vishnu Nair780b1282017-10-10 13:57:24 -07001214// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1215static void RunDumpsysCritical() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001216 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1217 /* timeout= */ 5s, /* service_timeout= */ 500ms);
1218 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL,
1219 /* timeout= */ 5s, /* service_timeout= */ 500ms);
Vishnu Nair780b1282017-10-10 13:57:24 -07001220}
1221
1222// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1223static void RunDumpsysHigh() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001224 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both
1225 // high priority. Reduce timeout once they are able to dump in a shorter time or
1226 // moved to a parallel task.
1227 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1228 /* timeout= */ 90s, /* service_timeout= */ 30s);
1229 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH,
1230 /* timeout= */ 5s, /* service_timeout= */ 1s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001231}
1232
1233// Runs dumpsys on services that must dump but can take up to 10s to dump.
1234static void RunDumpsysNormal() {
Vishnu Nair64afc022018-02-01 15:29:34 -08001235 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s);
1236 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL,
1237 /* timeout= */ 90s, /* service_timeout= */ 10s);
Vishnu Nair780b1282017-10-10 13:57:24 -07001238}
1239
Steven Moreland44cd9482018-01-04 16:24:13 -08001240static void DumpHals() {
1241 using android::sp;
1242 using android::hidl::manager::V1_0::IServiceManager;
1243 using android::hardware::defaultServiceManager;
1244
1245 sp<IServiceManager> sm = defaultServiceManager();
1246 if (sm == nullptr) {
1247 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n");
1248 return;
1249 }
1250
1251 auto ret = sm->list([&](const auto& interfaces) {
1252 for (const std::string& interface : interfaces) {
1253 std::string cleanName = interface;
1254 std::replace_if(cleanName.begin(),
1255 cleanName.end(),
1256 [](char c) {
1257 return !isalnum(c) &&
1258 std::string("@-_:.").find(c) == std::string::npos;
1259 }, '_');
1260 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName;
1261
1262 {
1263 auto fd = android::base::unique_fd(
1264 TEMP_FAILURE_RETRY(open(path.c_str(),
1265 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1266 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1267 if (fd < 0) {
1268 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str());
1269 continue;
1270 }
1271 RunCommandToFd(fd,
1272 "",
Steven Morelandc81cd3c2018-01-18 14:36:26 -08001273 {"lshal", "debug", "-E", interface},
Steven Moreland44cd9482018-01-04 16:24:13 -08001274 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1275
1276 bool empty = 0 == lseek(fd, 0, SEEK_END);
1277 if (!empty) {
1278 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path);
1279 }
1280 }
1281
1282 unlink(path.c_str());
1283 }
1284 });
1285
1286 if (!ret.isOk()) {
1287 MYLOGE("Could not list hals from hwservicemanager.\n");
1288 }
1289}
1290
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001291static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001292 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001294 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001295 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001296 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001297 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001298 DumpFile("MEMORY INFO", "/proc/meminfo");
1299 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001300 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001301 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001302 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1303 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1304 DumpFile("SLAB INFO", "/proc/slabinfo");
1305 DumpFile("ZONEINFO", "/proc/zoneinfo");
1306 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1307 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1308 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001309
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001310 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1311 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1312 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001313
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001314 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001315 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001316 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001317
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001318 if (ds.IsZipping()) {
Steven Moreland44cd9482018-01-04 16:24:13 -08001319 RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::WithTimeout(2).AsRootIfAvailable().Build());
1320 DumpHals();
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001321 } else {
Steven Moreland44cd9482018-01-04 16:24:13 -08001322 RunCommand("HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001323 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001324
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001325 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001326 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001327 struct stat s;
1328 if (stat("/proc/modules", &s) != 0) {
1329 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1330 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001331 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001332 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001333
Siarhei Vishniakou4a0a8772017-12-05 16:22:49 -08001334 if (__android_logger_property_get_bool(
1335 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) {
1336 DoKernelLogcat();
1337 } else {
1338 do_dmesg();
1339 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001340
Felipe Lemef0292972016-11-22 13:57:05 -08001341 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001342 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1343 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001344 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001345
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001346 /* Dump Bluetooth HCI logs */
1347 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001348
Felipe Leme9a523ae2016-10-20 15:10:33 -07001349 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001350 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001351 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001352 }
1353
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001354 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001355
Felipe Lemee184f662016-10-27 10:04:47 -07001356 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001357
Narayan Kamath8f788292017-05-25 13:20:39 +01001358 // NOTE: tombstones are always added as separate entries in the zip archive
1359 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001360 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1361 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001362 if (!tombstones_dumped) {
1363 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001364 }
1365
Jayachandran Ca94c7172017-06-10 15:08:12 -07001366 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001367
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001368 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001369
Jayachandran Ca94c7172017-06-10 15:08:12 -07001370 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001371
1372 dump_route_tables();
1373
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001374 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1375 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1376 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001377
Vishnu Nair780b1282017-10-10 13:57:24 -07001378 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001379
Elliott Hughes23ccc622017-02-28 10:14:22 -08001380 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001381
Jin Qianf334d662017-10-10 14:41:37 -07001382 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001383
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001384 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001385
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001386 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001387
Colin Crossf45fa6b2012-03-26 12:38:26 -07001388 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001389 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1390 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1391 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1392 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1393 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001394
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001395 /* Add window and surface trace files. */
1396 if (!PropertiesHelper::IsUserBuild()) {
1397 ds.AddDir(WMTRACE_DATA_DIR, false);
1398 }
1399
Felipe Leme6f674ae2016-11-18 17:10:33 -08001400 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001401
Steven Moreland7440ddb2016-12-15 16:13:39 -08001402 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001403 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1404 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001405 // su does not exist on user builds, so try running without it.
1406 // This way any implementations of vril-dump that do not require
1407 // root can run on user builds.
1408 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001409 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001410 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001411 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001412 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001413 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001414 }
1415
Felipe Lemed8b94e52016-12-08 10:21:44 -08001416 printf("========================================================\n");
1417 printf("== Android Framework Services\n");
1418 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001419
Vishnu Nair780b1282017-10-10 13:57:24 -07001420 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001421
Felipe Lemed8b94e52016-12-08 10:21:44 -08001422 printf("========================================================\n");
1423 printf("== Checkins\n");
1424 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001425
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001426 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1427 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1428 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1429 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1430 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1431 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001432
Felipe Lemed8b94e52016-12-08 10:21:44 -08001433 printf("========================================================\n");
1434 printf("== Running Application Activities\n");
1435 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001436
Winson Chung1434a5c2017-02-28 17:09:24 -08001437 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001438
Felipe Lemed8b94e52016-12-08 10:21:44 -08001439 printf("========================================================\n");
1440 printf("== Running Application Services\n");
1441 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001442
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001443 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001444
Felipe Lemed8b94e52016-12-08 10:21:44 -08001445 printf("========================================================\n");
1446 printf("== Running Application Providers\n");
1447 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001448
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001449 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001450
Adrian Roos8b397ab2017-04-04 16:35:44 -07001451 printf("========================================================\n");
1452 printf("== Dropbox crashes\n");
1453 printf("========================================================\n");
1454
1455 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1456 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1457
Felipe Lemed8b94e52016-12-08 10:21:44 -08001458 printf("========================================================\n");
1459 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1460 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1461 printf("========================================================\n");
1462 printf("== dumpstate: done (id %d)\n", ds.id_);
1463 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001464}
1465
mukesh agrawal253dad42018-01-23 21:59:59 -08001466// This method collects common dumpsys for telephony and wifi
1467static void DumpstateRadioCommon() {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001468 DumpIpTablesAsRoot();
1469
1470 if (!DropRootUser()) {
1471 return;
1472 }
1473
1474 do_dmesg();
1475 DoLogcat();
1476 DumpPacketStats();
1477 DoKmsg();
1478 DumpIpAddrAndRules();
1479 dump_route_tables();
1480
1481 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1482 CommandOptions::WithTimeout(10).Build());
mukesh agrawal253dad42018-01-23 21:59:59 -08001483}
1484
1485// This method collects dumpsys for telephony debugging only
1486static void DumpstateTelephonyOnly() {
1487 DurationReporter duration_reporter("DUMPSTATE");
1488
1489 DumpstateRadioCommon();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001490
1491 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1492
1493 printf("========================================================\n");
1494 printf("== Android Framework Services\n");
1495 printf("========================================================\n");
1496
Vishnu Nair652cc802017-11-30 15:18:30 -08001497 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1498 SEC_TO_MSEC(10));
1499 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(),
1500 SEC_TO_MSEC(10));
Jayachandran Ca94c7172017-06-10 15:08:12 -07001501
1502 printf("========================================================\n");
1503 printf("== Running Application Services\n");
1504 printf("========================================================\n");
1505
1506 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1507
1508 printf("========================================================\n");
1509 printf("== dumpstate: done (id %d)\n", ds.id_);
1510 printf("========================================================\n");
1511}
1512
mukesh agrawal253dad42018-01-23 21:59:59 -08001513// This method collects dumpsys for wifi debugging only
1514static void DumpstateWifiOnly() {
1515 DurationReporter duration_reporter("DUMPSTATE");
1516
1517 DumpstateRadioCommon();
1518
1519 printf("========================================================\n");
1520 printf("== Android Framework Services\n");
1521 printf("========================================================\n");
1522
1523 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1524 SEC_TO_MSEC(10));
1525 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1526 SEC_TO_MSEC(10));
1527
1528 printf("========================================================\n");
1529 printf("== dumpstate: done (id %d)\n", ds.id_);
1530 printf("========================================================\n");
1531}
1532
Felipe Leme6f674ae2016-11-18 17:10:33 -08001533void Dumpstate::DumpstateBoard() {
1534 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001535 printf("========================================================\n");
1536 printf("== Board\n");
1537 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001538
Chris Phoenix69d92212017-01-24 23:01:13 -08001539 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001540 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001541 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001542 return;
1543 }
1544
1545 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001546 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001547 return;
1548 }
1549
Jie Song9fbfad02017-06-20 16:29:42 -07001550 std::string path[NUM_OF_DUMPS];
1551 android::base::unique_fd fd[NUM_OF_DUMPS];
1552 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001553
Jie Song9fbfad02017-06-20 16:29:42 -07001554 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1555 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1556 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1557
1558 fd[i] = android::base::unique_fd(
1559 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1560 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1561 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1562 if (fd[i] < 0) {
1563 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1564 return;
1565 } else {
1566 numFds++;
1567 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001568 }
1569
Jie Song9fbfad02017-06-20 16:29:42 -07001570 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001571 if (handle == nullptr) {
1572 MYLOGE("Could not create native_handle\n");
1573 return;
1574 }
Jie Song9fbfad02017-06-20 16:29:42 -07001575
1576 for (int i = 0; i < numFds; i++) {
1577 handle->data[i] = fd[i].release();
1578 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001579
Felipe Lemef0292972016-11-22 13:57:05 -08001580 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001581 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1582 if (!status.isOk()) {
1583 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1584 native_handle_close(handle);
1585 native_handle_delete(handle);
1586 return;
1587 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001588
Jie Song9fbfad02017-06-20 16:29:42 -07001589 for (int i = 0; i < numFds; i++) {
1590 struct stat s;
1591 if (fstat(handle->data[i], &s) == -1) {
1592 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1593 } else if (s.st_size > 0) {
1594 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1595 } else {
1596 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1597 }
1598 }
1599
Felipe Lemed8b94e52016-12-08 10:21:44 -08001600 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001601
1602 native_handle_close(handle);
1603 native_handle_delete(handle);
1604
Jie Song9fbfad02017-06-20 16:29:42 -07001605 for (int i = 0; i < numFds; i++) {
1606 if (remove(path[i].c_str()) != 0) {
1607 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1608 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001609 }
1610}
1611
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001612static void ShowUsageAndExit(int exitCode = 1) {
1613 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001614 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001615 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1616 " -h: display this help message\n"
1617 " -b: play sound file instead of vibrate, at beginning of job\n"
1618 " -e: play sound file instead of vibrate, at end of job\n"
1619 " -o: write to file (instead of stdout)\n"
1620 " -d: append date to filename (requires -o)\n"
1621 " -p: capture screenshot to filename.png (requires -o)\n"
1622 " -z: generate zipped file (requires -o)\n"
1623 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001624 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001625 " -q: disable vibrate\n"
1626 " -B: send broadcast when finished (requires -o)\n"
1627 " -P: send broadcast when started and update system properties on "
1628 "progress (requires -o and -B)\n"
1629 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1630 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001631 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001632 exit(exitCode);
1633}
1634
1635static void ExitOnInvalidArgs() {
1636 fprintf(stderr, "invalid combination of args\n");
1637 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001638}
1639
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001640static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001641 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001642}
1643
Wei Liuf87959e2016-08-26 14:51:42 -07001644static void register_sig_handler() {
1645 struct sigaction sa;
1646 sigemptyset(&sa.sa_mask);
1647 sa.sa_flags = 0;
1648 sa.sa_handler = sig_handler;
1649 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1650 sigaction(SIGSEGV, &sa, NULL); // segment fault
1651 sigaction(SIGINT, &sa, NULL); // ctrl-c
1652 sigaction(SIGTERM, &sa, NULL); // killed
1653 sigaction(SIGQUIT, &sa, NULL); // quit
1654}
1655
Felipe Leme1d486fe2016-10-14 18:06:47 -07001656bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001657 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001658 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001659 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001660 // Final timestamp
1661 char date[80];
1662 time_t the_real_now_please_stand_up = time(nullptr);
1663 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001664 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001665 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001666
Felipe Leme9a523ae2016-10-20 15:10:33 -07001667 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001668 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001669 return false;
1670 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001671 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001672 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001673 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001674 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001675
Felipe Leme0f3fb202016-06-10 17:10:53 -07001676 // Add log file (which contains stderr output) to zip...
1677 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001678 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001679 MYLOGE("Failed to add dumpstate log to .zip file\n");
1680 return false;
1681 }
1682 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001683 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001684 fprintf(stderr, "\n");
1685
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001686 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001687 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001688 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001689 return false;
1690 }
1691
Felipe Leme1d486fe2016-10-14 18:06:47 -07001692 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1693 ds.zip_file.reset(nullptr);
1694
Felipe Lemee9d2c542016-11-15 11:48:26 -08001695 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1696 if (remove(tmp_path_.c_str()) != 0) {
1697 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001698 }
1699
Felipe Leme1e9edc62015-12-21 16:02:13 -08001700 return true;
1701}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001702
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001703static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001704 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1705 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001706 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001707 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001708 return NULL;
1709 }
1710
1711 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001712 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001713
1714 std::vector<uint8_t> buffer(65536);
1715 while (1) {
1716 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1717 if (bytes_read == 0) {
1718 break;
1719 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001720 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001721 return NULL;
1722 }
1723
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001724 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001725 }
1726
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001727 uint8_t hash[SHA256_DIGEST_LENGTH];
1728 SHA256_Final(hash, &ctx);
1729
1730 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1731 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001732 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001733 }
1734 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1735 return std::string(hash_buffer);
1736}
1737
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001738static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1739 // clang-format off
1740 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1741 "--receiver-foreground", "--receiver-include-background", "-a", action};
1742 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001743
1744 am.insert(am.end(), args.begin(), args.end());
1745
Felipe Leme8d2410e2017-02-08 09:46:08 -08001746 RunCommand("", am,
1747 CommandOptions::WithTimeout(20)
1748 .Log("Sending broadcast: '%s'\n")
1749 .Always()
1750 .DropRoot()
1751 .RedirectStderr()
1752 .Build());
1753}
1754
Felipe Leme35b8cf12017-02-10 15:47:29 -08001755static void Vibrate(int duration_ms) {
1756 // clang-format off
1757 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1758 CommandOptions::WithTimeout(10)
1759 .Log("Vibrate: '%s'\n")
1760 .Always()
1761 .Build());
1762 // clang-format on
1763}
1764
Vishnu Nair20cf5032018-01-05 13:15:49 -08001765/** Main entry point for dumpstate. */
1766int run_main(int argc, char* argv[]) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001767 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001768 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001769 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001770 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001771 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001772 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001773 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001774 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001775 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001776 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001777 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001778 bool telephony_only = false;
mukesh agrawal253dad42018-01-23 21:59:59 -08001779 bool wifi_only = false;
Vishnu Nair20cf5032018-01-05 13:15:49 -08001780 int dup_stdout_fd;
1781 int dup_stderr_fd;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001782
Colin Crossf45fa6b2012-03-26 12:38:26 -07001783 /* set as high priority, and protect from OOM killer */
1784 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001785
Felipe Lemed071c682016-10-20 16:48:00 -07001786 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001787 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001788 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001789 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001790 } else {
1791 /* fallback to kernels <= 2.6.35 */
1792 oom_adj = fopen("/proc/self/oom_adj", "we");
1793 if (oom_adj) {
1794 fputs("-17", oom_adj);
1795 fclose(oom_adj);
1796 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001797 }
1798
Jeff Brown1dc94e32014-09-11 14:15:27 -07001799 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001801 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001803 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001804 case 'd': do_add_date = 1; break;
1805 case 'z': do_zip_file = 1; break;
1806 case 'o': use_outfile = optarg; break;
1807 case 's': use_socket = 1; break;
1808 case 'S': use_control_socket = 1; break;
1809 case 'v': show_header_only = true; break;
1810 case 'q': do_vibrate = 0; break;
1811 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001812 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001813 case 'R': is_remote_mode = 1; break;
1814 case 'B': do_broadcast = 1; break;
1815 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001816 case 'h':
1817 ShowUsageAndExit(0);
1818 break;
1819 default:
1820 fprintf(stderr, "Invalid option: %c\n", c);
1821 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001822 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001823 }
1824 }
1825
Felipe Lemed071c682016-10-20 16:48:00 -07001826 // TODO: use helper function to convert argv into a string
1827 for (int i = 0; i < argc; i++) {
1828 ds.args_ += argv[i];
1829 if (i < argc - 1) {
1830 ds.args_ += " ";
1831 }
1832 }
1833
1834 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001835 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001836 // Framework uses a system property to override some command-line args.
1837 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001838 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001839 // Currently, the dumpstate binder is only used by Shell to update progress.
1840 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001841 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001842 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001843 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001844 do_vibrate = 0;
1845 is_remote_mode = 1;
1846 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001847 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001848 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001849 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001850 } else if (ds.extra_options_ == "bugreporttelephony") {
1851 telephony_only = true;
mukesh agrawal253dad42018-01-23 21:59:59 -08001852 } else if (ds.extra_options_ == "bugreportwifi") {
1853 wifi_only = true;
1854 do_zip_file = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001855 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001856 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001857 }
1858 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001859 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001860 }
1861
Naveen Kallab53a1c92017-03-16 18:17:25 -07001862 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1863 if (!ds.notification_title.empty()) {
1864 // Reset the property
1865 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1866
1867 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1868 if (!ds.notification_description.empty()) {
1869 // Reset the property
1870 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1871 }
1872 MYLOGD("notification (title: %s, description: %s)\n",
1873 ds.notification_title.c_str(), ds.notification_description.c_str());
1874 }
1875
Felipe Leme9a523ae2016-10-20 15:10:33 -07001876 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001877 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001878 }
1879
Felipe Leme2628e9e2016-04-12 16:36:51 -07001880 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001881 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001882 }
1883
Felipe Leme9a523ae2016-10-20 15:10:33 -07001884 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001885 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001886 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001887
Felipe Leme9a523ae2016-10-20 15:10:33 -07001888 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001889 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001890 }
1891
Felipe Lemed071c682016-10-20 16:48:00 -07001892 if (ds.version_ == VERSION_DEFAULT) {
1893 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001894 }
1895
Vishnu Nair64afc022018-02-01 15:29:34 -08001896 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1897 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1898 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1899 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001900 exit(1);
1901 }
1902
1903 if (show_header_only) {
1904 ds.PrintHeader();
1905 exit(0);
1906 }
1907
Felipe Leme7447d7c2016-11-03 18:12:22 -07001908 /* redirect output if needed */
1909 bool is_redirecting = !use_socket && use_outfile;
1910
1911 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1912 std::string stats_path =
1913 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1914 : "";
1915 ds.progress_.reset(new Progress(stats_path));
1916
Felipe Lemed071c682016-10-20 16:48:00 -07001917 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001918 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001919 ds.id_ = ++last_id;
1920 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1921
1922 MYLOGI("begin\n");
1923
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001924 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001925
Felipe Leme75876a22016-10-27 16:31:27 -07001926 if (do_start_service) {
1927 MYLOGI("Starting 'dumpstate' service\n");
1928 android::status_t ret;
1929 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1930 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1931 }
1932 }
1933
Felipe Lemef0292972016-11-22 13:57:05 -08001934 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001935 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1936 }
1937
Felipe Leme7447d7c2016-11-03 18:12:22 -07001938 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001939 ds.extra_options_.c_str());
1940
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001941 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001942
Felipe Leme9a523ae2016-10-20 15:10:33 -07001943 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001944
Christopher Ferrised9354f2014-10-01 17:35:01 -07001945 // If we are going to use a socket, do it as early as possible
1946 // to avoid timeouts from bugreport.
1947 if (use_socket) {
1948 redirect_to_socket(stdout, "dumpstate");
1949 }
1950
Felipe Leme2628e9e2016-04-12 16:36:51 -07001951 if (use_control_socket) {
1952 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001953 ds.control_socket_fd_ = open_socket("dumpstate");
1954 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001955 }
1956
Felipe Leme71bbfc52015-11-23 14:14:51 -08001957 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001958 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001959 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001960 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001961 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1962 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001963 if (do_add_date) {
1964 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001965 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001966 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001967 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001968 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001969 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001970
1971 if (telephony_only) {
1972 ds.base_name_ += "-telephony";
mukesh agrawal253dad42018-01-23 21:59:59 -08001973 } else if (wifi_only) {
1974 ds.base_name_ += "-wifi";
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001975 }
1976
Felipe Leme71bbfc52015-11-23 14:14:51 -08001977 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001978 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001979 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001980 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001981 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001982
Felipe Lemee844a9d2016-09-21 15:01:39 -07001983 MYLOGD(
1984 "Bugreport dir: %s\n"
1985 "Base name: %s\n"
1986 "Suffix: %s\n"
1987 "Log path: %s\n"
1988 "Temporary path: %s\n"
1989 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001990 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1991 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001992
Felipe Leme1e9edc62015-12-21 16:02:13 -08001993 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001994 ds.path_ = ds.GetPath(".zip");
1995 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1996 create_parent_dirs(ds.path_.c_str());
1997 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001998 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001999 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002000 do_zip_file = 0;
2001 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002002 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002003 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002004 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08002005 }
2006
Felipe Leme9a523ae2016-10-20 15:10:33 -07002007 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002008 if (do_broadcast) {
2009 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002010
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002011 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002012 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002013 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002014 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002015 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002016 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002017 };
2018 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002019 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002020 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002021 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002022 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002023 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002024 }
2025 }
2026
Nick Kralevichf3599b32016-01-25 15:05:16 -08002027 /* read /proc/cmdline before dropping root */
2028 FILE *cmdline = fopen("/proc/cmdline", "re");
2029 if (cmdline) {
2030 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2031 fclose(cmdline);
2032 }
2033
John Michelau1f794c42012-09-17 11:20:19 -05002034 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002035 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002036 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002037
Felipe Leme9a523ae2016-10-20 15:10:33 -07002038 if (do_fb && ds.do_early_screenshot_) {
2039 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002040 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002041 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002042 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002043 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002044 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002045 }
2046 }
2047
Felipe Leme1e9edc62015-12-21 16:02:13 -08002048 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002049 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2050 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002051 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002052 }
2053 }
2054
Felipe Leme71bbfc52015-11-23 14:14:51 -08002055 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002056 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002057 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2058 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2059 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2060 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002061 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002062 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002063 /* TODO: rather than generating a text file now and zipping it later,
2064 it would be more efficient to redirect stdout to the zip entry
2065 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07002066 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2067 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002068 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002069 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002070 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002071 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002072
2073 // Don't buffer stdout
2074 setvbuf(stdout, nullptr, _IONBF, 0);
2075
Felipe Leme608385d2016-02-01 10:35:38 -08002076 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2077 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002078 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002079 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002080
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002081 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002082 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002083 ds.DumpstateBoard();
mukesh agrawal253dad42018-01-23 21:59:59 -08002084 } else if (wifi_only) {
2085 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002086 } else {
2087 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
2088 // First try to dump anrd trace if the daemon is running. Otherwise, dump
2089 // the raw trace.
2090 if (!dump_anrd_trace()) {
2091 dump_systrace();
2092 }
2093
2094 // Invoking the following dumpsys calls before dump_traces() to try and
2095 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07002096 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002097
2098 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
2099 dump_raft();
2100
2101 /* collect stack traces from Dalvik and native processes (needs root) */
2102 dump_traces_path = dump_traces();
2103
2104 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01002105 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
2106 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01002107
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002108 ds.AddDir(RECOVERY_DIR, true);
2109 ds.AddDir(RECOVERY_DATA_DIR, true);
2110 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2111 if (!PropertiesHelper::IsUserBuild()) {
2112 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2113 ds.AddDir(PROFILE_DATA_DIR_REF, true);
2114 }
2115 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002116 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002117
2118 // Capture any IPSec policies in play. No keys are exposed here.
2119 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
2120 CommandOptions::WithTimeout(10).Build());
2121
2122 // Run ss as root so we can see socket marks.
2123 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
2124 CommandOptions::WithTimeout(10).Build());
2125
Jin Qian3cd671e2017-09-27 18:50:04 -07002126 // Run iotop as root to show top 100 IO threads
2127 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2128
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002129 if (!DropRootUser()) {
2130 return -1;
2131 }
2132
2133 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002134 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002135
Felipe Leme55b42a62015-11-10 17:39:08 -08002136 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002137 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002138 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002139 }
2140
Felipe Leme6e01fa62015-11-11 19:35:14 -08002141 /* rename or zip the (now complete) .tmp file to its final location */
2142 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002143
2144 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002145 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07002146 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08002147 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002148 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002149 /* must whitelist which characters are allowed, otherwise it could cross directories */
2150 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002151 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002152 change_suffix = true;
2153 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002154 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08002155 }
2156 }
2157 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002158 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2159 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07002160 if (!ds.screenshot_path_.empty()) {
2161 std::string new_screenshot_path = ds.GetPath(".png");
2162 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2163 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2164 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08002165 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002166 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08002167 }
2168 }
2169 }
2170
Felipe Leme6e01fa62015-11-11 19:35:14 -08002171 bool do_text_file = true;
2172 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07002173 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002174 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002175 do_text_file = true;
2176 } else {
2177 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08002178 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07002179 std::string new_path = ds.GetPath(".zip");
2180 if (ds.path_ != new_path) {
2181 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2182 if (rename(ds.path_.c_str(), new_path.c_str())) {
2183 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002184 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08002185 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002186 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08002187 }
2188 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002189 }
2190 }
2191 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002192 ds.path_ = ds.GetPath(".txt");
2193 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
2194 ds.tmp_path_.c_str());
2195 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2196 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002197 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002198 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08002199 }
2200 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002201 if (use_control_socket) {
2202 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002203 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002204 "FAIL:could not create zip file, check %s "
2205 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002206 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002207 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002208 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002209 }
2210 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002211 }
2212
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002213 /* vibrate a few but shortly times to let user know it's finished */
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002214 if (do_vibrate) {
2215 for (int i = 0; i < 3; i++) {
2216 Vibrate(75);
2217 usleep((75 + 50) * 1000);
2218 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002219 }
2220
Jeff Brown1dc94e32014-09-11 14:15:27 -07002221 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002222 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002223 if (!ds.path_.empty()) {
2224 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002225 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002226
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002227 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002228 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002229 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002230 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002231 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002232 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2233 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002234 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002235 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002236 if (do_fb) {
2237 am_args.push_back("--es");
2238 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002239 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002240 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002241 if (!ds.notification_title.empty()) {
2242 am_args.push_back("--es");
2243 am_args.push_back("android.intent.extra.TITLE");
2244 am_args.push_back(ds.notification_title);
2245 if (!ds.notification_description.empty()) {
2246 am_args.push_back("--es");
2247 am_args.push_back("android.intent.extra.DESCRIPTION");
2248 am_args.push_back(ds.notification_description);
2249 }
2250 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002251 if (is_remote_mode) {
2252 am_args.push_back("--es");
2253 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002254 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002255 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2256 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002257 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002258 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002259 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002260 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002261 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002262 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002263 }
2264
Felipe Leme7447d7c2016-11-03 18:12:22 -07002265 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2266 ds.progress_->GetInitialMax());
2267 ds.progress_->Save();
2268 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002269
Felipe Leme107a05f2016-03-08 15:11:15 -08002270 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002271 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002272 }
2273
Felipe Leme9a523ae2016-10-20 15:10:33 -07002274 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002275 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002276 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002277 }
2278
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002279 CloseDumpFds(tombstone_data.get());
2280 CloseDumpFds(anr_data.get());
2281
Colin Crossf45fa6b2012-03-26 12:38:26 -07002282 return 0;
2283}