blob: 371533c4db48b07105b74f1890ac6e55b0088c77 [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
Narayan Kamath3f31b632018-02-22 19:42:36 +0000204 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");
Sooraj Sasindran963b04f2018-03-09 13:26:39 -08001509 printf("== Checkins\n");
1510 printf("========================================================\n");
1511
1512 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1513
1514 printf("========================================================\n");
Jayachandran Ca94c7172017-06-10 15:08:12 -07001515 printf("== dumpstate: done (id %d)\n", ds.id_);
1516 printf("========================================================\n");
1517}
1518
mukesh agrawal253dad42018-01-23 21:59:59 -08001519// This method collects dumpsys for wifi debugging only
1520static void DumpstateWifiOnly() {
1521 DurationReporter duration_reporter("DUMPSTATE");
1522
1523 DumpstateRadioCommon();
1524
1525 printf("========================================================\n");
1526 printf("== Android Framework Services\n");
1527 printf("========================================================\n");
1528
1529 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(),
1530 SEC_TO_MSEC(10));
1531 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(),
1532 SEC_TO_MSEC(10));
1533
1534 printf("========================================================\n");
1535 printf("== dumpstate: done (id %d)\n", ds.id_);
1536 printf("========================================================\n");
1537}
1538
Felipe Leme6f674ae2016-11-18 17:10:33 -08001539void Dumpstate::DumpstateBoard() {
1540 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001541 printf("========================================================\n");
1542 printf("== Board\n");
1543 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001544
Chris Phoenix69d92212017-01-24 23:01:13 -08001545 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001546 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001547 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001548 return;
1549 }
1550
1551 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001552 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001553 return;
1554 }
1555
Jie Song9fbfad02017-06-20 16:29:42 -07001556 std::string path[NUM_OF_DUMPS];
1557 android::base::unique_fd fd[NUM_OF_DUMPS];
1558 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001559
Jie Song9fbfad02017-06-20 16:29:42 -07001560 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1561 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1562 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1563
1564 fd[i] = android::base::unique_fd(
1565 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1566 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1567 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1568 if (fd[i] < 0) {
1569 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1570 return;
1571 } else {
1572 numFds++;
1573 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001574 }
1575
Jie Song9fbfad02017-06-20 16:29:42 -07001576 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001577 if (handle == nullptr) {
1578 MYLOGE("Could not create native_handle\n");
1579 return;
1580 }
Jie Song9fbfad02017-06-20 16:29:42 -07001581
1582 for (int i = 0; i < numFds; i++) {
1583 handle->data[i] = fd[i].release();
1584 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001585
Felipe Lemef0292972016-11-22 13:57:05 -08001586 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001587 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1588 if (!status.isOk()) {
1589 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1590 native_handle_close(handle);
1591 native_handle_delete(handle);
1592 return;
1593 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001594
Jie Song9fbfad02017-06-20 16:29:42 -07001595 for (int i = 0; i < numFds; i++) {
1596 struct stat s;
1597 if (fstat(handle->data[i], &s) == -1) {
1598 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1599 } else if (s.st_size > 0) {
1600 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1601 } else {
1602 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1603 }
1604 }
1605
Felipe Lemed8b94e52016-12-08 10:21:44 -08001606 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001607
1608 native_handle_close(handle);
1609 native_handle_delete(handle);
1610
Jie Song9fbfad02017-06-20 16:29:42 -07001611 for (int i = 0; i < numFds; i++) {
1612 if (remove(path[i].c_str()) != 0) {
1613 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1614 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001615 }
1616}
1617
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001618static void ShowUsageAndExit(int exitCode = 1) {
1619 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001620 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001621 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1622 " -h: display this help message\n"
1623 " -b: play sound file instead of vibrate, at beginning of job\n"
1624 " -e: play sound file instead of vibrate, at end of job\n"
1625 " -o: write to file (instead of stdout)\n"
1626 " -d: append date to filename (requires -o)\n"
1627 " -p: capture screenshot to filename.png (requires -o)\n"
1628 " -z: generate zipped file (requires -o)\n"
1629 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001630 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001631 " -q: disable vibrate\n"
1632 " -B: send broadcast when finished (requires -o)\n"
1633 " -P: send broadcast when started and update system properties on "
1634 "progress (requires -o and -B)\n"
1635 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1636 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001637 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001638 exit(exitCode);
1639}
1640
1641static void ExitOnInvalidArgs() {
1642 fprintf(stderr, "invalid combination of args\n");
1643 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001644}
1645
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001646static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001647 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001648}
1649
Wei Liuf87959e2016-08-26 14:51:42 -07001650static void register_sig_handler() {
1651 struct sigaction sa;
1652 sigemptyset(&sa.sa_mask);
1653 sa.sa_flags = 0;
1654 sa.sa_handler = sig_handler;
1655 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1656 sigaction(SIGSEGV, &sa, NULL); // segment fault
1657 sigaction(SIGINT, &sa, NULL); // ctrl-c
1658 sigaction(SIGTERM, &sa, NULL); // killed
1659 sigaction(SIGQUIT, &sa, NULL); // quit
1660}
1661
Felipe Leme1d486fe2016-10-14 18:06:47 -07001662bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001663 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001664 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001665 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001666 // Final timestamp
1667 char date[80];
1668 time_t the_real_now_please_stand_up = time(nullptr);
1669 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001670 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001671 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001672
Felipe Leme9a523ae2016-10-20 15:10:33 -07001673 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001674 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001675 return false;
1676 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001677 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001678 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001679 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001680 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001681
Felipe Leme0f3fb202016-06-10 17:10:53 -07001682 // Add log file (which contains stderr output) to zip...
1683 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001684 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001685 MYLOGE("Failed to add dumpstate log to .zip file\n");
1686 return false;
1687 }
1688 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001689 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001690 fprintf(stderr, "\n");
1691
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001692 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001693 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001694 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001695 return false;
1696 }
1697
Felipe Leme1d486fe2016-10-14 18:06:47 -07001698 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1699 ds.zip_file.reset(nullptr);
1700
Felipe Lemee9d2c542016-11-15 11:48:26 -08001701 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1702 if (remove(tmp_path_.c_str()) != 0) {
1703 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001704 }
1705
Felipe Leme1e9edc62015-12-21 16:02:13 -08001706 return true;
1707}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001708
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001709static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001710 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1711 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001712 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001713 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001714 return NULL;
1715 }
1716
1717 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001718 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001719
1720 std::vector<uint8_t> buffer(65536);
1721 while (1) {
1722 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1723 if (bytes_read == 0) {
1724 break;
1725 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001726 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001727 return NULL;
1728 }
1729
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001730 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001731 }
1732
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001733 uint8_t hash[SHA256_DIGEST_LENGTH];
1734 SHA256_Final(hash, &ctx);
1735
1736 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1737 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001738 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001739 }
1740 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1741 return std::string(hash_buffer);
1742}
1743
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001744static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1745 // clang-format off
1746 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1747 "--receiver-foreground", "--receiver-include-background", "-a", action};
1748 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001749
1750 am.insert(am.end(), args.begin(), args.end());
1751
Felipe Leme8d2410e2017-02-08 09:46:08 -08001752 RunCommand("", am,
1753 CommandOptions::WithTimeout(20)
1754 .Log("Sending broadcast: '%s'\n")
1755 .Always()
1756 .DropRoot()
1757 .RedirectStderr()
1758 .Build());
1759}
1760
Felipe Leme35b8cf12017-02-10 15:47:29 -08001761static void Vibrate(int duration_ms) {
1762 // clang-format off
1763 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1764 CommandOptions::WithTimeout(10)
1765 .Log("Vibrate: '%s'\n")
1766 .Always()
1767 .Build());
1768 // clang-format on
1769}
1770
Vishnu Nair20cf5032018-01-05 13:15:49 -08001771/** Main entry point for dumpstate. */
1772int run_main(int argc, char* argv[]) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001773 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001774 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001775 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001776 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001777 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001778 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001779 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001780 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001781 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001782 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001783 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001784 bool telephony_only = false;
mukesh agrawal253dad42018-01-23 21:59:59 -08001785 bool wifi_only = false;
Vishnu Nair20cf5032018-01-05 13:15:49 -08001786 int dup_stdout_fd;
1787 int dup_stderr_fd;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001788
Colin Crossf45fa6b2012-03-26 12:38:26 -07001789 /* set as high priority, and protect from OOM killer */
1790 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001791
Felipe Lemed071c682016-10-20 16:48:00 -07001792 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001793 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001794 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001795 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001796 } else {
1797 /* fallback to kernels <= 2.6.35 */
1798 oom_adj = fopen("/proc/self/oom_adj", "we");
1799 if (oom_adj) {
1800 fputs("-17", oom_adj);
1801 fclose(oom_adj);
1802 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001803 }
1804
Jeff Brown1dc94e32014-09-11 14:15:27 -07001805 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001806 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001807 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001808 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001809 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001810 case 'd': do_add_date = 1; break;
1811 case 'z': do_zip_file = 1; break;
1812 case 'o': use_outfile = optarg; break;
1813 case 's': use_socket = 1; break;
1814 case 'S': use_control_socket = 1; break;
1815 case 'v': show_header_only = true; break;
1816 case 'q': do_vibrate = 0; break;
1817 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001818 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001819 case 'R': is_remote_mode = 1; break;
1820 case 'B': do_broadcast = 1; break;
1821 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001822 case 'h':
1823 ShowUsageAndExit(0);
1824 break;
1825 default:
1826 fprintf(stderr, "Invalid option: %c\n", c);
1827 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001828 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001829 }
1830 }
1831
Felipe Lemed071c682016-10-20 16:48:00 -07001832 // TODO: use helper function to convert argv into a string
1833 for (int i = 0; i < argc; i++) {
1834 ds.args_ += argv[i];
1835 if (i < argc - 1) {
1836 ds.args_ += " ";
1837 }
1838 }
1839
1840 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001841 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001842 // Framework uses a system property to override some command-line args.
1843 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001844 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001845 // Currently, the dumpstate binder is only used by Shell to update progress.
1846 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001847 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001848 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001849 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001850 do_vibrate = 0;
1851 is_remote_mode = 1;
1852 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001853 } else if (ds.extra_options_ == "bugreportwear") {
lingfan44612512018-02-27 11:32:11 -08001854 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001855 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001856 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001857 } else if (ds.extra_options_ == "bugreporttelephony") {
1858 telephony_only = true;
mukesh agrawal253dad42018-01-23 21:59:59 -08001859 } else if (ds.extra_options_ == "bugreportwifi") {
1860 wifi_only = true;
1861 do_zip_file = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001862 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001863 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001864 }
1865 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001866 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001867 }
1868
Naveen Kallab53a1c92017-03-16 18:17:25 -07001869 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1870 if (!ds.notification_title.empty()) {
1871 // Reset the property
1872 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1873
1874 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1875 if (!ds.notification_description.empty()) {
1876 // Reset the property
1877 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1878 }
1879 MYLOGD("notification (title: %s, description: %s)\n",
1880 ds.notification_title.c_str(), ds.notification_description.c_str());
1881 }
1882
Felipe Leme9a523ae2016-10-20 15:10:33 -07001883 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001884 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001885 }
1886
Felipe Leme2628e9e2016-04-12 16:36:51 -07001887 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001888 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001889 }
1890
Felipe Leme9a523ae2016-10-20 15:10:33 -07001891 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001892 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001893 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001894
Felipe Leme9a523ae2016-10-20 15:10:33 -07001895 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001896 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001897 }
1898
Felipe Lemed071c682016-10-20 16:48:00 -07001899 if (ds.version_ == VERSION_DEFAULT) {
1900 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001901 }
1902
Vishnu Nair64afc022018-02-01 15:29:34 -08001903 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1904 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1905 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1906 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001907 exit(1);
1908 }
1909
1910 if (show_header_only) {
1911 ds.PrintHeader();
1912 exit(0);
1913 }
1914
Felipe Leme7447d7c2016-11-03 18:12:22 -07001915 /* redirect output if needed */
1916 bool is_redirecting = !use_socket && use_outfile;
1917
1918 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1919 std::string stats_path =
1920 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1921 : "";
1922 ds.progress_.reset(new Progress(stats_path));
1923
Felipe Lemed071c682016-10-20 16:48:00 -07001924 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001925 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001926 ds.id_ = ++last_id;
1927 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1928
1929 MYLOGI("begin\n");
1930
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001931 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001932
Felipe Leme75876a22016-10-27 16:31:27 -07001933 if (do_start_service) {
1934 MYLOGI("Starting 'dumpstate' service\n");
1935 android::status_t ret;
1936 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1937 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1938 }
1939 }
1940
Felipe Lemef0292972016-11-22 13:57:05 -08001941 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001942 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1943 }
1944
Felipe Leme7447d7c2016-11-03 18:12:22 -07001945 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001946 ds.extra_options_.c_str());
1947
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001948 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001949
Felipe Leme9a523ae2016-10-20 15:10:33 -07001950 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001951
Christopher Ferrised9354f2014-10-01 17:35:01 -07001952 // If we are going to use a socket, do it as early as possible
1953 // to avoid timeouts from bugreport.
1954 if (use_socket) {
1955 redirect_to_socket(stdout, "dumpstate");
1956 }
1957
Felipe Leme2628e9e2016-04-12 16:36:51 -07001958 if (use_control_socket) {
1959 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001960 ds.control_socket_fd_ = open_socket("dumpstate");
1961 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001962 }
1963
Felipe Leme71bbfc52015-11-23 14:14:51 -08001964 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001965 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001966 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001967 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001968 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1969 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001970 if (do_add_date) {
1971 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001972 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001973 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001974 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001975 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001976 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001977
1978 if (telephony_only) {
1979 ds.base_name_ += "-telephony";
mukesh agrawal253dad42018-01-23 21:59:59 -08001980 } else if (wifi_only) {
1981 ds.base_name_ += "-wifi";
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001982 }
1983
Felipe Leme71bbfc52015-11-23 14:14:51 -08001984 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001985 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001986 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001987 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001988 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001989
Felipe Lemee844a9d2016-09-21 15:01:39 -07001990 MYLOGD(
1991 "Bugreport dir: %s\n"
1992 "Base name: %s\n"
1993 "Suffix: %s\n"
1994 "Log path: %s\n"
1995 "Temporary path: %s\n"
1996 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001997 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1998 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001999
Felipe Leme1e9edc62015-12-21 16:02:13 -08002000 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002001 ds.path_ = ds.GetPath(".zip");
2002 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
2003 create_parent_dirs(ds.path_.c_str());
2004 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07002005 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002006 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002007 do_zip_file = 0;
2008 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07002009 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002010 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07002011 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08002012 }
2013
Felipe Leme9a523ae2016-10-20 15:10:33 -07002014 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002015 if (do_broadcast) {
2016 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002017
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002018 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002019 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002020 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002021 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002022 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002023 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002024 };
2025 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002026 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07002027 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002028 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002029 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002030 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08002031 }
2032 }
2033
Nick Kralevichf3599b32016-01-25 15:05:16 -08002034 /* read /proc/cmdline before dropping root */
2035 FILE *cmdline = fopen("/proc/cmdline", "re");
2036 if (cmdline) {
2037 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
2038 fclose(cmdline);
2039 }
2040
John Michelau1f794c42012-09-17 11:20:19 -05002041 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08002042 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05002043 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002044
Felipe Leme9a523ae2016-10-20 15:10:33 -07002045 if (do_fb && ds.do_early_screenshot_) {
2046 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08002047 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08002048 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08002049 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002050 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002051 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08002052 }
2053 }
2054
Felipe Leme1e9edc62015-12-21 16:02:13 -08002055 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002056 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
2057 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002058 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08002059 }
2060 }
2061
Felipe Leme71bbfc52015-11-23 14:14:51 -08002062 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002063 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr)));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002064 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
2065 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
2066 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
2067 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002068 }
Vishnu Nair20cf5032018-01-05 13:15:49 -08002069 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout)));
Felipe Leme6e01fa62015-11-11 19:35:14 -08002070 /* TODO: rather than generating a text file now and zipping it later,
2071 it would be more efficient to redirect stdout to the zip entry
2072 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07002073 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
2074 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08002075 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002076 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08002077 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002078 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08002079
2080 // Don't buffer stdout
2081 setvbuf(stdout, nullptr, _IONBF, 0);
2082
Felipe Leme608385d2016-02-01 10:35:38 -08002083 // NOTE: there should be no stdout output until now, otherwise it would break the header.
2084 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08002085 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07002086 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07002087
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002088 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07002089 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002090 ds.DumpstateBoard();
mukesh agrawal253dad42018-01-23 21:59:59 -08002091 } else if (wifi_only) {
2092 DumpstateWifiOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002093 } else {
2094 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
2095 // First try to dump anrd trace if the daemon is running. Otherwise, dump
2096 // the raw trace.
2097 if (!dump_anrd_trace()) {
2098 dump_systrace();
2099 }
2100
2101 // Invoking the following dumpsys calls before dump_traces() to try and
2102 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07002103 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002104
2105 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
2106 dump_raft();
2107
2108 /* collect stack traces from Dalvik and native processes (needs root) */
2109 dump_traces_path = dump_traces();
2110
2111 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01002112 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
2113 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01002114
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002115 ds.AddDir(RECOVERY_DIR, true);
2116 ds.AddDir(RECOVERY_DATA_DIR, true);
2117 ds.AddDir(LOGPERSIST_DATA_DIR, false);
2118 if (!PropertiesHelper::IsUserBuild()) {
2119 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
2120 ds.AddDir(PROFILE_DATA_DIR_REF, true);
2121 }
2122 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07002123 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002124
2125 // Capture any IPSec policies in play. No keys are exposed here.
2126 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
2127 CommandOptions::WithTimeout(10).Build());
2128
2129 // Run ss as root so we can see socket marks.
2130 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
2131 CommandOptions::WithTimeout(10).Build());
2132
Jin Qian3cd671e2017-09-27 18:50:04 -07002133 // Run iotop as root to show top 100 IO threads
2134 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
2135
Felipe Leme6ec6ac42017-01-10 15:29:53 -08002136 if (!DropRootUser()) {
2137 return -1;
2138 }
2139
2140 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07002141 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07002142
Felipe Leme55b42a62015-11-10 17:39:08 -08002143 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002144 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002145 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout)));
Colin Crossf45fa6b2012-03-26 12:38:26 -07002146 }
2147
Felipe Leme6e01fa62015-11-11 19:35:14 -08002148 /* rename or zip the (now complete) .tmp file to its final location */
2149 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002150
2151 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002152 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07002153 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08002154 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002155 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002156 /* must whitelist which characters are allowed, otherwise it could cross directories */
2157 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002158 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08002159 change_suffix = true;
2160 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07002161 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08002162 }
2163 }
2164 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07002165 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
2166 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07002167 if (!ds.screenshot_path_.empty()) {
2168 std::string new_screenshot_path = ds.GetPath(".png");
2169 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
2170 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
2171 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08002172 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002173 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08002174 }
2175 }
2176 }
2177
Felipe Leme6e01fa62015-11-11 19:35:14 -08002178 bool do_text_file = true;
2179 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07002180 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002181 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002182 do_text_file = true;
2183 } else {
2184 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08002185 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07002186 std::string new_path = ds.GetPath(".zip");
2187 if (ds.path_ != new_path) {
2188 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
2189 if (rename(ds.path_.c_str(), new_path.c_str())) {
2190 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002191 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08002192 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002193 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08002194 }
2195 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002196 }
2197 }
2198 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002199 ds.path_ = ds.GetPath(".txt");
2200 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
2201 ds.tmp_path_.c_str());
2202 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
2203 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07002204 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07002205 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08002206 }
2207 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07002208 if (use_control_socket) {
2209 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002210 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07002211 "FAIL:could not create zip file, check %s "
2212 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07002213 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002214 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002215 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07002216 }
2217 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07002218 }
2219
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002220 /* vibrate a few but shortly times to let user know it's finished */
Takuya Ogawa47f644e2017-12-20 18:09:09 +09002221 if (do_vibrate) {
2222 for (int i = 0; i < 3; i++) {
2223 Vibrate(75);
2224 usleep((75 + 50) * 1000);
2225 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08002226 }
2227
Jeff Brown1dc94e32014-09-11 14:15:27 -07002228 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002229 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002230 if (!ds.path_.empty()) {
2231 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002232 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002233
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002234 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002235 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002236 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002237 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002238 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002239 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2240 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002241 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002242 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002243 if (do_fb) {
2244 am_args.push_back("--es");
2245 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002246 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002247 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002248 if (!ds.notification_title.empty()) {
2249 am_args.push_back("--es");
2250 am_args.push_back("android.intent.extra.TITLE");
2251 am_args.push_back(ds.notification_title);
2252 if (!ds.notification_description.empty()) {
2253 am_args.push_back("--es");
2254 am_args.push_back("android.intent.extra.DESCRIPTION");
2255 am_args.push_back(ds.notification_description);
2256 }
2257 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002258 if (is_remote_mode) {
2259 am_args.push_back("--es");
2260 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002261 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002262 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2263 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002264 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002265 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002266 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002267 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002268 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002269 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002270 }
2271
Felipe Leme7447d7c2016-11-03 18:12:22 -07002272 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2273 ds.progress_->GetInitialMax());
2274 ds.progress_->Save();
2275 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002276
Felipe Leme107a05f2016-03-08 15:11:15 -08002277 if (is_redirecting) {
Vishnu Nair20cf5032018-01-05 13:15:49 -08002278 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr)));
Felipe Leme107a05f2016-03-08 15:11:15 -08002279 }
2280
Felipe Leme9a523ae2016-10-20 15:10:33 -07002281 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002282 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002283 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002284 }
2285
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002286 CloseDumpFds(tombstone_data.get());
2287 CloseDumpFds(anr_data.get());
2288
Colin Crossf45fa6b2012-03-26 12:38:26 -07002289 return 0;
2290}