blob: 734cfa73a31d4b058c28a0c5c8e46484cae83d03 [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>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070028#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <sys/resource.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <sys/wait.h>
33#include <unistd.h>
Narayan Kamath8f788292017-05-25 13:20:39 +010034#include <memory>
35#include <regex>
36#include <set>
37#include <string>
38#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070039
Felipe Leme96c2bbb2016-09-26 09:21:21 -070040#include <android-base/file.h>
41#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080042#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070043#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070044#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080045#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
46#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070047#include <cutils/properties.h>
Felipe Leme75876a22016-10-27 16:31:27 -070048#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070049#include <private/android_filesystem_config.h>
50#include <private/android_logger.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070051
Felipe Lemef0292972016-11-22 13:57:05 -080052#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070053#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070054#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080055
Steven Morelandcb7ef822016-11-29 13:20:37 -080056using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Steven Morelandcb7ef822016-11-29 13:20:37 -080057
Felipe Leme47e9be22016-12-21 15:37:07 -080058// TODO: remove once moved to namespace
59using android::os::dumpstate::CommandOptions;
60using android::os::dumpstate::DumpFileToFd;
61using android::os::dumpstate::PropertiesHelper;
62using android::os::dumpstate::GetPidByName;
63
Colin Crossf45fa6b2012-03-26 12:38:26 -070064/* read before root is shed */
65static char cmdline_buf[16384] = "(unknown)";
66static const char *dump_traces_path = NULL;
67
Felipe Leme1d486fe2016-10-14 18:06:47 -070068// TODO: variables and functions below should be part of dumpstate object
69
Felipe Leme635ca312016-01-05 14:23:02 -080070static std::set<std::string> mount_points;
71void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080072
Todd Poynor2a83daa2013-11-22 15:44:22 -080073#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070074#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -070075#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -080076
Wei Liu341938b2016-04-27 16:18:17 -070077#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080078#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070079#define RECOVERY_DATA_DIR "/data/misc/recovery"
Tianjie Xu75d53362018-04-11 16:42:28 -070080#define UPDATE_ENGINE_LOG_DIR "/data/misc/update_engine_log"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070081#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010082#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
83#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +090084#define WLUTIL "/vendor/xbin/wlutil"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070085
Narayan Kamath8f788292017-05-25 13:20:39 +010086// TODO(narayan): Since this information has to be kept in sync
87// with tombstoned, we should just put it in a common header.
88//
89// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +010090static const std::string TOMBSTONE_DIR = "/data/tombstones/";
91static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
92static const std::string ANR_DIR = "/data/anr/";
93static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -070094
Felipe Lemee844a9d2016-09-21 15:01:39 -070095// TODO: temporary variables and functions used during C++ refactoring
96static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -070097static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
98 const CommandOptions& options = CommandOptions::DEFAULT) {
99 return ds.RunCommand(title, fullCommand, options);
100}
101static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800102 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Felipe Leme678727a2016-09-21 17:22:11 -0700103 long dumpsysTimeout = 0) {
104 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
105}
106static int DumpFile(const std::string& title, const std::string& path) {
107 return ds.DumpFile(title, path);
108}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800109
Felipe Lemee844a9d2016-09-21 15:01:39 -0700110// Relative directory (inside the zip) for all files copied as-is into the bugreport.
111static const std::string ZIP_ROOT_DIR = "FS";
112
Steven Moreland7440ddb2016-12-15 16:13:39 -0800113// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700114static const std::string kDumpstateBoardPath = "/bugreports/";
115static const std::string kDumpstateBoardFiles[] = {
116 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700117 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700118};
119static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
120
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700121static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800122
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700123static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700124static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700125static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700126static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
127static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700128
Felipe Lemef0292972016-11-22 13:57:05 -0800129static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
130
Narayan Kamath8f788292017-05-25 13:20:39 +0100131/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100132 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
133 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
134 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gampe8262d482017-08-22 13:08:37 -0700135 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100136 */
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700137static std::vector<DumpData> GetDumpFds(const std::string& dir_path,
138 const std::string& file_prefix,
139 bool limit_by_mtime,
140 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100141 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
142
Narayan Kamathbd863722017-06-01 18:50:12 +0100143 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100144
Luis Hector Chavezbe2d7dd2018-03-14 12:15:56 -0700145 if (dump_dir == nullptr) {
146 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno));
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700147 return std::vector<DumpData>();
Luis Hector Chavezbe2d7dd2018-03-14 12:15:56 -0700148 }
149
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700150 std::vector<DumpData> dump_data;
Narayan Kamathbd863722017-06-01 18:50:12 +0100151 struct dirent* entry = nullptr;
152 while ((entry = readdir(dump_dir.get()))) {
153 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100154 continue;
155 }
156
Narayan Kamathbd863722017-06-01 18:50:12 +0100157 const std::string base_name(entry->d_name);
158 if (base_name.find(file_prefix) != 0) {
159 continue;
160 }
161
162 const std::string abs_path = dir_path + base_name;
163 android::base::unique_fd fd(
164 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
165 if (fd == -1) {
Luis Hector Chavezbe2d7dd2018-03-14 12:15:56 -0700166 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamathbd863722017-06-01 18:50:12 +0100167 break;
168 }
169
170 struct stat st = {};
171 if (fstat(fd, &st) == -1) {
Luis Hector Chavezbe2d7dd2018-03-14 12:15:56 -0700172 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100173 continue;
174 }
175
Narayan Kamath3f31b632018-02-22 19:42:36 +0000176 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100177 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100178 continue;
179 }
180
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700181 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime});
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700182 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100183
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700184 // Sort in descending modification time so that we only keep the newest
185 // reports if |limit_by_count| is true.
186 std::sort(dump_data.begin(), dump_data.end(),
187 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; });
Narayan Kamath8f788292017-05-25 13:20:39 +0100188
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700189 if (limit_by_count && dump_data.size() > 10) {
190 dump_data.erase(dump_data.begin() + 10, dump_data.end());
Andreas Gampe8262d482017-08-22 13:08:37 -0700191 }
192
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700193 return dump_data;
Narayan Kamath8f788292017-05-25 13:20:39 +0100194}
195
Narayan Kamathbd863722017-06-01 18:50:12 +0100196static bool AddDumps(const std::vector<DumpData>::const_iterator start,
197 const std::vector<DumpData>::const_iterator end,
198 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100199 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100200 for (auto it = start; it != end; ++it) {
201 const std::string& name = it->name;
202 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100203 dumped = true;
Narayan Kamathd3badba2017-10-27 11:15:51 +0100204
205 // Seek to the beginning of the file before dumping any data. A given
206 // DumpData entry might be dumped multiple times in the report.
207 //
208 // For example, the most recent ANR entry is dumped to the body of the
209 // main entry and it also shows up as a separate entry in the bugreport
210 // ZIP file.
211 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
212 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
213 strerror(errno));
214 }
215
Narayan Kamath8f788292017-05-25 13:20:39 +0100216 if (ds.IsZipping() && add_to_zip) {
217 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
Narayan Kamathd3badba2017-10-27 11:15:51 +0100218 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100219 }
220 } else {
221 dump_file_from_fd(type_name, name.c_str(), fd);
222 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100223 }
224
225 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700226}
227
Felipe Leme635ca312016-01-05 14:23:02 -0800228// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700229void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800230 char path[PATH_MAX];
231
232 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
233 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700234 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800235 char linkname[PATH_MAX];
236 ssize_t r = readlink(path, linkname, PATH_MAX);
237 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800238 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800239 return;
240 }
241 linkname[r] = '\0';
242
243 if (mount_points.find(linkname) == mount_points.end()) {
244 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700245 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700246 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800247 mount_points.insert(linkname);
248 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800249 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800250 }
251 }
252}
253
254void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700255 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700256 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800257 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800258 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700259 for_each_pid(do_mountinfo, nullptr);
260 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800261}
262
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700263static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
264{
265 DIR *d;
266 struct dirent *de;
267 char path[PATH_MAX];
268
269 d = opendir(driverpath);
270 if (d == NULL) {
271 return;
272 }
273
274 while ((de = readdir(d))) {
275 if (de->d_type != DT_LNK) {
276 continue;
277 }
278 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700279 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700280 }
281
282 closedir(d);
283}
284
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700285
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700286
287// dump anrd's trace and add to the zip file.
288// 1. check if anrd is running on this device.
289// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
290// 3. wait until the trace generation completes and add to the zip file.
291static bool dump_anrd_trace() {
292 unsigned int pid;
293 char buf[50], path[PATH_MAX];
294 struct dirent *trace;
295 struct stat st;
296 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700297 int retry = 5;
298 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700299 long long cur_size = 0;
300 const char *trace_path = "/data/misc/anrd/";
301
Felipe Leme1d486fe2016-10-14 18:06:47 -0700302 if (!ds.IsZipping()) {
303 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700304 return false;
305 }
306
307 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700308 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700309
310 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700311 if (stat(trace_path, &st) == 0) {
312 old_mtime = st.st_mtime;
313 } else {
314 MYLOGE("Failed to find: %s\n", trace_path);
315 return false;
316 }
317
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700318 // send SIGUSR1 to the anrd to generate a trace.
319 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700320 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700321 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700322 MYLOGE("anrd signal timed out. Please manually collect trace\n");
323 return false;
324 }
325
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700326 while (retry-- > 0 && old_mtime == st.st_mtime) {
327 sleep(1);
328 stat(trace_path, &st);
329 }
330
331 if (retry < 0 && old_mtime == st.st_mtime) {
332 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
333 return false;
334 }
335
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700336 // identify the trace file by its creation time.
337 if (!(trace_dir = opendir(trace_path))) {
338 MYLOGE("Can't open trace file under %s\n", trace_path);
339 }
340 while ((trace = readdir(trace_dir))) {
341 if (strcmp(trace->d_name, ".") == 0
342 || strcmp(trace->d_name, "..") == 0) {
343 continue;
344 }
345 sprintf(path, "%s%s", trace_path, trace->d_name);
346 if (stat(path, &st) == 0) {
347 if (st.st_ctime > max_ctime) {
348 max_ctime = st.st_ctime;
349 sprintf(buf, "%s", trace->d_name);
350 }
351 }
352 }
353 closedir(trace_dir);
354
355 // Wait until the dump completes by checking the size of the trace.
356 if (max_ctime > 0) {
357 sprintf(path, "%s%s", trace_path, buf);
358 while(true) {
359 sleep(1);
360 if (stat(path, &st) == 0) {
361 if (st.st_size == cur_size) {
362 break;
363 } else if (st.st_size > cur_size) {
364 cur_size = st.st_size;
365 } else {
366 return false;
367 }
368 } else {
369 MYLOGE("Cant stat() %s anymore\n", path);
370 return false;
371 }
372 }
373 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700374 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700375 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
376 } else {
377 if (remove(path)) {
378 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
379 }
380 return true;
381 }
382 } else {
383 MYLOGE("Can't stats any trace file under %s\n", trace_path);
384 }
385 }
386 return false;
387}
388
Felipe Lemeefd7e272016-05-18 09:27:16 -0700389static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700390 if (!ds.IsZipping()) {
391 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700392 return;
393 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700394 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700395 if (systrace_path.empty()) {
396 MYLOGE("Not dumping systrace because path is empty\n");
397 return;
398 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700399 const char* path = "/sys/kernel/debug/tracing/tracing_on";
400 long int is_tracing;
401 if (read_file_as_long(path, &is_tracing)) {
402 return; // error already logged
403 }
404 if (is_tracing <= 0) {
405 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
406 return;
407 }
408
Felipe Leme14e034a2016-03-30 18:51:03 -0700409 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
410 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700411 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700412 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700413 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700414 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700415 // peacefully; ideally, we should call strace to stop itself, but there is no such option
416 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700417 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700418 // MYLOGE("could not stop systrace ");
419 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700420 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700421 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700422 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700423 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700424 if (remove(systrace_path.c_str())) {
425 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
426 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700427 }
428}
429
Felipe Lemeefd7e272016-05-18 09:27:16 -0700430static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800431 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700432 return;
433 }
434
Felipe Leme1d486fe2016-10-14 18:06:47 -0700435 std::string raft_path = ds.GetPath("-raft_log.txt");
436 if (raft_path.empty()) {
437 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700438 return;
439 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700440
441 struct stat s;
442 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
443 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
444 return;
445 }
446
Felipe Leme30dbfa12016-09-02 12:43:26 -0700447 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 if (!ds.IsZipping()) {
449 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700450 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700451 return;
452 }
453
Felipe Leme1d486fe2016-10-14 18:06:47 -0700454 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
455 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
456 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700457 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700458 if (remove(raft_path.c_str())) {
459 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700460 }
461 }
462}
463
Mark Salyzyn326842f2015-04-30 09:49:41 -0700464static bool skip_not_stat(const char *path) {
465 static const char stat[] = "/stat";
466 size_t len = strlen(path);
467 if (path[len - 1] == '/') { /* Directory? */
468 return false;
469 }
470 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
471}
472
Felipe Leme4c2d6632016-09-28 14:32:00 -0700473static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800474 return false;
475}
476
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700477unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700478
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800479//
480// stat offsets
481// Name units description
482// ---- ----- -----------
483// read I/Os requests number of read I/Os processed
484#define __STAT_READ_IOS 0
485// read merges requests number of read I/Os merged with in-queue I/O
486#define __STAT_READ_MERGES 1
487// read sectors sectors number of sectors read
488#define __STAT_READ_SECTORS 2
489// read ticks milliseconds total wait time for read requests
490#define __STAT_READ_TICKS 3
491// write I/Os requests number of write I/Os processed
492#define __STAT_WRITE_IOS 4
493// write merges requests number of write I/Os merged with in-queue I/O
494#define __STAT_WRITE_MERGES 5
495// write sectors sectors number of sectors written
496#define __STAT_WRITE_SECTORS 6
497// write ticks milliseconds total wait time for write requests
498#define __STAT_WRITE_TICKS 7
499// in_flight requests number of I/Os currently in flight
500#define __STAT_IN_FLIGHT 8
501// io_ticks milliseconds total time this block device has been active
502#define __STAT_IO_TICKS 9
503// time_in_queue milliseconds total wait time for all requests
504#define __STAT_IN_QUEUE 10
505#define __STAT_NUMBER_FIELD 11
506//
507// read I/Os, write I/Os
508// =====================
509//
510// These values increment when an I/O request completes.
511//
512// read merges, write merges
513// =========================
514//
515// These values increment when an I/O request is merged with an
516// already-queued I/O request.
517//
518// read sectors, write sectors
519// ===========================
520//
521// These values count the number of sectors read from or written to this
522// block device. The "sectors" in question are the standard UNIX 512-byte
523// sectors, not any device- or filesystem-specific block size. The
524// counters are incremented when the I/O completes.
525#define SECTOR_SIZE 512
526//
527// read ticks, write ticks
528// =======================
529//
530// These values count the number of milliseconds that I/O requests have
531// waited on this block device. If there are multiple I/O requests waiting,
532// these values will increase at a rate greater than 1000/second; for
533// example, if 60 read requests wait for an average of 30 ms, the read_ticks
534// field will increase by 60*30 = 1800.
535//
536// in_flight
537// =========
538//
539// This value counts the number of I/O requests that have been issued to
540// the device driver but have not yet completed. It does not include I/O
541// requests that are in the queue but not yet issued to the device driver.
542//
543// io_ticks
544// ========
545//
546// This value counts the number of milliseconds during which the device has
547// had I/O requests queued.
548//
549// time_in_queue
550// =============
551//
552// This value counts the number of milliseconds that I/O requests have waited
553// on this block device. If there are multiple I/O requests waiting, this
554// value will increase as the product of the number of milliseconds times the
555// number of requests waiting (see "read ticks" above for an example).
556#define S_TO_MS 1000
557//
558
Mark Salyzyn326842f2015-04-30 09:49:41 -0700559static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800560 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700561 bool z;
562 char *cp, *buffer = NULL;
563 size_t i = 0;
564 FILE *fp = fdopen(fd, "rb");
565 getline(&buffer, &i, fp);
566 fclose(fp);
567 if (!buffer) {
568 return -errno;
569 }
570 i = strlen(buffer);
571 while ((i > 0) && (buffer[i - 1] == '\n')) {
572 buffer[--i] = '\0';
573 }
574 if (!*buffer) {
575 free(buffer);
576 return 0;
577 }
578 z = true;
579 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800580 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700581 if (fields[i] != 0) {
582 z = false;
583 }
584 }
585 if (z) { /* never accessed */
586 free(buffer);
587 return 0;
588 }
589
Wei Wang509bb5d2017-06-09 14:42:12 -0700590 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
591 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700592 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700593
594 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
595 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
596 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700597 free(buffer);
598
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800599 if (fields[__STAT_IO_TICKS]) {
600 unsigned long read_perf = 0;
601 unsigned long read_ios = 0;
602 if (fields[__STAT_READ_TICKS]) {
603 unsigned long long divisor = fields[__STAT_READ_TICKS]
604 * fields[__STAT_IO_TICKS];
605 read_perf = ((unsigned long long)SECTOR_SIZE
606 * fields[__STAT_READ_SECTORS]
607 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
608 / divisor;
609 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
610 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
611 / divisor;
612 }
613
614 unsigned long write_perf = 0;
615 unsigned long write_ios = 0;
616 if (fields[__STAT_WRITE_TICKS]) {
617 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
618 * fields[__STAT_IO_TICKS];
619 write_perf = ((unsigned long long)SECTOR_SIZE
620 * fields[__STAT_WRITE_SECTORS]
621 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
622 / divisor;
623 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
624 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
625 / divisor;
626 }
627
628 unsigned queue = (fields[__STAT_IN_QUEUE]
629 + (fields[__STAT_IO_TICKS] >> 1))
630 / fields[__STAT_IO_TICKS];
631
632 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700633 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 -0800634 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700635 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 -0800636 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800637 }
638
639 /* bugreport timeout factor adjustment */
640 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
641 worst_write_perf = write_perf;
642 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700643 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700644 return 0;
645}
646
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700647/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800648static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700649 log_id_t id = android_name_to_log_id(name);
650 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700651 /* Engineering margin is ten-fold our guess */
652 return 10 * (property_size + worst_write_perf) / worst_write_perf;
653}
654
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700655void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700656 std::string build, fingerprint, radio, bootloader, network;
657 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700658
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700659 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
660 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700661 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
662 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
663 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700664 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700665
Felipe Lemed8b94e52016-12-08 10:21:44 -0800666 printf("========================================================\n");
667 printf("== dumpstate: %s\n", date);
668 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700669
Felipe Lemed8b94e52016-12-08 10:21:44 -0800670 printf("\n");
671 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700672 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800673 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
674 printf("Bootloader: %s\n", bootloader.c_str());
675 printf("Radio: %s\n", radio.c_str());
676 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700677
Felipe Lemed8b94e52016-12-08 10:21:44 -0800678 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800679 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800680 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
pengzhicai24ae8192017-05-25 17:29:33 +0800681 ds.RunCommand("UPTIME", {"uptime"}, CommandOptions::DEFAULT);
Felipe Lemed8b94e52016-12-08 10:21:44 -0800682 printf("Bugreport format version: %s\n", version_.c_str());
683 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
684 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
685 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800686}
687
Felipe Leme24b66ee2016-06-16 10:55:26 -0700688// List of file extensions that can cause a zip file attachment to be rejected by some email
689// service providers.
690static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
691 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
692 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
693 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
694};
695
Felipe Leme1d486fe2016-10-14 18:06:47 -0700696bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
697 if (!IsZipping()) {
698 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
699 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800700 return false;
701 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700702 std::string valid_name = entry_name;
703
704 // Rename extension if necessary.
Chih-Hung Hsieh0e1f4ce2017-08-03 15:48:25 -0700705 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700706 if (idx != std::string::npos) {
707 std::string extension = entry_name.substr(idx);
708 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
709 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
710 valid_name = entry_name + ".renamed";
711 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
712 }
713 }
714
Felipe Leme6fe9db62016-02-12 09:04:16 -0800715 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
716 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700717 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
718 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700719 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700720 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700721 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800722 return false;
723 }
724
Felipe Leme770410d2016-01-26 17:07:14 -0800725 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800726 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400727 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800728 if (bytes_read == 0) {
729 break;
730 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800731 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800732 return false;
733 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700734 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800735 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700736 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800737 return false;
738 }
739 }
740
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700741 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700742 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700743 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800744 return false;
745 }
746
747 return true;
748}
749
Felipe Leme1d486fe2016-10-14 18:06:47 -0700750bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
751 android::base::unique_fd fd(
752 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700753 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800754 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800755 return false;
756 }
757
Felipe Leme1d486fe2016-10-14 18:06:47 -0700758 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800759}
760
761/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700762static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700763 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800764}
765
Felipe Leme1d486fe2016-10-14 18:06:47 -0700766void Dumpstate::AddDir(const std::string& dir, bool recursive) {
767 if (!IsZipping()) {
768 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800769 return;
770 }
Felipe Leme678727a2016-09-21 17:22:11 -0700771 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800772 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700773 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800774}
775
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
777 if (!IsZipping()) {
778 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
779 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800780 return false;
781 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800782 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700783 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700784 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700785 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700786 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800787 return false;
788 }
789
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700790 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700791 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700792 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700793 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800794 return false;
795 }
796
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700797 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700798 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700799 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800800 return false;
801 }
802
803 return true;
804}
805
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800806static void DoKmsg() {
807 struct stat st;
808 if (!stat(PSTORE_LAST_KMSG, &st)) {
809 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
810 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
811 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
812 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
813 } else {
814 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
815 DumpFile("LAST KMSG", "/proc/last_kmsg");
816 }
817}
818
819static void DoLogcat() {
820 unsigned long timeout;
821 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
822 // calculate timeout
823 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
824 if (timeout < 20000) {
825 timeout = 20000;
826 }
Tony Makae737652017-03-30 17:47:09 +0100827 RunCommand("SYSTEM LOG",
828 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
829 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800830 CommandOptions::WithTimeout(timeout / 1000).Build());
831 timeout = logcat_timeout("events");
832 if (timeout < 20000) {
833 timeout = 20000;
834 }
835 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100836 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
837 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800838 CommandOptions::WithTimeout(timeout / 1000).Build());
839 timeout = logcat_timeout("radio");
840 if (timeout < 20000) {
841 timeout = 20000;
842 }
843 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100844 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
845 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800846 CommandOptions::WithTimeout(timeout / 1000).Build());
847
848 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
849
850 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
851 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100852 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
853 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800854}
855
Jayachandran Ca94c7172017-06-10 15:08:12 -0700856static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700857 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
858 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900859 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700860 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900861 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
862 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
863 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
864 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700865}
866
Narayan Kamath8f788292017-05-25 13:20:39 +0100867static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
868 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
869 anr_traces_dir.c_str());
870
871 // If we're here, dump_traces_path will always be a temporary file
872 // (created with mkostemp or similar) that contains dumps taken earlier
873 // on in the process.
874 if (dump_traces_path != nullptr) {
875 if (add_to_zip) {
876 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
877 } else {
878 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
879 dump_traces_path);
880 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
881 }
882
883 const int ret = unlink(dump_traces_path);
884 if (ret == -1) {
885 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
886 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700887 }
888 }
889
Narayan Kamathbd863722017-06-01 18:50:12 +0100890 // Add a specific message for the first ANR Dump.
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700891 if (ds.anr_data_.size() > 0) {
892 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1,
Narayan Kamathbd863722017-06-01 18:50:12 +0100893 "VM TRACES AT LAST ANR", add_to_zip);
894
Narayan Kamathd3badba2017-10-27 11:15:51 +0100895 // The "last" ANR will always be included as separate entry in the zip file. In addition,
896 // it will be present in the body of the main entry if |add_to_zip| == false.
897 //
898 // Historical ANRs are always included as separate entries in the bugreport zip file.
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -0700899 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(),
Narayan Kamathd3badba2017-10-27 11:15:51 +0100900 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100901 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100902 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
903 }
904}
905
906static void AddAnrTraceFiles() {
907 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
908
Elliott Hughesd9fe0382018-03-23 11:04:25 -0700909 std::string anr_traces_dir = "/data/anr";
Narayan Kamath8f788292017-05-25 13:20:39 +0100910
Elliott Hughesd9fe0382018-03-23 11:04:25 -0700911 AddAnrTraceDir(add_to_zip, anr_traces_dir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100912
Elliott Hughesd9fe0382018-03-23 11:04:25 -0700913 // Slow traces for slow operations.
Felipe Lemee184f662016-10-27 10:04:47 -0700914 struct stat st;
Elliott Hughesd9fe0382018-03-23 11:04:25 -0700915 int i = 0;
916 while (true) {
917 const std::string slow_trace_path =
918 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
919 if (stat(slow_trace_path.c_str(), &st)) {
920 // No traces file at this index, done with the files.
921 break;
Felipe Lemee184f662016-10-27 10:04:47 -0700922 }
Elliott Hughesd9fe0382018-03-23 11:04:25 -0700923 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
924 i++;
Felipe Lemee184f662016-10-27 10:04:47 -0700925 }
926}
927
Wei Wang509bb5d2017-06-09 14:42:12 -0700928static void DumpBlockStatFiles() {
929 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700930
Wei Wang1dc1ef52017-06-12 11:28:37 -0700931 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
932
933 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700934 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
935 return;
936 }
937
938 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -0700939 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700940 if ((d->d_name[0] == '.')
941 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
942 || (d->d_name[1] == '\0'))) {
943 continue;
944 }
945 const std::string new_path =
946 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
947 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
948 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
949 printf("\n");
950 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700951 return;
Wei Wang509bb5d2017-06-09 14:42:12 -0700952}
Jayachandran Ca94c7172017-06-10 15:08:12 -0700953
954static void DumpPacketStats() {
955 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
956 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
957 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
958 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
959 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
960}
961
962static void DumpIpAddrAndRules() {
963 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
964 RunCommand("NETWORK INTERFACES", {"ip", "link"});
965 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
966 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
967 RunCommand("IP RULES", {"ip", "rule", "show"});
968 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
969}
970
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700971static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -0700972 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700973
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700974 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
pengzhicai24ae8192017-05-25 17:29:33 +0800975 /* TODO: Remove duplicate uptime call when tools use it from header */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700976 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -0700977 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800978 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700979 DumpFile("MEMORY INFO", "/proc/meminfo");
980 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700981 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -0800982 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700983 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
984 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
985 DumpFile("SLAB INFO", "/proc/slabinfo");
986 DumpFile("ZONEINFO", "/proc/zoneinfo");
987 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
988 DumpFile("BUDDYINFO", "/proc/buddyinfo");
989 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700990
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700991 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
992 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
993 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700994
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700995 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700996 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemef0292972016-11-22 13:57:05 -0800997 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700998
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700999 if (ds.IsZipping()) {
1000 RunCommand(
1001 "HARDWARE HALS",
1002 {"lshal", std::string("--debug=") + kLsHalDebugPath},
Yifan Hong48e83a12017-10-03 14:10:07 -07001003 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001004
1005 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1006
1007 unlink(kLsHalDebugPath.c_str());
1008 } else {
1009 RunCommand(
Yifan Hong48e83a12017-10-03 14:10:07 -07001010 "HARDWARE HALS", {"lshal", "--debug"},
1011 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001012 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001013
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001014 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001015 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001016 struct stat s;
1017 if (stat("/proc/modules", &s) != 0) {
1018 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1019 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001020 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001021 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001022
Colin Crossf45fa6b2012-03-26 12:38:26 -07001023 do_dmesg();
1024
Felipe Lemef0292972016-11-22 13:57:05 -08001025 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001026 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1027 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001028 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001029
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001030 /* Dump Bluetooth HCI logs */
1031 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001032
Felipe Leme9a523ae2016-10-20 15:10:33 -07001033 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001034 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001035 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001036 }
1037
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001038 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001039
Felipe Lemee184f662016-10-27 10:04:47 -07001040 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001041
Narayan Kamath8f788292017-05-25 13:20:39 +01001042 // NOTE: tombstones are always added as separate entries in the zip archive
1043 // and are not interspersed with the main report.
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -07001044 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(),
Narayan Kamathbd863722017-06-01 18:50:12 +01001045 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001046 if (!tombstones_dumped) {
1047 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001048 }
1049
Jayachandran Ca94c7172017-06-10 15:08:12 -07001050 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001051
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001052 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001053
Jayachandran Ca94c7172017-06-10 15:08:12 -07001054 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001055
1056 dump_route_tables();
1057
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001058 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1059 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1060 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001061
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001062 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001063 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001064
Elliott Hughes23ccc622017-02-28 10:14:22 -08001065 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001066
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001067 RunCommand("VOLD DUMP", {"vdc", "dump"});
1068 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001069
Jin Qian24354422017-01-24 12:07:14 -08001070 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001071
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001072 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001073
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001074 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001075
Colin Crossf45fa6b2012-03-26 12:38:26 -07001076 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001077 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1078 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1079 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1080 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1081 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001082
Felipe Leme6f674ae2016-11-18 17:10:33 -08001083 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001084
Steven Moreland7440ddb2016-12-15 16:13:39 -08001085 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001086 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1087 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001088 // su does not exist on user builds, so try running without it.
1089 // This way any implementations of vril-dump that do not require
1090 // root can run on user builds.
1091 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001092 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001093 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001094 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001095 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001096 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001097 }
1098
Felipe Lemed8b94e52016-12-08 10:21:44 -08001099 printf("========================================================\n");
1100 printf("== Android Framework Services\n");
1101 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001102
Felipe Leme5bcce572016-09-27 09:21:08 -07001103 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1104 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001105
Felipe Lemed8b94e52016-12-08 10:21:44 -08001106 printf("========================================================\n");
1107 printf("== Checkins\n");
1108 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001109
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001110 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1111 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1112 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1113 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1114 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1115 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001116
Felipe Lemed8b94e52016-12-08 10:21:44 -08001117 printf("========================================================\n");
1118 printf("== Running Application Activities\n");
1119 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001120
Winson Chung1434a5c2017-02-28 17:09:24 -08001121 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001122
Felipe Lemed8b94e52016-12-08 10:21:44 -08001123 printf("========================================================\n");
1124 printf("== Running Application Services\n");
1125 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001126
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001127 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001128
Felipe Lemed8b94e52016-12-08 10:21:44 -08001129 printf("========================================================\n");
1130 printf("== Running Application Providers\n");
1131 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001132
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001133 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001134
Adrian Roos8b397ab2017-04-04 16:35:44 -07001135 printf("========================================================\n");
1136 printf("== Dropbox crashes\n");
1137 printf("========================================================\n");
1138
1139 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1140 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1141
Felipe Lemed8b94e52016-12-08 10:21:44 -08001142 printf("========================================================\n");
1143 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1144 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1145 printf("========================================================\n");
1146 printf("== dumpstate: done (id %d)\n", ds.id_);
1147 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001148}
1149
Jayachandran Ca94c7172017-06-10 15:08:12 -07001150// This method collects dumpsys for telephony debugging only
1151static void DumpstateTelephonyOnly() {
1152 DurationReporter duration_reporter("DUMPSTATE");
1153
1154 DumpIpTablesAsRoot();
1155
1156 if (!DropRootUser()) {
1157 return;
1158 }
1159
1160 do_dmesg();
1161 DoLogcat();
1162 DumpPacketStats();
1163 DoKmsg();
1164 DumpIpAddrAndRules();
1165 dump_route_tables();
1166
1167 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1168 CommandOptions::WithTimeout(10).Build());
1169
1170 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1171
1172 printf("========================================================\n");
1173 printf("== Android Framework Services\n");
1174 printf("========================================================\n");
1175
1176 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1177 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1178
1179 printf("========================================================\n");
1180 printf("== Running Application Services\n");
1181 printf("========================================================\n");
1182
1183 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1184
1185 printf("========================================================\n");
1186 printf("== dumpstate: done (id %d)\n", ds.id_);
1187 printf("========================================================\n");
1188}
1189
Felipe Leme6f674ae2016-11-18 17:10:33 -08001190void Dumpstate::DumpstateBoard() {
1191 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001192 printf("========================================================\n");
1193 printf("== Board\n");
1194 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001195
Chris Phoenix69d92212017-01-24 23:01:13 -08001196 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001197 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001198 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001199 return;
1200 }
1201
1202 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001203 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001204 return;
1205 }
1206
Jie Song9fbfad02017-06-20 16:29:42 -07001207 std::string path[NUM_OF_DUMPS];
1208 android::base::unique_fd fd[NUM_OF_DUMPS];
1209 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001210
Jie Song9fbfad02017-06-20 16:29:42 -07001211 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1212 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1213 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1214
1215 fd[i] = android::base::unique_fd(
1216 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1217 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1218 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1219 if (fd[i] < 0) {
1220 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1221 return;
1222 } else {
1223 numFds++;
1224 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001225 }
1226
Jie Song9fbfad02017-06-20 16:29:42 -07001227 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001228 if (handle == nullptr) {
1229 MYLOGE("Could not create native_handle\n");
1230 return;
1231 }
Jie Song9fbfad02017-06-20 16:29:42 -07001232
1233 for (int i = 0; i < numFds; i++) {
1234 handle->data[i] = fd[i].release();
1235 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001236
Felipe Lemef0292972016-11-22 13:57:05 -08001237 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001238 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1239 if (!status.isOk()) {
1240 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1241 native_handle_close(handle);
1242 native_handle_delete(handle);
1243 return;
1244 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001245
Jie Song9fbfad02017-06-20 16:29:42 -07001246 for (int i = 0; i < numFds; i++) {
1247 struct stat s;
1248 if (fstat(handle->data[i], &s) == -1) {
1249 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1250 } else if (s.st_size > 0) {
1251 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1252 } else {
1253 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1254 }
1255 }
1256
Felipe Lemed8b94e52016-12-08 10:21:44 -08001257 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001258
1259 native_handle_close(handle);
1260 native_handle_delete(handle);
1261
Jie Song9fbfad02017-06-20 16:29:42 -07001262 for (int i = 0; i < numFds; i++) {
1263 if (remove(path[i].c_str()) != 0) {
1264 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1265 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001266 }
1267}
1268
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001269static void ShowUsageAndExit(int exitCode = 1) {
1270 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001271 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001272 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1273 " -h: display this help message\n"
1274 " -b: play sound file instead of vibrate, at beginning of job\n"
1275 " -e: play sound file instead of vibrate, at end of job\n"
1276 " -o: write to file (instead of stdout)\n"
1277 " -d: append date to filename (requires -o)\n"
1278 " -p: capture screenshot to filename.png (requires -o)\n"
1279 " -z: generate zipped file (requires -o)\n"
1280 " -s: write output to control socket (for init)\n"
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001281 " -S: write file location to control socket (for init; requires -o and -z)\n"
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001282 " -q: disable vibrate\n"
1283 " -B: send broadcast when finished (requires -o)\n"
1284 " -P: send broadcast when started and update system properties on "
1285 "progress (requires -o and -B)\n"
1286 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1287 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001288 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001289 exit(exitCode);
1290}
1291
1292static void ExitOnInvalidArgs() {
1293 fprintf(stderr, "invalid combination of args\n");
1294 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001295}
1296
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001297static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001298 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001299}
1300
Wei Liuf87959e2016-08-26 14:51:42 -07001301static void register_sig_handler() {
1302 struct sigaction sa;
1303 sigemptyset(&sa.sa_mask);
1304 sa.sa_flags = 0;
1305 sa.sa_handler = sig_handler;
1306 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1307 sigaction(SIGSEGV, &sa, NULL); // segment fault
1308 sigaction(SIGINT, &sa, NULL); // ctrl-c
1309 sigaction(SIGTERM, &sa, NULL); // killed
1310 sigaction(SIGQUIT, &sa, NULL); // quit
1311}
1312
Felipe Leme1d486fe2016-10-14 18:06:47 -07001313bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001314 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001315 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001316 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001317 // Final timestamp
1318 char date[80];
1319 time_t the_real_now_please_stand_up = time(nullptr);
1320 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001321 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001322 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001323
Felipe Leme9a523ae2016-10-20 15:10:33 -07001324 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001325 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001326 return false;
1327 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001328 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001329 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001330 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001331 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001332
Felipe Leme0f3fb202016-06-10 17:10:53 -07001333 // Add log file (which contains stderr output) to zip...
1334 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001335 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001336 MYLOGE("Failed to add dumpstate log to .zip file\n");
1337 return false;
1338 }
1339 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001340 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001341 fprintf(stderr, "\n");
1342
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001343 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001344 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001345 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001346 return false;
1347 }
1348
Felipe Leme1d486fe2016-10-14 18:06:47 -07001349 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1350 ds.zip_file.reset(nullptr);
1351
Felipe Lemee9d2c542016-11-15 11:48:26 -08001352 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1353 if (remove(tmp_path_.c_str()) != 0) {
1354 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001355 }
1356
Felipe Leme1e9edc62015-12-21 16:02:13 -08001357 return true;
1358}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001359
Chih-Hung Hsieh0e1f4ce2017-08-03 15:48:25 -07001360static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001361 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1362 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001363 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001364 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001365 return NULL;
1366 }
1367
1368 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001369 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001370
1371 std::vector<uint8_t> buffer(65536);
1372 while (1) {
1373 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1374 if (bytes_read == 0) {
1375 break;
1376 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001377 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001378 return NULL;
1379 }
1380
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001381 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001382 }
1383
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001384 uint8_t hash[SHA256_DIGEST_LENGTH];
1385 SHA256_Final(hash, &ctx);
1386
1387 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1388 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001389 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001390 }
1391 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1392 return std::string(hash_buffer);
1393}
1394
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001395static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1396 // clang-format off
1397 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1398 "--receiver-foreground", "--receiver-include-background", "-a", action};
1399 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001400
1401 am.insert(am.end(), args.begin(), args.end());
1402
Felipe Leme8d2410e2017-02-08 09:46:08 -08001403 RunCommand("", am,
1404 CommandOptions::WithTimeout(20)
1405 .Log("Sending broadcast: '%s'\n")
1406 .Always()
1407 .DropRoot()
1408 .RedirectStderr()
1409 .Build());
1410}
1411
Felipe Leme35b8cf12017-02-10 15:47:29 -08001412static void Vibrate(int duration_ms) {
1413 // clang-format off
1414 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1415 CommandOptions::WithTimeout(10)
1416 .Log("Vibrate: '%s'\n")
1417 .Always()
1418 .Build());
1419 // clang-format on
1420}
1421
Colin Crossf45fa6b2012-03-26 12:38:26 -07001422int main(int argc, char *argv[]) {
1423 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001424 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001425 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001426 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001427 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001428 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001429 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001430 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001431 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001432 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001433 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001434 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001435
Colin Crossf45fa6b2012-03-26 12:38:26 -07001436 /* set as high priority, and protect from OOM killer */
1437 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001438
Felipe Lemed071c682016-10-20 16:48:00 -07001439 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001440 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001441 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001442 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001443 } else {
1444 /* fallback to kernels <= 2.6.35 */
1445 oom_adj = fopen("/proc/self/oom_adj", "we");
1446 if (oom_adj) {
1447 fputs("-17", oom_adj);
1448 fclose(oom_adj);
1449 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001450 }
1451
Jeff Brown1dc94e32014-09-11 14:15:27 -07001452 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001453 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001454 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001455 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001456 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001457 case 'd': do_add_date = 1; break;
1458 case 'z': do_zip_file = 1; break;
1459 case 'o': use_outfile = optarg; break;
1460 case 's': use_socket = 1; break;
1461 case 'S': use_control_socket = 1; break;
1462 case 'v': show_header_only = true; break;
1463 case 'q': do_vibrate = 0; break;
1464 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001465 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001466 case 'R': is_remote_mode = 1; break;
1467 case 'B': do_broadcast = 1; break;
1468 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001469 case 'h':
1470 ShowUsageAndExit(0);
1471 break;
1472 default:
1473 fprintf(stderr, "Invalid option: %c\n", c);
1474 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001475 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001476 }
1477 }
1478
Felipe Lemed071c682016-10-20 16:48:00 -07001479 // TODO: use helper function to convert argv into a string
1480 for (int i = 0; i < argc; i++) {
1481 ds.args_ += argv[i];
1482 if (i < argc - 1) {
1483 ds.args_ += " ";
1484 }
1485 }
1486
1487 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001488 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001489 // Framework uses a system property to override some command-line args.
1490 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001491 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001492 // Currently, the dumpstate binder is only used by Shell to update progress.
1493 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001494 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001495 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001496 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001497 do_vibrate = 0;
1498 is_remote_mode = 1;
1499 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001500 } else if (ds.extra_options_ == "bugreportwear") {
lingfan44612512018-02-27 11:32:11 -08001501 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001502 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001503 } else if (ds.extra_options_ == "bugreporttelephony") {
1504 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001505 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001506 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001507 }
1508 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001509 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001510 }
1511
Naveen Kallab53a1c92017-03-16 18:17:25 -07001512 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1513 if (!ds.notification_title.empty()) {
1514 // Reset the property
1515 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1516
1517 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1518 if (!ds.notification_description.empty()) {
1519 // Reset the property
1520 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1521 }
1522 MYLOGD("notification (title: %s, description: %s)\n",
1523 ds.notification_title.c_str(), ds.notification_description.c_str());
1524 }
1525
Felipe Leme9a523ae2016-10-20 15:10:33 -07001526 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001527 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001528 }
1529
Felipe Leme2628e9e2016-04-12 16:36:51 -07001530 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001531 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001532 }
1533
Felipe Leme9a523ae2016-10-20 15:10:33 -07001534 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001535 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001536 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001537
Felipe Leme9a523ae2016-10-20 15:10:33 -07001538 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001539 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001540 }
1541
Felipe Lemed071c682016-10-20 16:48:00 -07001542 if (ds.version_ == VERSION_DEFAULT) {
1543 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001544 }
1545
Felipe Lemee184f662016-10-27 10:04:47 -07001546 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1547 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1548 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1549 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001550 exit(1);
1551 }
1552
1553 if (show_header_only) {
1554 ds.PrintHeader();
1555 exit(0);
1556 }
1557
Felipe Leme7447d7c2016-11-03 18:12:22 -07001558 /* redirect output if needed */
1559 bool is_redirecting = !use_socket && use_outfile;
1560
1561 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1562 std::string stats_path =
1563 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1564 : "";
1565 ds.progress_.reset(new Progress(stats_path));
1566
Felipe Lemed071c682016-10-20 16:48:00 -07001567 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001568 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001569 ds.id_ = ++last_id;
1570 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1571
1572 MYLOGI("begin\n");
1573
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001574 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001575
Felipe Leme75876a22016-10-27 16:31:27 -07001576 if (do_start_service) {
1577 MYLOGI("Starting 'dumpstate' service\n");
1578 android::status_t ret;
1579 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1580 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1581 }
1582 }
1583
Felipe Lemef0292972016-11-22 13:57:05 -08001584 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001585 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1586 }
1587
Felipe Leme7447d7c2016-11-03 18:12:22 -07001588 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001589 ds.extra_options_.c_str());
1590
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001591 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001592
Felipe Leme9a523ae2016-10-20 15:10:33 -07001593 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001594
Christopher Ferrised9354f2014-10-01 17:35:01 -07001595 // If we are going to use a socket, do it as early as possible
1596 // to avoid timeouts from bugreport.
1597 if (use_socket) {
1598 redirect_to_socket(stdout, "dumpstate");
1599 }
1600
Felipe Leme2628e9e2016-04-12 16:36:51 -07001601 if (use_control_socket) {
1602 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001603 ds.control_socket_fd_ = open_socket("dumpstate");
1604 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001605 }
1606
Felipe Leme71bbfc52015-11-23 14:14:51 -08001607 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001608 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001609 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001610 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001611 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1612 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001613 if (do_add_date) {
1614 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001615 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001616 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001617 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001618 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001619 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001620
1621 if (telephony_only) {
1622 ds.base_name_ += "-telephony";
1623 }
1624
Felipe Leme71bbfc52015-11-23 14:14:51 -08001625 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001626 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001627 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001628 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001629 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001630
Felipe Lemee844a9d2016-09-21 15:01:39 -07001631 MYLOGD(
1632 "Bugreport dir: %s\n"
1633 "Base name: %s\n"
1634 "Suffix: %s\n"
1635 "Log path: %s\n"
1636 "Temporary path: %s\n"
1637 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001638 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1639 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001640
Felipe Leme1e9edc62015-12-21 16:02:13 -08001641 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001642 ds.path_ = ds.GetPath(".zip");
1643 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1644 create_parent_dirs(ds.path_.c_str());
1645 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001646 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001647 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001648 do_zip_file = 0;
1649 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001650 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001651 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001652 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001653 }
1654
Felipe Leme9a523ae2016-10-20 15:10:33 -07001655 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001656 if (do_broadcast) {
1657 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001658
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001659 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001660 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001661 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001662 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001663 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001664 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001665 };
1666 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001667 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001668 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001669 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001670 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001671 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001672 }
1673 }
1674
Nick Kralevichf3599b32016-01-25 15:05:16 -08001675 /* read /proc/cmdline before dropping root */
1676 FILE *cmdline = fopen("/proc/cmdline", "re");
1677 if (cmdline) {
1678 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1679 fclose(cmdline);
1680 }
1681
John Michelau1f794c42012-09-17 11:20:19 -05001682 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001683 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001684 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001685
Felipe Leme9a523ae2016-10-20 15:10:33 -07001686 if (do_fb && ds.do_early_screenshot_) {
1687 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001688 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001689 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001690 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001691 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001692 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001693 }
1694 }
1695
Felipe Leme1e9edc62015-12-21 16:02:13 -08001696 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001697 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1698 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001699 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001700 }
1701 }
1702
Felipe Leme71bbfc52015-11-23 14:14:51 -08001703 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001704 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1705 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1706 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1707 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001708 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001709 /* TODO: rather than generating a text file now and zipping it later,
1710 it would be more efficient to redirect stdout to the zip entry
1711 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001712 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1713 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001714 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001715 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001716 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001717 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001718
1719 // Don't buffer stdout
1720 setvbuf(stdout, nullptr, _IONBF, 0);
1721
Felipe Leme608385d2016-02-01 10:35:38 -08001722 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1723 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001724 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001725 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001726
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001727 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001728 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001729 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001730 } else {
1731 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1732 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1733 // the raw trace.
1734 if (!dump_anrd_trace()) {
1735 dump_systrace();
1736 }
1737
1738 // Invoking the following dumpsys calls before dump_traces() to try and
1739 // keep the system stats as close to its initial state as possible.
1740 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1741 CommandOptions::WithTimeout(90).DropRoot().Build());
1742 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1743 CommandOptions::WithTimeout(10).DropRoot().Build());
1744
1745 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1746 dump_raft();
1747
1748 /* collect stack traces from Dalvik and native processes (needs root) */
1749 dump_traces_path = dump_traces();
1750
1751 /* Run some operations that require root. */
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -07001752 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping());
1753 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping());
Narayan Kamath8f788292017-05-25 13:20:39 +01001754
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001755 ds.AddDir(RECOVERY_DIR, true);
1756 ds.AddDir(RECOVERY_DATA_DIR, true);
Tianjie Xu75d53362018-04-11 16:42:28 -07001757 ds.AddDir(UPDATE_ENGINE_LOG_DIR, true);
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001758 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1759 if (!PropertiesHelper::IsUserBuild()) {
1760 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1761 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1762 }
1763 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001764 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001765
1766 // Capture any IPSec policies in play. No keys are exposed here.
1767 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1768 CommandOptions::WithTimeout(10).Build());
1769
1770 // Run ss as root so we can see socket marks.
1771 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1772 CommandOptions::WithTimeout(10).Build());
1773
1774 if (!DropRootUser()) {
1775 return -1;
1776 }
1777
1778 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001779 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001780
Felipe Leme55b42a62015-11-10 17:39:08 -08001781 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001782 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001783 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001784 }
1785
Felipe Leme6e01fa62015-11-11 19:35:14 -08001786 /* rename or zip the (now complete) .tmp file to its final location */
1787 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001788
1789 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001790 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001791 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001792 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001793 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001794 /* must whitelist which characters are allowed, otherwise it could cross directories */
1795 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001796 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001797 change_suffix = true;
1798 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001799 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001800 }
1801 }
1802 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001803 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1804 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001805 if (!ds.screenshot_path_.empty()) {
1806 std::string new_screenshot_path = ds.GetPath(".png");
1807 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1808 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1809 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001810 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001811 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001812 }
1813 }
1814 }
1815
Felipe Leme6e01fa62015-11-11 19:35:14 -08001816 bool do_text_file = true;
1817 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001818 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001819 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001820 do_text_file = true;
1821 } else {
1822 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001823 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001824 std::string new_path = ds.GetPath(".zip");
1825 if (ds.path_ != new_path) {
1826 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1827 if (rename(ds.path_.c_str(), new_path.c_str())) {
1828 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001829 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001830 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001831 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001832 }
1833 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001834 }
1835 }
1836 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001837 ds.path_ = ds.GetPath(".txt");
1838 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1839 ds.tmp_path_.c_str());
1840 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1841 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001842 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001843 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001844 }
1845 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001846 if (use_control_socket) {
1847 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001848 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001849 "FAIL:could not create zip file, check %s "
1850 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001851 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001852 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001853 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001854 }
1855 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001856 }
1857
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001858 /* vibrate a few but shortly times to let user know it's finished */
Takuya Ogawa47f644e2017-12-20 18:09:09 +09001859 if (do_vibrate) {
1860 for (int i = 0; i < 3; i++) {
1861 Vibrate(75);
1862 usleep((75 + 50) * 1000);
1863 }
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001864 }
1865
Jeff Brown1dc94e32014-09-11 14:15:27 -07001866 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001867 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001868 if (!ds.path_.empty()) {
1869 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001870 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001871
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001872 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001873 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001874 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001875 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001876 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001877 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1878 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001879 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001880 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001881 if (do_fb) {
1882 am_args.push_back("--es");
1883 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001884 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001885 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001886 if (!ds.notification_title.empty()) {
1887 am_args.push_back("--es");
1888 am_args.push_back("android.intent.extra.TITLE");
1889 am_args.push_back(ds.notification_title);
1890 if (!ds.notification_description.empty()) {
1891 am_args.push_back("--es");
1892 am_args.push_back("android.intent.extra.DESCRIPTION");
1893 am_args.push_back(ds.notification_description);
1894 }
1895 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001896 if (is_remote_mode) {
1897 am_args.push_back("--es");
1898 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001899 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001900 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1901 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001902 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001903 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001904 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001905 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001906 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001907 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001908 }
1909
Felipe Leme7447d7c2016-11-03 18:12:22 -07001910 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1911 ds.progress_->GetInitialMax());
1912 ds.progress_->Save();
1913 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001914
Felipe Leme107a05f2016-03-08 15:11:15 -08001915 if (is_redirecting) {
1916 fclose(stderr);
1917 }
1918
Felipe Leme9a523ae2016-10-20 15:10:33 -07001919 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001920 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001921 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001922 }
1923
Luis Hector Chavez91c2ae52018-03-14 15:12:46 -07001924 ds.tombstone_data_.clear();
1925 ds.anr_data_.clear();
Narayan Kamathd3badba2017-10-27 11:15:51 +01001926
Colin Crossf45fa6b2012-03-26 12:38:26 -07001927 return 0;
1928}