blob: 43fc5d7967f13d9e5b775785cb6112935c8e791b [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 */
16
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070017#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070018#include <errno.h>
19#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080020#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <limits.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080022#include <memory>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <regex>
Felipe Leme635ca312016-01-05 14:23:02 -080024#include <set>
Wei Liuf87959e2016-08-26 14:51:42 -070025#include <signal.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070026#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070027#include <stdio.h>
28#include <stdlib.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080029#include <string>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <string.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070031#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070032#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35#include <sys/wait.h>
36#include <unistd.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070037
Felipe Leme96c2bbb2016-09-26 09:21:21 -070038#include <android-base/file.h>
39#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080040#include <android-base/stringprintf.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070041#include <android-base/unique_fd.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Wei Liuf87959e2016-08-26 14:51:42 -070043#include <hardware_legacy/power.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044
45#include "private/android_filesystem_config.h"
46
47#define LOG_TAG "dumpstate"
Alex Ray656a6b92013-07-23 13:44:34 -070048#include <cutils/log.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070049
50#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080051#include "ziparchive/zip_writer.h"
52
Elliott Hughesc4dc1412016-04-12 16:28:31 -070053#include <openssl/sha.h>
Michal Karpinski4db754f2015-12-11 18:04:32 +000054
Colin Crossf45fa6b2012-03-26 12:38:26 -070055/* read before root is shed */
56static char cmdline_buf[16384] = "(unknown)";
57static const char *dump_traces_path = NULL;
58
Felipe Lemeefd7e272016-05-18 09:27:16 -070059// TODO: variables below should be part of dumpstate object
Felipe Lemee82a27d2016-01-05 13:35:44 -080060static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080061static std::set<std::string> mount_points;
62void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080063
Todd Poynor2a83daa2013-11-22 15:44:22 -080064#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070065#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080066
Wei Liu341938b2016-04-27 16:18:17 -070067#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080068#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070069#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070070#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010071#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
72#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070073#define TOMBSTONE_DIR "/data/tombstones"
74#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
75/* Can accomodate a tombstone number up to 9999. */
76#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
77#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090078#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070079#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070080
81typedef struct {
82 char name[TOMBSTONE_MAX_LEN];
83 int fd;
84} tombstone_data_t;
85
86static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
87
Felipe Lemee844a9d2016-09-21 15:01:39 -070088// TODO: temporary variables and functions used during C++ refactoring
89static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -070090static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
91 const CommandOptions& options = CommandOptions::DEFAULT) {
92 return ds.RunCommand(title, fullCommand, options);
93}
94static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
95 const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
96 long dumpsysTimeout = 0) {
97 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
98}
99static int DumpFile(const std::string& title, const std::string& path) {
100 return ds.DumpFile(title, path);
101}
Felipe Leme6ad9c062016-09-28 11:58:36 -0700102bool IsUserBuild() {
103 return ds.IsUserBuild();
104}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800105
Felipe Lemee844a9d2016-09-21 15:01:39 -0700106// Relative directory (inside the zip) for all files copied as-is into the bugreport.
107static const std::string ZIP_ROOT_DIR = "FS";
108
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700109static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700110static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700111
Felipe Leme3d305a12016-05-20 11:24:37 -0700112/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
113 * otherwise, gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700114static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700115 time_t thirty_minutes_ago = ds.now_ - 60 * 30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700116 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
117 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800118 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
119 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700120 struct stat st;
Felipe Leme3d305a12016-05-20 11:24:37 -0700121 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800122 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
Felipe Leme3d305a12016-05-20 11:24:37 -0700123 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700124 } else {
Felipe Leme3d305a12016-05-20 11:24:37 -0700125 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700126 data[i].fd = -1;
127 }
128 }
129}
130
Felipe Leme635ca312016-01-05 14:23:02 -0800131// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700132void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800133 char path[PATH_MAX];
134
135 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
136 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700137 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800138 char linkname[PATH_MAX];
139 ssize_t r = readlink(path, linkname, PATH_MAX);
140 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800141 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800142 return;
143 }
144 linkname[r] = '\0';
145
146 if (mount_points.find(linkname) == mount_points.end()) {
147 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700148 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800149 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
150 mount_points.insert(linkname);
151 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800152 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800153 }
154 }
155}
156
157void add_mountinfo() {
158 if (!zip_writer) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700159 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800160 mount_points.clear();
Felipe Leme678727a2016-09-21 17:22:11 -0700161 DurationReporter durationReporter(title, nullptr);
162 for_each_pid(do_mountinfo, nullptr);
163 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800164}
165
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700166static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
167{
168 DIR *d;
169 struct dirent *de;
170 char path[PATH_MAX];
171
172 d = opendir(driverpath);
173 if (d == NULL) {
174 return;
175 }
176
177 while ((de = readdir(d))) {
178 if (de->d_type != DT_LNK) {
179 continue;
180 }
181 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700182 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700183 }
184
185 closedir(d);
186}
187
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700188// return pid of a userspace process. If not found or error, return 0.
189static unsigned int pid_of_process(const char* ps_name) {
190 DIR *proc_dir;
191 struct dirent *ps;
192 unsigned int pid;
193 std::string cmdline;
194
195 if (!(proc_dir = opendir("/proc"))) {
196 MYLOGE("Can't open /proc\n");
197 return 0;
198 }
199
200 while ((ps = readdir(proc_dir))) {
201 if (!(pid = atoi(ps->d_name))) {
202 continue;
203 }
204 android::base::ReadFileToString("/proc/"
205 + std::string(ps->d_name) + "/cmdline", &cmdline);
206 if (cmdline.find(ps_name) == std::string::npos) {
207 continue;
208 } else {
209 closedir(proc_dir);
210 return pid;
211 }
212 }
213 closedir(proc_dir);
214 return 0;
215}
216
217// dump anrd's trace and add to the zip file.
218// 1. check if anrd is running on this device.
219// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
220// 3. wait until the trace generation completes and add to the zip file.
221static bool dump_anrd_trace() {
222 unsigned int pid;
223 char buf[50], path[PATH_MAX];
224 struct dirent *trace;
225 struct stat st;
226 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700227 int retry = 5;
228 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700229 long long cur_size = 0;
230 const char *trace_path = "/data/misc/anrd/";
231
232 if (!zip_writer) {
233 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
234 return false;
235 }
236
237 // find anrd's pid if it is running.
238 pid = pid_of_process("/system/xbin/anrd");
239
240 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700241 if (stat(trace_path, &st) == 0) {
242 old_mtime = st.st_mtime;
243 } else {
244 MYLOGE("Failed to find: %s\n", trace_path);
245 return false;
246 }
247
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700248 // send SIGUSR1 to the anrd to generate a trace.
249 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700250 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700251 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700252 MYLOGE("anrd signal timed out. Please manually collect trace\n");
253 return false;
254 }
255
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700256 while (retry-- > 0 && old_mtime == st.st_mtime) {
257 sleep(1);
258 stat(trace_path, &st);
259 }
260
261 if (retry < 0 && old_mtime == st.st_mtime) {
262 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
263 return false;
264 }
265
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700266 // identify the trace file by its creation time.
267 if (!(trace_dir = opendir(trace_path))) {
268 MYLOGE("Can't open trace file under %s\n", trace_path);
269 }
270 while ((trace = readdir(trace_dir))) {
271 if (strcmp(trace->d_name, ".") == 0
272 || strcmp(trace->d_name, "..") == 0) {
273 continue;
274 }
275 sprintf(path, "%s%s", trace_path, trace->d_name);
276 if (stat(path, &st) == 0) {
277 if (st.st_ctime > max_ctime) {
278 max_ctime = st.st_ctime;
279 sprintf(buf, "%s", trace->d_name);
280 }
281 }
282 }
283 closedir(trace_dir);
284
285 // Wait until the dump completes by checking the size of the trace.
286 if (max_ctime > 0) {
287 sprintf(path, "%s%s", trace_path, buf);
288 while(true) {
289 sleep(1);
290 if (stat(path, &st) == 0) {
291 if (st.st_size == cur_size) {
292 break;
293 } else if (st.st_size > cur_size) {
294 cur_size = st.st_size;
295 } else {
296 return false;
297 }
298 } else {
299 MYLOGE("Cant stat() %s anymore\n", path);
300 return false;
301 }
302 }
303 // Add to the zip file.
304 if (!add_zip_entry("anrd_trace.txt", path)) {
305 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
306 } else {
307 if (remove(path)) {
308 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
309 }
310 return true;
311 }
312 } else {
313 MYLOGE("Can't stats any trace file under %s\n", trace_path);
314 }
315 }
316 return false;
317}
318
Felipe Lemeefd7e272016-05-18 09:27:16 -0700319static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700320 if (!zip_writer) {
321 MYLOGD("Not dumping systrace because zip_writer is not set\n");
322 return;
323 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700324 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700325 if (systrace_path.empty()) {
326 MYLOGE("Not dumping systrace because path is empty\n");
327 return;
328 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700329 const char* path = "/sys/kernel/debug/tracing/tracing_on";
330 long int is_tracing;
331 if (read_file_as_long(path, &is_tracing)) {
332 return; // error already logged
333 }
334 if (is_tracing <= 0) {
335 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
336 return;
337 }
338
Felipe Leme14e034a2016-03-30 18:51:03 -0700339 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
340 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700341 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700342 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700343 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700344 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700345 // peacefully; ideally, we should call strace to stop itself, but there is no such option
346 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700347 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700348 // MYLOGE("could not stop systrace ");
349 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700350 }
351 if (!add_zip_entry("systrace.txt", systrace_path)) {
352 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700353 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700354 if (remove(systrace_path.c_str())) {
355 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
356 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700357 }
358}
359
Felipe Lemeefd7e272016-05-18 09:27:16 -0700360static void dump_raft() {
Felipe Leme6ad9c062016-09-28 11:58:36 -0700361 if (IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700362 return;
363 }
364
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700365 std::string raft_log_path = ds.GetPath("-raft_log.txt");
Wei Liu341938b2016-04-27 16:18:17 -0700366 if (raft_log_path.empty()) {
367 MYLOGD("raft_log_path is empty\n");
368 return;
369 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700370
371 struct stat s;
372 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
373 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
374 return;
375 }
376
Felipe Leme30dbfa12016-09-02 12:43:26 -0700377 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Wei Liu341938b2016-04-27 16:18:17 -0700378 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700379 // Write compressed and encoded raft logs to stdout if not zip_writer.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700380 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700381 return;
382 }
383
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700384 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_log_path}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700385 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
386 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
387 } else {
388 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700389 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700390 }
391 }
392}
393
Mark Salyzyn326842f2015-04-30 09:49:41 -0700394static bool skip_not_stat(const char *path) {
395 static const char stat[] = "/stat";
396 size_t len = strlen(path);
397 if (path[len - 1] == '/') { /* Directory? */
398 return false;
399 }
400 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
401}
402
Felipe Leme4c2d6632016-09-28 14:32:00 -0700403static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800404 return false;
405}
406
Mark Salyzyn326842f2015-04-30 09:49:41 -0700407static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700408unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700409
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800410//
411// stat offsets
412// Name units description
413// ---- ----- -----------
414// read I/Os requests number of read I/Os processed
415#define __STAT_READ_IOS 0
416// read merges requests number of read I/Os merged with in-queue I/O
417#define __STAT_READ_MERGES 1
418// read sectors sectors number of sectors read
419#define __STAT_READ_SECTORS 2
420// read ticks milliseconds total wait time for read requests
421#define __STAT_READ_TICKS 3
422// write I/Os requests number of write I/Os processed
423#define __STAT_WRITE_IOS 4
424// write merges requests number of write I/Os merged with in-queue I/O
425#define __STAT_WRITE_MERGES 5
426// write sectors sectors number of sectors written
427#define __STAT_WRITE_SECTORS 6
428// write ticks milliseconds total wait time for write requests
429#define __STAT_WRITE_TICKS 7
430// in_flight requests number of I/Os currently in flight
431#define __STAT_IN_FLIGHT 8
432// io_ticks milliseconds total time this block device has been active
433#define __STAT_IO_TICKS 9
434// time_in_queue milliseconds total wait time for all requests
435#define __STAT_IN_QUEUE 10
436#define __STAT_NUMBER_FIELD 11
437//
438// read I/Os, write I/Os
439// =====================
440//
441// These values increment when an I/O request completes.
442//
443// read merges, write merges
444// =========================
445//
446// These values increment when an I/O request is merged with an
447// already-queued I/O request.
448//
449// read sectors, write sectors
450// ===========================
451//
452// These values count the number of sectors read from or written to this
453// block device. The "sectors" in question are the standard UNIX 512-byte
454// sectors, not any device- or filesystem-specific block size. The
455// counters are incremented when the I/O completes.
456#define SECTOR_SIZE 512
457//
458// read ticks, write ticks
459// =======================
460//
461// These values count the number of milliseconds that I/O requests have
462// waited on this block device. If there are multiple I/O requests waiting,
463// these values will increase at a rate greater than 1000/second; for
464// example, if 60 read requests wait for an average of 30 ms, the read_ticks
465// field will increase by 60*30 = 1800.
466//
467// in_flight
468// =========
469//
470// This value counts the number of I/O requests that have been issued to
471// the device driver but have not yet completed. It does not include I/O
472// requests that are in the queue but not yet issued to the device driver.
473//
474// io_ticks
475// ========
476//
477// This value counts the number of milliseconds during which the device has
478// had I/O requests queued.
479//
480// time_in_queue
481// =============
482//
483// This value counts the number of milliseconds that I/O requests have waited
484// on this block device. If there are multiple I/O requests waiting, this
485// value will increase as the product of the number of milliseconds times the
486// number of requests waiting (see "read ticks" above for an example).
487#define S_TO_MS 1000
488//
489
Mark Salyzyn326842f2015-04-30 09:49:41 -0700490static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800491 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700492 bool z;
493 char *cp, *buffer = NULL;
494 size_t i = 0;
495 FILE *fp = fdopen(fd, "rb");
496 getline(&buffer, &i, fp);
497 fclose(fp);
498 if (!buffer) {
499 return -errno;
500 }
501 i = strlen(buffer);
502 while ((i > 0) && (buffer[i - 1] == '\n')) {
503 buffer[--i] = '\0';
504 }
505 if (!*buffer) {
506 free(buffer);
507 return 0;
508 }
509 z = true;
510 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800511 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700512 if (fields[i] != 0) {
513 z = false;
514 }
515 }
516 if (z) { /* never accessed */
517 free(buffer);
518 return 0;
519 }
520
521 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
522 path += sizeof(mmcblk0) - 1;
523 }
524
525 printf("%s: %s\n", path, buffer);
526 free(buffer);
527
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800528 if (fields[__STAT_IO_TICKS]) {
529 unsigned long read_perf = 0;
530 unsigned long read_ios = 0;
531 if (fields[__STAT_READ_TICKS]) {
532 unsigned long long divisor = fields[__STAT_READ_TICKS]
533 * fields[__STAT_IO_TICKS];
534 read_perf = ((unsigned long long)SECTOR_SIZE
535 * fields[__STAT_READ_SECTORS]
536 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
537 / divisor;
538 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
539 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
540 / divisor;
541 }
542
543 unsigned long write_perf = 0;
544 unsigned long write_ios = 0;
545 if (fields[__STAT_WRITE_TICKS]) {
546 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
547 * fields[__STAT_IO_TICKS];
548 write_perf = ((unsigned long long)SECTOR_SIZE
549 * fields[__STAT_WRITE_SECTORS]
550 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
551 / divisor;
552 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
553 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
554 / divisor;
555 }
556
557 unsigned queue = (fields[__STAT_IN_QUEUE]
558 + (fields[__STAT_IO_TICKS] >> 1))
559 / fields[__STAT_IO_TICKS];
560
561 if (!write_perf && !write_ios) {
562 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
563 path, read_perf, read_ios, queue);
564 } else {
565 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
566 path, read_perf, read_ios, write_perf, write_ios, queue);
567 }
568
569 /* bugreport timeout factor adjustment */
570 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
571 worst_write_perf = write_perf;
572 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700573 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700574 return 0;
575}
576
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700577/* Copied policy from system/core/logd/LogBuffer.cpp */
578
579#define LOG_BUFFER_SIZE (256 * 1024)
580#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
581#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
582
583static bool valid_size(unsigned long value) {
584 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
585 return false;
586 }
587
588 long pages = sysconf(_SC_PHYS_PAGES);
589 if (pages < 1) {
590 return true;
591 }
592
593 long pagesize = sysconf(_SC_PAGESIZE);
594 if (pagesize <= 1) {
595 pagesize = PAGE_SIZE;
596 }
597
598 // maximum memory impact a somewhat arbitrary ~3%
599 pages = (pages + 31) / 32;
600 unsigned long maximum = pages * pagesize;
601
602 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
603 return true;
604 }
605
606 return value <= maximum;
607}
608
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700609// TODO: migrate to logd/LogBuffer.cpp or use android::base::GetProperty
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700610static unsigned long property_get_size(const char *key) {
611 unsigned long value;
612 char *cp, property[PROPERTY_VALUE_MAX];
613
614 property_get(key, property, "");
615 value = strtoul(property, &cp, 10);
616
617 switch(*cp) {
618 case 'm':
619 case 'M':
620 value *= 1024;
621 /* FALLTHRU */
622 case 'k':
623 case 'K':
624 value *= 1024;
625 /* FALLTHRU */
626 case '\0':
627 break;
628
629 default:
630 value = 0;
631 }
632
633 if (!valid_size(value)) {
634 value = 0;
635 }
636
637 return value;
638}
639
640/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800641static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700642 static const char global_tuneable[] = "persist.logd.size"; // Settings App
643 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
644 char key[PROP_NAME_MAX];
645 unsigned long property_size, default_size;
646
647 default_size = property_get_size(global_tuneable);
648 if (!default_size) {
649 default_size = property_get_size(global_default);
650 }
651
652 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
653 property_size = property_get_size(key);
654
655 if (!property_size) {
656 snprintf(key, sizeof(key), "%s.%s", global_default, name);
657 property_size = property_get_size(key);
658 }
659
660 if (!property_size) {
661 property_size = default_size;
662 }
663
664 if (!property_size) {
665 property_size = LOG_BUFFER_SIZE;
666 }
667
668 /* Engineering margin is ten-fold our guess */
669 return 10 * (property_size + worst_write_perf) / worst_write_perf;
670}
671
672/* End copy from system/core/logd/LogBuffer.cpp */
673
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700674// TODO: move to utils.cpp
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700675void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700676 std::string build, fingerprint, radio, bootloader, network;
677 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700678
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700679 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
680 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700681 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
682 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
683 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700684 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700685
686 printf("========================================================\n");
687 printf("== dumpstate: %s\n", date);
688 printf("========================================================\n");
689
690 printf("\n");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700691 printf("Build: %s\n", build.c_str());
692 // NOTE: fingerprint entry format is important for other tools.
693 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
694 printf("Bootloader: %s\n", bootloader.c_str());
695 printf("Radio: %s\n", radio.c_str());
696 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700697
698 printf("Kernel: ");
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700699 JustDumpFile("", "/proc/version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700700 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700701 printf("Bugreport format version: %s\n", version_.c_str());
702 printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", id_, getpid(),
703 dryRun_, args_.c_str(), extraOptions_.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700704 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800705}
706
Felipe Leme24b66ee2016-06-16 10:55:26 -0700707// List of file extensions that can cause a zip file attachment to be rejected by some email
708// service providers.
709static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
710 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
711 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
712 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
713};
714
Felipe Leme71ca15e2016-05-19 16:18:17 -0700715bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800716 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800717 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
718 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800719 return false;
720 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700721 std::string valid_name = entry_name;
722
723 // Rename extension if necessary.
724 size_t idx = entry_name.rfind(".");
725 if (idx != std::string::npos) {
726 std::string extension = entry_name.substr(idx);
727 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
728 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
729 valid_name = entry_name + ".renamed";
730 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
731 }
732 }
733
Felipe Leme6fe9db62016-02-12 09:04:16 -0800734 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
735 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700736 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
737 get_mtime(fd, ds.now_));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800738 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700739 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800740 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800741 return false;
742 }
743
Felipe Leme770410d2016-01-26 17:07:14 -0800744 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800745 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400746 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800747 if (bytes_read == 0) {
748 break;
749 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800750 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800751 return false;
752 }
753 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
754 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800755 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800756 return false;
757 }
758 }
759
760 err = zip_writer->FinishEntry();
761 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800762 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800763 return false;
764 }
765
766 return true;
767}
768
Felipe Leme71ca15e2016-05-19 16:18:17 -0700769bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700770 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
771 | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700772 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800773 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800774 return false;
775 }
776
777 return add_zip_entry_from_fd(entry_name, fd.get());
778}
779
780/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700781static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800782 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
783}
784
Felipe Leme24b66ee2016-06-16 10:55:26 -0700785// TODO: move to util.cpp
Felipe Leme678727a2016-09-21 17:22:11 -0700786void add_dir(const std::string& dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800787 if (!zip_writer) {
Felipe Leme678727a2016-09-21 17:22:11 -0700788 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800789 return;
790 }
Felipe Leme678727a2016-09-21 17:22:11 -0700791 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
792 DurationReporter durationReporter(dir, nullptr);
793 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800794}
795
Felipe Leme809d74e2016-02-02 12:57:00 -0800796/* adds a text entry entry to the existing zip file. */
797static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800798 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800799 MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800800 return false;
801 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800802 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700803 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme809d74e2016-02-02 12:57:00 -0800804 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800805 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800806 ZipWriter::ErrorCodeString(err));
807 return false;
808 }
809
810 err = zip_writer->WriteBytes(content.c_str(), content.length());
811 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800812 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800813 ZipWriter::ErrorCodeString(err));
814 return false;
815 }
816
817 err = zip_writer->FinishEntry();
818 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800819 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800820 return false;
821 }
822
823 return true;
824}
825
Felipe Lemec0808152016-06-17 17:37:13 -0700826static void dump_iptables() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700827 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
828 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900829 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700830 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900831 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
832 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
833 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
834 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700835}
836
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700837static void dumpstate() {
Felipe Leme678727a2016-09-21 17:22:11 -0700838 DurationReporter durationReporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800839 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700840
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700841 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700842 RunCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -0700843 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800844 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700845 DumpFile("MEMORY INFO", "/proc/meminfo");
846 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700847 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700848 RunCommand("PROCRANK", {"procrank"}, CommandOptions::AS_ROOT_20);
849 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
850 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
851 DumpFile("SLAB INFO", "/proc/slabinfo");
852 DumpFile("ZONEINFO", "/proc/zoneinfo");
853 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
854 DumpFile("BUDDYINFO", "/proc/buddyinfo");
855 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700856
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700857 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
858 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
859 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700860
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700861 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700862 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700863 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT_10);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700864
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700865 RunCommand("PRINTENV", {"printenv"});
866 RunCommand("NETSTAT", {"netstat", "-n"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700867 struct stat s;
868 if (stat("/proc/modules", &s) != 0) {
869 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
870 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700871 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700872 }
Michal Karpinski4db754f2015-12-11 18:04:32 +0000873
Colin Crossf45fa6b2012-03-26 12:38:26 -0700874 do_dmesg();
875
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700876 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT_10);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700877 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
878 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800879 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700880
Ajay Panickerd886ec42016-09-14 12:26:46 -0700881 /* Dump Bluetooth HCI logs */
882 add_dir("/data/misc/bluetooth/logs", true);
883
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700884 if (!ds.doEarlyScreenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800885 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700886 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -0700887 }
888
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700889 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700890 // calculate timeout
891 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
892 if (timeout < 20000) {
893 timeout = 20000;
894 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700895 RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700896 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800897 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700898 if (timeout < 20000) {
899 timeout = 20000;
900 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700901 RunCommand("EVENT LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700902 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
903 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700904 timeout = logcat_timeout("radio");
905 if (timeout < 20000) {
906 timeout = 20000;
907 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700908 RunCommand("RADIO LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700909 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
910 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700911
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700912 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
Mark Salyzynecc07632015-07-30 14:57:09 -0700913
Colin Crossf45fa6b2012-03-26 12:38:26 -0700914 /* show the traces we collected in main(), if that was done */
915 if (dump_traces_path != NULL) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700916 DumpFile("VM TRACES JUST NOW", dump_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700917 }
918
919 /* only show ANR traces if they're less than 15 minutes old */
920 struct stat st;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700921 std::string anrTracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
922 if (anrTracesPath.empty()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700923 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700924 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700925 int fd = TEMP_FAILURE_RETRY(
926 open(anrTracesPath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
927 if (fd < 0) {
928 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anrTracesPath.c_str(), strerror(errno));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700929 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700930 dump_file_from_fd("VM TRACES AT LAST ANR", anrTracesPath.c_str(), fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700931 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700932 }
933
934 /* slow traces for slow operations */
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700935 if (!anrTracesPath.empty()) {
936 int tail = anrTracesPath.size() - 1;
937 while (tail > 0 && anrTracesPath.at(tail) != '/') {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700938 tail--;
939 }
940 int i = 0;
941 while (1) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700942 anrTracesPath =
943 anrTracesPath.substr(0, tail + 1) + android::base::StringPrintf("slow%02d.txt", i);
944 if (stat(anrTracesPath.c_str(), &st)) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700945 // No traces file at this index, done with the files.
946 break;
947 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700948 DumpFile("VM TRACES WHEN SLOW", anrTracesPath.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700949 i++;
950 }
951 }
952
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700953 int dumped = 0;
954 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
955 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800956 const char *name = tombstone_data[i].name;
957 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700958 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800959 if (zip_writer) {
960 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800961 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800962 }
963 } else {
964 dump_file_from_fd("TOMBSTONE", name, fd);
965 }
966 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700967 tombstone_data[i].fd = -1;
968 }
969 }
970 if (!dumped) {
971 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
972 }
973
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700974 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
975 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
976 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
977 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
978 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700979
Todd Poynor2a83daa2013-11-22 15:44:22 -0800980 if (!stat(PSTORE_LAST_KMSG, &st)) {
981 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700982 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700983 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700984 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -0800985 } else {
986 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700987 DumpFile("LAST KMSG", "/proc/last_kmsg");
Todd Poynor2a83daa2013-11-22 15:44:22 -0800988 }
989
Mark Salyzyn2262c162014-12-16 09:09:26 -0800990 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700991 RunCommand("LAST LOGCAT",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700992 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
Mark Salyzyn2262c162014-12-16 09:09:26 -0800993
Colin Crossf45fa6b2012-03-26 12:38:26 -0700994 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -0800995
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700996 RunCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +0900997
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700998 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
999 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001000
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001001 RunCommand("IP RULES", {"ip", "rule", "show"});
1002 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001003
1004 dump_route_tables();
1005
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001006 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1007 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1008 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1009 RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001010 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001011
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001012#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001013 RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001014
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001015 RunCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001016
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001017 RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001018
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001019#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001020 DumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001021
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001022 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001023 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001024
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001025#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001026 RunCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001027
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001028 RunCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001029
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001030 RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001031#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001032 DumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001033
1034 print_properties();
1035
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001036 RunCommand("VOLD DUMP", {"vdc", "dump"});
1037 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001038
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001039 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001040
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001041 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001042
1043 printf("------ BACKLIGHTS ------\n");
1044 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001045 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001046 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001047 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001048 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001049 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001050 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001051 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001052 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001053 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001054 printf("\n");
1055
1056 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001057 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1058 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1059 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1060 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1061 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001062
Colin Crossf45fa6b2012-03-26 12:38:26 -07001063 printf("========================================================\n");
1064 printf("== Board\n");
1065 printf("========================================================\n");
1066
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001067 {
1068 DurationReporter tmpDr("dumpstate_board()");
1069 dumpstate_board();
1070 printf("\n");
1071 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001072
1073 /* Migrate the ril_dumpstate to a dumpstate_board()? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001074 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1075 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001076 // su does not exist on user builds, so try running without it.
1077 // This way any implementations of vril-dump that do not require
1078 // root can run on user builds.
1079 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001080 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001081 if (!IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001082 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001083 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001084 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001085 }
1086
1087 printf("========================================================\n");
1088 printf("== Android Framework Services\n");
1089 printf("========================================================\n");
1090
Felipe Leme5bcce572016-09-27 09:21:08 -07001091 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1092 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001093
1094 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001095 printf("== Checkins\n");
1096 printf("========================================================\n");
1097
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001098 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1099 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1100 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1101 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1102 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1103 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001104
1105 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001106 printf("== Running Application Activities\n");
1107 printf("========================================================\n");
1108
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001109 RunDumpsys("APP ACTIVITIES", {"activity", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001110
1111 printf("========================================================\n");
1112 printf("== Running Application Services\n");
1113 printf("========================================================\n");
1114
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001115 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001116
1117 printf("========================================================\n");
1118 printf("== Running Application Providers\n");
1119 printf("========================================================\n");
1120
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001121 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001122
1123 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001124 printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_,
1125 ds.weightTotal_, WEIGHT_TOTAL);
Felipe Leme608385d2016-02-01 10:35:38 -08001126 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001127 printf("== dumpstate: done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001128 printf("========================================================\n");
1129}
1130
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001131static void ShowUsageAndExit(int exitCode = 1) {
1132 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001133 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001134 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1135 " -h: display this help message\n"
1136 " -b: play sound file instead of vibrate, at beginning of job\n"
1137 " -e: play sound file instead of vibrate, at end of job\n"
1138 " -o: write to file (instead of stdout)\n"
1139 " -d: append date to filename (requires -o)\n"
1140 " -p: capture screenshot to filename.png (requires -o)\n"
1141 " -z: generate zipped file (requires -o)\n"
1142 " -s: write output to control socket (for init)\n"
1143 " -S: write file location to control socket (for init; requires -o and -z)"
1144 " -q: disable vibrate\n"
1145 " -B: send broadcast when finished (requires -o)\n"
1146 " -P: send broadcast when started and update system properties on "
1147 "progress (requires -o and -B)\n"
1148 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1149 "shouldn't be used with -P)\n"
1150 " -V: sets the bugreport format version (valid values: %s)\n",
1151 VERSION_DEFAULT.c_str());
1152 exit(exitCode);
1153}
1154
1155static void ExitOnInvalidArgs() {
1156 fprintf(stderr, "invalid combination of args\n");
1157 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001158}
1159
Wei Liuf87959e2016-08-26 14:51:42 -07001160static void wake_lock_releaser() {
1161 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1162 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1163 } else {
1164 MYLOGD("Wake lock released.\n");
1165 }
1166}
1167
Felipe Leme4c2d6632016-09-28 14:32:00 -07001168static void sig_handler(int signo __attribute__((unused))) {
Wei Liuf87959e2016-08-26 14:51:42 -07001169 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001170 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001171}
1172
Wei Liuf87959e2016-08-26 14:51:42 -07001173static void register_sig_handler() {
1174 struct sigaction sa;
1175 sigemptyset(&sa.sa_mask);
1176 sa.sa_flags = 0;
1177 sa.sa_handler = sig_handler;
1178 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1179 sigaction(SIGSEGV, &sa, NULL); // segment fault
1180 sigaction(SIGINT, &sa, NULL); // ctrl-c
1181 sigaction(SIGTERM, &sa, NULL); // killed
1182 sigaction(SIGQUIT, &sa, NULL); // quit
1183}
1184
Felipe Leme1e9edc62015-12-21 16:02:13 -08001185/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1186 temporary file.
1187 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001188static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001189 const std::string& log_path) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001190 // Final timestamp
1191 char date[80];
1192 time_t the_real_now_please_stand_up = time(nullptr);
1193 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001194 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001195 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001196
Felipe Lemee82a27d2016-01-05 13:35:44 -08001197 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001198 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001199 return false;
1200 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001201 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001202 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001203 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001204 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001205
Felipe Leme0f3fb202016-06-10 17:10:53 -07001206 // Add log file (which contains stderr output) to zip...
1207 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1208 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1209 MYLOGE("Failed to add dumpstate log to .zip file\n");
1210 return false;
1211 }
1212 // ... and re-opens it for further logging.
1213 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1214 fprintf(stderr, "\n");
1215
Felipe Lemee82a27d2016-01-05 13:35:44 -08001216 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001217 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001218 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001219 return false;
1220 }
1221
Felipe Leme6ad9c062016-09-28 11:58:36 -07001222 if (IsUserBuild()) {
Felipe Lemec4eee562016-04-21 15:42:55 -07001223 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1224 if (remove(bugreport_path.c_str())) {
1225 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1226 }
1227 } else {
1228 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1229 }
1230
Felipe Leme1e9edc62015-12-21 16:02:13 -08001231 return true;
1232}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001233
Michal Karpinski4db754f2015-12-11 18:04:32 +00001234static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001235 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1236 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001237 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001238 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001239 return NULL;
1240 }
1241
1242 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001243 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001244
1245 std::vector<uint8_t> buffer(65536);
1246 while (1) {
1247 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1248 if (bytes_read == 0) {
1249 break;
1250 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001251 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001252 return NULL;
1253 }
1254
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001255 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001256 }
1257
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001258 uint8_t hash[SHA256_DIGEST_LENGTH];
1259 SHA256_Final(hash, &ctx);
1260
1261 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1262 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001263 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001264 }
1265 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1266 return std::string(hash_buffer);
1267}
1268
Colin Crossf45fa6b2012-03-26 12:38:26 -07001269int main(int argc, char *argv[]) {
1270 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001271 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001272 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001273 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001274 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001275 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001276 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001277 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001278 int is_remote_mode = 0;
Felipe Lemee82a27d2016-01-05 13:35:44 -08001279
Felipe Lemecbce55d2016-02-08 09:53:18 -08001280 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001281
Wei Liuf87959e2016-08-26 14:51:42 -07001282 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1283 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1284 } else {
1285 MYLOGD("Wake lock acquired.\n");
1286 atexit(wake_lock_releaser);
1287 register_sig_handler();
1288 }
1289
Felipe Leme4c2d6632016-09-28 14:32:00 -07001290 if (ds.IsDryRun()) {
Felipe Leme8268ed22016-08-02 18:18:25 -07001291 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1292 }
1293
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001294 // TODO: use helper function to convert argv into a string
Felipe Leme30dbfa12016-09-02 12:43:26 -07001295 for (int i = 0; i < argc; i++) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001296 ds.args_ += argv[i];
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001297 if (i < argc - 1) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001298 ds.args_ += " ";
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001299 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001300 }
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001301
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001302 ds.extraOptions_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1303 MYLOGI("Dumpstate args: %s (extra options: %s)\n", ds.args_.c_str(), ds.extraOptions_.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -07001304
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001305 /* gets the sequential id */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001306 int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemee844a9d2016-09-21 15:01:39 -07001307 ds.id_ = ++lastId;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001308 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001309 MYLOGI("dumpstate id: %lu\n", ds.id_);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001310
Colin Crossf45fa6b2012-03-26 12:38:26 -07001311 /* set as high priority, and protect from OOM killer */
1312 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001313
1314 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001315 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001316 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001317 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001318 } else {
1319 /* fallback to kernels <= 2.6.35 */
1320 oom_adj = fopen("/proc/self/oom_adj", "we");
1321 if (oom_adj) {
1322 fputs("-17", oom_adj);
1323 fclose(oom_adj);
1324 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001325 }
1326
Jeff Brown1dc94e32014-09-11 14:15:27 -07001327 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001328 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001329 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001330 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001331 // clang-format off
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001332 case 'd': do_add_date = 1; break;
1333 case 'z': do_zip_file = 1; break;
1334 case 'o': use_outfile = optarg; break;
1335 case 's': use_socket = 1; break;
1336 case 'S': use_control_socket = 1; break;
1337 case 'v': break; // compatibility no-op
1338 case 'q': do_vibrate = 0; break;
1339 case 'p': do_fb = 1; break;
1340 case 'P': ds.updateProgress_ = true; break;
1341 case 'R': is_remote_mode = 1; break;
1342 case 'B': do_broadcast = 1; break;
1343 case 'V': ds.version_ = optarg; break;
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001344 case 'h':
1345 ShowUsageAndExit(0);
1346 break;
1347 default:
1348 fprintf(stderr, "Invalid option: %c\n", c);
1349 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001350 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001351 }
1352 }
1353
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001354 if (!ds.extraOptions_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001355 // Framework uses a system property to override some command-line args.
1356 // Currently, it contains the type of the requested bugreport.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001357 if (ds.extraOptions_ == "bugreportplus") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001358 MYLOGD("Running as bugreportplus: add -P, remove -p\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001359 ds.updateProgress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001360 do_fb = 0;
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001361 } else if (ds.extraOptions_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001362 MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
1363 do_vibrate = 0;
1364 is_remote_mode = 1;
1365 do_fb = 0;
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001366 } else if (ds.extraOptions_ == "bugreportwear") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001367 MYLOGD("Running as bugreportwear: add -P\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001368 ds.updateProgress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001369 } else {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001370 MYLOGE("Unknown extra option: %s\n", ds.extraOptions_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001371 }
1372 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001373 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001374 }
1375
Felipe Lemee844a9d2016-09-21 15:01:39 -07001376 if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001377 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001378 }
1379
Felipe Leme2628e9e2016-04-12 16:36:51 -07001380 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001381 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001382 }
1383
Felipe Lemee844a9d2016-09-21 15:01:39 -07001384 if (ds.updateProgress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001385 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001386 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001387
Felipe Lemee844a9d2016-09-21 15:01:39 -07001388 if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001389 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001390 }
1391
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001392 if (ds.version_ != VERSION_DEFAULT) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001393 ShowUsageAndExit();
Felipe Leme809d74e2016-02-02 12:57:00 -08001394 }
1395
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001396 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001397
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001398 ds.doEarlyScreenshot_ = ds.updateProgress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001399
Christopher Ferrised9354f2014-10-01 17:35:01 -07001400 // If we are going to use a socket, do it as early as possible
1401 // to avoid timeouts from bugreport.
1402 if (use_socket) {
1403 redirect_to_socket(stdout, "dumpstate");
1404 }
1405
Felipe Leme2628e9e2016-04-12 16:36:51 -07001406 if (use_control_socket) {
1407 MYLOGD("Opening control socket\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001408 ds.controlSocketFd_ = open_socket("dumpstate");
1409 ds.updateProgress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001410 }
1411
Felipe Lemecbce55d2016-02-08 09:53:18 -08001412 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001413 std::string tmp_path;
1414
Felipe Leme0f3fb202016-06-10 17:10:53 -07001415 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001416 std::string log_path;
1417
Felipe Leme71bbfc52015-11-23 14:14:51 -08001418 /* pointer to the actual path, be it zip or text */
1419 std::string path;
1420
Felipe Leme635ca312016-01-05 14:23:02 -08001421 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001422 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001423
Felipe Lemead5f6c42015-11-30 14:26:46 -08001424 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001425 bool is_redirecting = !use_socket && use_outfile;
1426
1427 if (is_redirecting) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001428 ds.bugreportDir_ = dirname(use_outfile);
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001429 ds.baseName_ = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001430 if (do_add_date) {
1431 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001432 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001433 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001434 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001435 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001436 }
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001437 std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001438 ds.baseName_ = ds.baseName_ + "-" + buildId;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001439 if (do_fb) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001440 ds.screenshotPath_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001441 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001442 tmp_path = ds.GetPath(".tmp");
1443 log_path = ds.GetPath("-dumpstate_log-" + std::to_string(getpid()) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001444
Felipe Lemee844a9d2016-09-21 15:01:39 -07001445 MYLOGD(
1446 "Bugreport dir: %s\n"
1447 "Base name: %s\n"
1448 "Suffix: %s\n"
1449 "Log path: %s\n"
1450 "Temporary path: %s\n"
1451 "Screenshot path: %s\n",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001452 ds.bugreportDir_.c_str(), ds.baseName_.c_str(), ds.name_.c_str(), log_path.c_str(),
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001453 tmp_path.c_str(), ds.screenshotPath_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001454
Felipe Leme1e9edc62015-12-21 16:02:13 -08001455 if (do_zip_file) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001456 path = ds.GetPath(".zip");
Felipe Leme26bd34c2016-03-15 13:40:33 -07001457 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001458 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001459 zip_file.reset(fopen(path.c_str(), "wb"));
1460 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001461 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001462 do_zip_file = 0;
1463 } else {
1464 zip_writer.reset(new ZipWriter(zip_file.get()));
1465 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001466 add_text_zip_entry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001467 }
1468
Felipe Lemee844a9d2016-09-21 15:01:39 -07001469 if (ds.updateProgress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001470 if (do_broadcast) {
1471 // clang-format off
1472 std::vector<std::string> am_args = {
1473 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001474 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001475 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001476 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1477 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1478 };
1479 // clang-format on
1480 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1481 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001482 if (use_control_socket) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001483 dprintf(ds.controlSocketFd_, "BEGIN:%s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001484 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001485 }
1486 }
1487
Nick Kralevichf3599b32016-01-25 15:05:16 -08001488 /* read /proc/cmdline before dropping root */
1489 FILE *cmdline = fopen("/proc/cmdline", "re");
1490 if (cmdline) {
1491 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1492 fclose(cmdline);
1493 }
1494
Jeff Brown1dc94e32014-09-11 14:15:27 -07001495 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001496 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001497 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001498 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001499 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001500 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001501 }
John Michelau1f794c42012-09-17 11:20:19 -05001502 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001503
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001504 if (do_fb && ds.doEarlyScreenshot_) {
1505 if (ds.screenshotPath_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001506 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001507 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001508 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001509 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001510 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001511 }
1512 }
1513
Felipe Leme1e9edc62015-12-21 16:02:13 -08001514 if (do_zip_file) {
1515 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001516 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001517 }
1518 }
1519
Felipe Leme71bbfc52015-11-23 14:14:51 -08001520 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001521 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001522 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1523 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1524 log_path.c_str(), strerror(errno));
1525 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001526 /* TODO: rather than generating a text file now and zipping it later,
1527 it would be more efficient to redirect stdout to the zip entry
1528 directly, but the libziparchive doesn't support that option yet. */
1529 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001530 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1531 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1532 tmp_path.c_str(), strerror(errno));
1533 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001534 }
Felipe Leme608385d2016-02-01 10:35:38 -08001535 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1536 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001537 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001538 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001539
Felipe Leme71a74ac2016-03-17 15:43:25 -07001540 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001541 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1542 // the raw trace.
1543 if (!dump_anrd_trace()) {
1544 dump_systrace();
1545 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001546
Felipe Leme9c74aad2016-02-29 18:15:42 -08001547 // Invoking the following dumpsys calls before dump_traces() to try and
1548 // keep the system stats as close to its initial state as possible.
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001549 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001550 CommandOptions::WithTimeout(90).DropRoot().Build());
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001551 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001552 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001553
Felipe Lemee844a9d2016-09-21 15:01:39 -07001554 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1555 dump_raft();
1556
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001557 /* collect stack traces from Dalvik and native processes (needs root) */
1558 dump_traces_path = dump_traces();
1559
Felipe Lemec0808152016-06-17 17:37:13 -07001560 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001561 get_tombstone_fds(tombstone_data);
1562 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001563 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001564 add_dir(LOGPERSIST_DATA_DIR, false);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001565 if (!IsUserBuild()) {
David Brazdild2991962016-06-03 14:40:44 +01001566 add_dir(PROFILE_DATA_DIR_CUR, true);
1567 add_dir(PROFILE_DATA_DIR_REF, true);
1568 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001569 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001570 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001571
Erik Kline32af8c22016-09-28 17:26:26 +09001572 // Capture any IPSec policies in play. No keys are exposed here.
1573 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1574 CommandOptions::WithTimeout(10).Build());
1575
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001576 // Run ss as root so we can see socket marks.
Felipe Lemec7fe8fe2016-09-21 18:13:20 -07001577 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001578
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001579 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001580 return -1;
1581 }
1582
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001583 dumpstate();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001584
Felipe Leme55b42a62015-11-10 17:39:08 -08001585 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001586 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001587 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001588 }
1589
Felipe Leme6e01fa62015-11-11 19:35:14 -08001590 /* rename or zip the (now complete) .tmp file to its final location */
1591 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001592
1593 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001594 std::string name = android::base::GetProperty(
1595 android::base::StringPrintf("dumpstate.%d.name", getpid()), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001596 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001597 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001598 /* must whitelist which characters are allowed, otherwise it could cross directories */
1599 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001600 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001601 change_suffix = true;
1602 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001603 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001604 }
1605 }
1606 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001607 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1608 ds.name_ = name;
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001609 if (!ds.screenshotPath_.empty()) {
1610 std::string newScreenshotPath = ds.GetPath(".png");
1611 if (rename(ds.screenshotPath_.c_str(), newScreenshotPath.c_str())) {
1612 MYLOGE("rename(%s, %s): %s\n", ds.screenshotPath_.c_str(),
1613 newScreenshotPath.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001614 } else {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001615 ds.screenshotPath_ = newScreenshotPath;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001616 }
1617 }
1618 }
1619
Felipe Leme6e01fa62015-11-11 19:35:14 -08001620 bool do_text_file = true;
1621 if (do_zip_file) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001622 std::string entry_name = ds.baseName_ + "-" + ds.name_ + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001623 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001624 if (!finish_zip_file(entry_name, tmp_path, log_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001625 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001626 do_text_file = true;
1627 } else {
1628 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001629 // Since zip file is already created, it needs to be renamed.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001630 std::string new_path = ds.GetPath(".zip");
Felipe Leme91274352016-02-26 15:03:52 -08001631 if (path != new_path) {
1632 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1633 if (rename(path.c_str(), new_path.c_str())) {
1634 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1635 new_path.c_str(), strerror(errno));
1636 } else {
1637 path = new_path;
1638 }
1639 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001640 }
1641 }
1642 if (do_text_file) {
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001643 path = ds.GetPath(".txt");
Felipe Leme88c79332016-02-22 11:06:49 -08001644 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001645 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001646 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001647 path.clear();
1648 }
1649 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001650 if (use_control_socket) {
1651 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001652 dprintf(ds.controlSocketFd_,
1653 "FAIL:could not create zip file, check %s "
1654 "for more details\n",
1655 log_path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001656 } else {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001657 dprintf(ds.controlSocketFd_, "OK:%s\n", path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001658 }
1659 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001660 }
1661
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001662 /* vibrate a few but shortly times to let user know it's finished */
1663 if (vibrator) {
1664 for (int i = 0; i < 3; i++) {
1665 vibrate(vibrator.get(), 75);
1666 usleep((75 + 50) * 1000);
1667 }
1668 }
1669
Jeff Brown1dc94e32014-09-11 14:15:27 -07001670 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001671 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001672 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001673 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001674 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001675 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001676 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001677 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001678 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemee844a9d2016-09-21 15:01:39 -07001679 "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001680 "--es", "android.intent.extra.BUGREPORT", path,
1681 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001682 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001683 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001684 if (do_fb) {
1685 am_args.push_back("--es");
1686 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001687 am_args.push_back(ds.screenshotPath_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001688 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001689 if (is_remote_mode) {
1690 am_args.push_back("--es");
1691 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1692 am_args.push_back(SHA256_file_hash(path));
1693 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1694 } else {
1695 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1696 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001697 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001698 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001699 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001700 }
1701
Felipe Lemee844a9d2016-09-21 15:01:39 -07001702 MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL);
1703 MYLOGI("done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001704
Felipe Leme107a05f2016-03-08 15:11:15 -08001705 if (is_redirecting) {
1706 fclose(stderr);
1707 }
1708
Felipe Lemee844a9d2016-09-21 15:01:39 -07001709 if (use_control_socket && ds.controlSocketFd_ != -1) {
1710 MYLOGD("Closing control socket\n");
1711 close(ds.controlSocketFd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001712 }
1713
Colin Crossf45fa6b2012-03-26 12:38:26 -07001714 return 0;
1715}