blob: 691863bbbb2271dc5176af01094f86b7b050be8f [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
Elliott Hughes9dc117c2015-12-07 14:21:50 -080038#include <android-base/stringprintf.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070039#include <android-base/unique_fd.h>
Zhengyin Qian068ecc72016-08-10 16:48:14 -070040#include <android-base/file.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070041#include <cutils/properties.h>
Wei Liuf87959e2016-08-26 14:51:42 -070042#include <hardware_legacy/power.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070043
44#include "private/android_filesystem_config.h"
45
46#define LOG_TAG "dumpstate"
Alex Ray656a6b92013-07-23 13:44:34 -070047#include <cutils/log.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070048
49#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080050#include "ziparchive/zip_writer.h"
51
Elliott Hughesc4dc1412016-04-12 16:28:31 -070052#include <openssl/sha.h>
Michal Karpinski4db754f2015-12-11 18:04:32 +000053
Felipe Leme6e01fa62015-11-11 19:35:14 -080054using android::base::StringPrintf;
Colin Crossf45fa6b2012-03-26 12:38:26 -070055
56/* read before root is shed */
57static char cmdline_buf[16384] = "(unknown)";
58static const char *dump_traces_path = NULL;
59
Felipe Lemeefd7e272016-05-18 09:27:16 -070060// TODO: variables below should be part of dumpstate object
Felipe Leme8fecfdd2016-02-09 10:40:07 -080061static unsigned long id;
Felipe Leme78f2c862015-12-21 09:55:22 -080062static char build_type[PROPERTY_VALUE_MAX];
Felipe Lemee82a27d2016-01-05 13:35:44 -080063static time_t now;
64static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080065static std::set<std::string> mount_points;
66void add_mountinfo();
Felipe Leme02b7e002016-07-22 12:03:20 -070067int control_socket_fd = -1;
Felipe Lemeefd7e272016-05-18 09:27:16 -070068/* suffix of the bugreport files - it's typically the date (when invoked with -d),
69 * although it could be changed by the user using a system property */
70static std::string suffix;
Felipe Leme8268ed22016-08-02 18:18:25 -070071static bool dry_run = false;
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"
Todd Poynor2a83daa2013-11-22 15:44:22 -080075
Wei Liu341938b2016-04-27 16:18:17 -070076#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080077#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070078#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070079#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010080#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
81#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070082#define TOMBSTONE_DIR "/data/tombstones"
83#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
84/* Can accomodate a tombstone number up to 9999. */
85#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
86#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090087#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070088#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070089
90typedef struct {
91 char name[TOMBSTONE_MAX_LEN];
92 int fd;
93} tombstone_data_t;
94
95static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
96
Felipe Leme71ca15e2016-05-19 16:18:17 -070097const std::string ZIP_ROOT_DIR = "FS";
98std::string bugreport_dir;
Felipe Lemee82a27d2016-01-05 13:35:44 -080099
Felipe Leme809d74e2016-02-02 12:57:00 -0800100/*
101 * List of supported zip format versions.
102 *
Felipe Leme8268ed22016-08-02 18:18:25 -0700103 * See bugreport-format.md for more info.
Felipe Leme809d74e2016-02-02 12:57:00 -0800104 */
Felipe Lemeca9c12e2016-05-19 16:30:15 -0700105static std::string VERSION_DEFAULT = "1.0";
Felipe Leme809d74e2016-02-02 12:57:00 -0800106
Calvin On249beee2016-06-03 15:17:07 -0700107bool is_user_build() {
Felipe Lemec4eee562016-04-21 15:42:55 -0700108 return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
109}
110
Felipe Leme8268ed22016-08-02 18:18:25 -0700111bool is_dry_run() {
112 return dry_run;
113}
114
Felipe Leme3d305a12016-05-20 11:24:37 -0700115/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
116 * otherwise, gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700117static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800118 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700119 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
120 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800121 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
122 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700123 struct stat st;
Felipe Leme3d305a12016-05-20 11:24:37 -0700124 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800125 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
Felipe Leme3d305a12016-05-20 11:24:37 -0700126 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700127 } else {
Felipe Leme3d305a12016-05-20 11:24:37 -0700128 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700129 data[i].fd = -1;
130 }
131 }
132}
133
Felipe Leme635ca312016-01-05 14:23:02 -0800134// for_each_pid() callback to get mount info about a process.
135void do_mountinfo(int pid, const char *name) {
136 char path[PATH_MAX];
137
138 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
139 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700140 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800141 char linkname[PATH_MAX];
142 ssize_t r = readlink(path, linkname, PATH_MAX);
143 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800144 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800145 return;
146 }
147 linkname[r] = '\0';
148
149 if (mount_points.find(linkname) == mount_points.end()) {
150 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700151 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800152 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
153 mount_points.insert(linkname);
154 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800155 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800156 }
157 }
158}
159
160void add_mountinfo() {
161 if (!zip_writer) return;
162 const char *title = "MOUNT INFO";
163 mount_points.clear();
Felipe Leme608385d2016-02-01 10:35:38 -0800164 DurationReporter duration_reporter(title, NULL);
Felipe Leme635ca312016-01-05 14:23:02 -0800165 for_each_pid(do_mountinfo, NULL);
Felipe Leme1b0225a2016-02-09 16:35:14 -0800166 MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800167}
168
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700169static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
170{
171 DIR *d;
172 struct dirent *de;
173 char path[PATH_MAX];
174
175 d = opendir(driverpath);
176 if (d == NULL) {
177 return;
178 }
179
180 while ((de = readdir(d))) {
181 if (de->d_type != DT_LNK) {
182 continue;
183 }
184 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700185 dumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700186 }
187
188 closedir(d);
189}
190
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700191// return pid of a userspace process. If not found or error, return 0.
192static unsigned int pid_of_process(const char* ps_name) {
193 DIR *proc_dir;
194 struct dirent *ps;
195 unsigned int pid;
196 std::string cmdline;
197
198 if (!(proc_dir = opendir("/proc"))) {
199 MYLOGE("Can't open /proc\n");
200 return 0;
201 }
202
203 while ((ps = readdir(proc_dir))) {
204 if (!(pid = atoi(ps->d_name))) {
205 continue;
206 }
207 android::base::ReadFileToString("/proc/"
208 + std::string(ps->d_name) + "/cmdline", &cmdline);
209 if (cmdline.find(ps_name) == std::string::npos) {
210 continue;
211 } else {
212 closedir(proc_dir);
213 return pid;
214 }
215 }
216 closedir(proc_dir);
217 return 0;
218}
219
220// dump anrd's trace and add to the zip file.
221// 1. check if anrd is running on this device.
222// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
223// 3. wait until the trace generation completes and add to the zip file.
224static bool dump_anrd_trace() {
225 unsigned int pid;
226 char buf[50], path[PATH_MAX];
227 struct dirent *trace;
228 struct stat st;
229 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700230 int retry = 5;
231 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700232 long long cur_size = 0;
233 const char *trace_path = "/data/misc/anrd/";
234
235 if (!zip_writer) {
236 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
237 return false;
238 }
239
240 // find anrd's pid if it is running.
241 pid = pid_of_process("/system/xbin/anrd");
242
243 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700244 if (stat(trace_path, &st) == 0) {
245 old_mtime = st.st_mtime;
246 } else {
247 MYLOGE("Failed to find: %s\n", trace_path);
248 return false;
249 }
250
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700251 // send SIGUSR1 to the anrd to generate a trace.
252 sprintf(buf, "%u", pid);
Felipe Leme30dbfa12016-09-02 12:43:26 -0700253 if (runCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
254 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700255 MYLOGE("anrd signal timed out. Please manually collect trace\n");
256 return false;
257 }
258
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700259 while (retry-- > 0 && old_mtime == st.st_mtime) {
260 sleep(1);
261 stat(trace_path, &st);
262 }
263
264 if (retry < 0 && old_mtime == st.st_mtime) {
265 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
266 return false;
267 }
268
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700269 // identify the trace file by its creation time.
270 if (!(trace_dir = opendir(trace_path))) {
271 MYLOGE("Can't open trace file under %s\n", trace_path);
272 }
273 while ((trace = readdir(trace_dir))) {
274 if (strcmp(trace->d_name, ".") == 0
275 || strcmp(trace->d_name, "..") == 0) {
276 continue;
277 }
278 sprintf(path, "%s%s", trace_path, trace->d_name);
279 if (stat(path, &st) == 0) {
280 if (st.st_ctime > max_ctime) {
281 max_ctime = st.st_ctime;
282 sprintf(buf, "%s", trace->d_name);
283 }
284 }
285 }
286 closedir(trace_dir);
287
288 // Wait until the dump completes by checking the size of the trace.
289 if (max_ctime > 0) {
290 sprintf(path, "%s%s", trace_path, buf);
291 while(true) {
292 sleep(1);
293 if (stat(path, &st) == 0) {
294 if (st.st_size == cur_size) {
295 break;
296 } else if (st.st_size > cur_size) {
297 cur_size = st.st_size;
298 } else {
299 return false;
300 }
301 } else {
302 MYLOGE("Cant stat() %s anymore\n", path);
303 return false;
304 }
305 }
306 // Add to the zip file.
307 if (!add_zip_entry("anrd_trace.txt", path)) {
308 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
309 } else {
310 if (remove(path)) {
311 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
312 }
313 return true;
314 }
315 } else {
316 MYLOGE("Can't stats any trace file under %s\n", trace_path);
317 }
318 }
319 return false;
320}
321
Felipe Lemeefd7e272016-05-18 09:27:16 -0700322static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700323 if (!zip_writer) {
324 MYLOGD("Not dumping systrace because zip_writer is not set\n");
325 return;
326 }
Felipe Lemeefd7e272016-05-18 09:27:16 -0700327 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700328 if (systrace_path.empty()) {
329 MYLOGE("Not dumping systrace because path is empty\n");
330 return;
331 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700332 const char* path = "/sys/kernel/debug/tracing/tracing_on";
333 long int is_tracing;
334 if (read_file_as_long(path, &is_tracing)) {
335 return; // error already logged
336 }
337 if (is_tracing <= 0) {
338 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
339 return;
340 }
341
Felipe Leme14e034a2016-03-30 18:51:03 -0700342 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
343 systrace_path.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -0700344 if (runCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
345 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700346 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Leme30dbfa12016-09-02 12:43:26 -0700347 // TODO: run_command tries to kill the process, but atrace doesn't die
348 // peacefully; ideally, we should call strace to stop itself, but there is no such option
349 // yet (just a --async_stop, which stops and dump
350 // if (runCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
351 // MYLOGE("could not stop systrace ");
352 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700353 }
354 if (!add_zip_entry("systrace.txt", systrace_path)) {
355 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700356 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700357 if (remove(systrace_path.c_str())) {
358 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
359 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700360 }
361}
362
Felipe Lemeefd7e272016-05-18 09:27:16 -0700363static void dump_raft() {
Wei Liu341938b2016-04-27 16:18:17 -0700364 if (is_user_build()) {
365 return;
366 }
367
Felipe Lemeefd7e272016-05-18 09:27:16 -0700368 std::string raft_log_path = bugreport_dir + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700369 if (raft_log_path.empty()) {
370 MYLOGD("raft_log_path is empty\n");
371 return;
372 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700373
374 struct stat s;
375 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
376 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
377 return;
378 }
379
Felipe Leme30dbfa12016-09-02 12:43:26 -0700380 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Wei Liu341938b2016-04-27 16:18:17 -0700381 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700382 // Write compressed and encoded raft logs to stdout if not zip_writer.
Felipe Leme30dbfa12016-09-02 12:43:26 -0700383 runCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700384 return;
385 }
386
Felipe Leme30dbfa12016-09-02 12:43:26 -0700387 runCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_log_path}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700388 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
389 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
390 } else {
391 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700392 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700393 }
394 }
395}
396
Mark Salyzyn326842f2015-04-30 09:49:41 -0700397static bool skip_not_stat(const char *path) {
398 static const char stat[] = "/stat";
399 size_t len = strlen(path);
400 if (path[len - 1] == '/') { /* Directory? */
401 return false;
402 }
403 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
404}
405
Felipe Lemee82a27d2016-01-05 13:35:44 -0800406static bool skip_none(const char *path) {
407 return false;
408}
409
Mark Salyzyn326842f2015-04-30 09:49:41 -0700410static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700411unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700412
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800413//
414// stat offsets
415// Name units description
416// ---- ----- -----------
417// read I/Os requests number of read I/Os processed
418#define __STAT_READ_IOS 0
419// read merges requests number of read I/Os merged with in-queue I/O
420#define __STAT_READ_MERGES 1
421// read sectors sectors number of sectors read
422#define __STAT_READ_SECTORS 2
423// read ticks milliseconds total wait time for read requests
424#define __STAT_READ_TICKS 3
425// write I/Os requests number of write I/Os processed
426#define __STAT_WRITE_IOS 4
427// write merges requests number of write I/Os merged with in-queue I/O
428#define __STAT_WRITE_MERGES 5
429// write sectors sectors number of sectors written
430#define __STAT_WRITE_SECTORS 6
431// write ticks milliseconds total wait time for write requests
432#define __STAT_WRITE_TICKS 7
433// in_flight requests number of I/Os currently in flight
434#define __STAT_IN_FLIGHT 8
435// io_ticks milliseconds total time this block device has been active
436#define __STAT_IO_TICKS 9
437// time_in_queue milliseconds total wait time for all requests
438#define __STAT_IN_QUEUE 10
439#define __STAT_NUMBER_FIELD 11
440//
441// read I/Os, write I/Os
442// =====================
443//
444// These values increment when an I/O request completes.
445//
446// read merges, write merges
447// =========================
448//
449// These values increment when an I/O request is merged with an
450// already-queued I/O request.
451//
452// read sectors, write sectors
453// ===========================
454//
455// These values count the number of sectors read from or written to this
456// block device. The "sectors" in question are the standard UNIX 512-byte
457// sectors, not any device- or filesystem-specific block size. The
458// counters are incremented when the I/O completes.
459#define SECTOR_SIZE 512
460//
461// read ticks, write ticks
462// =======================
463//
464// These values count the number of milliseconds that I/O requests have
465// waited on this block device. If there are multiple I/O requests waiting,
466// these values will increase at a rate greater than 1000/second; for
467// example, if 60 read requests wait for an average of 30 ms, the read_ticks
468// field will increase by 60*30 = 1800.
469//
470// in_flight
471// =========
472//
473// This value counts the number of I/O requests that have been issued to
474// the device driver but have not yet completed. It does not include I/O
475// requests that are in the queue but not yet issued to the device driver.
476//
477// io_ticks
478// ========
479//
480// This value counts the number of milliseconds during which the device has
481// had I/O requests queued.
482//
483// time_in_queue
484// =============
485//
486// This value counts the number of milliseconds that I/O requests have waited
487// on this block device. If there are multiple I/O requests waiting, this
488// value will increase as the product of the number of milliseconds times the
489// number of requests waiting (see "read ticks" above for an example).
490#define S_TO_MS 1000
491//
492
Mark Salyzyn326842f2015-04-30 09:49:41 -0700493static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800494 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700495 bool z;
496 char *cp, *buffer = NULL;
497 size_t i = 0;
498 FILE *fp = fdopen(fd, "rb");
499 getline(&buffer, &i, fp);
500 fclose(fp);
501 if (!buffer) {
502 return -errno;
503 }
504 i = strlen(buffer);
505 while ((i > 0) && (buffer[i - 1] == '\n')) {
506 buffer[--i] = '\0';
507 }
508 if (!*buffer) {
509 free(buffer);
510 return 0;
511 }
512 z = true;
513 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800514 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700515 if (fields[i] != 0) {
516 z = false;
517 }
518 }
519 if (z) { /* never accessed */
520 free(buffer);
521 return 0;
522 }
523
524 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
525 path += sizeof(mmcblk0) - 1;
526 }
527
528 printf("%s: %s\n", path, buffer);
529 free(buffer);
530
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800531 if (fields[__STAT_IO_TICKS]) {
532 unsigned long read_perf = 0;
533 unsigned long read_ios = 0;
534 if (fields[__STAT_READ_TICKS]) {
535 unsigned long long divisor = fields[__STAT_READ_TICKS]
536 * fields[__STAT_IO_TICKS];
537 read_perf = ((unsigned long long)SECTOR_SIZE
538 * fields[__STAT_READ_SECTORS]
539 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
540 / divisor;
541 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
542 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
543 / divisor;
544 }
545
546 unsigned long write_perf = 0;
547 unsigned long write_ios = 0;
548 if (fields[__STAT_WRITE_TICKS]) {
549 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
550 * fields[__STAT_IO_TICKS];
551 write_perf = ((unsigned long long)SECTOR_SIZE
552 * fields[__STAT_WRITE_SECTORS]
553 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
554 / divisor;
555 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
556 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
557 / divisor;
558 }
559
560 unsigned queue = (fields[__STAT_IN_QUEUE]
561 + (fields[__STAT_IO_TICKS] >> 1))
562 / fields[__STAT_IO_TICKS];
563
564 if (!write_perf && !write_ios) {
565 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
566 path, read_perf, read_ios, queue);
567 } else {
568 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
569 path, read_perf, read_ios, write_perf, write_ios, queue);
570 }
571
572 /* bugreport timeout factor adjustment */
573 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
574 worst_write_perf = write_perf;
575 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700576 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700577 return 0;
578}
579
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700580/* Copied policy from system/core/logd/LogBuffer.cpp */
581
582#define LOG_BUFFER_SIZE (256 * 1024)
583#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
584#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
585
586static bool valid_size(unsigned long value) {
587 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
588 return false;
589 }
590
591 long pages = sysconf(_SC_PHYS_PAGES);
592 if (pages < 1) {
593 return true;
594 }
595
596 long pagesize = sysconf(_SC_PAGESIZE);
597 if (pagesize <= 1) {
598 pagesize = PAGE_SIZE;
599 }
600
601 // maximum memory impact a somewhat arbitrary ~3%
602 pages = (pages + 31) / 32;
603 unsigned long maximum = pages * pagesize;
604
605 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
606 return true;
607 }
608
609 return value <= maximum;
610}
611
612static unsigned long property_get_size(const char *key) {
613 unsigned long value;
614 char *cp, property[PROPERTY_VALUE_MAX];
615
616 property_get(key, property, "");
617 value = strtoul(property, &cp, 10);
618
619 switch(*cp) {
620 case 'm':
621 case 'M':
622 value *= 1024;
623 /* FALLTHRU */
624 case 'k':
625 case 'K':
626 value *= 1024;
627 /* FALLTHRU */
628 case '\0':
629 break;
630
631 default:
632 value = 0;
633 }
634
635 if (!valid_size(value)) {
636 value = 0;
637 }
638
639 return value;
640}
641
642/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800643static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700644 static const char global_tuneable[] = "persist.logd.size"; // Settings App
645 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
646 char key[PROP_NAME_MAX];
647 unsigned long property_size, default_size;
648
649 default_size = property_get_size(global_tuneable);
650 if (!default_size) {
651 default_size = property_get_size(global_default);
652 }
653
654 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
655 property_size = property_get_size(key);
656
657 if (!property_size) {
658 snprintf(key, sizeof(key), "%s.%s", global_default, name);
659 property_size = property_get_size(key);
660 }
661
662 if (!property_size) {
663 property_size = default_size;
664 }
665
666 if (!property_size) {
667 property_size = LOG_BUFFER_SIZE;
668 }
669
670 /* Engineering margin is ten-fold our guess */
671 return 10 * (property_size + worst_write_perf) / worst_write_perf;
672}
673
674/* End copy from system/core/logd/LogBuffer.cpp */
675
Colin Crossf45fa6b2012-03-26 12:38:26 -0700676/* dumps the current system state to stdout */
Felipe Leme809d74e2016-02-02 12:57:00 -0800677static void print_header(std::string version) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700678 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
679 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
680 char network[PROPERTY_VALUE_MAX], date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700681
682 property_get("ro.build.display.id", build, "(unknown)");
683 property_get("ro.build.fingerprint", fingerprint, "(unknown)");
684 property_get("ro.build.type", build_type, "(unknown)");
Junda Liu58ad9292016-06-12 11:51:54 -0700685 property_get("gsm.version.baseband", radio, "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700686 property_get("ro.bootloader", bootloader, "(unknown)");
687 property_get("gsm.operator.alpha", network, "(unknown)");
688 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
689
690 printf("========================================================\n");
691 printf("== dumpstate: %s\n", date);
692 printf("========================================================\n");
693
694 printf("\n");
695 printf("Build: %s\n", build);
696 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
697 printf("Bootloader: %s\n", bootloader);
698 printf("Radio: %s\n", radio);
699 printf("Network: %s\n", network);
700
701 printf("Kernel: ");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700702 dumpFile(nullptr, "/proc/version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700703 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800704 printf("Bugreport format version: %s\n", version.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -0700705 printf("Dumpstate info: id=%lu pid=%d dry_run=%d\n", id, getpid(), dry_run);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700706 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800707}
708
Felipe Leme24b66ee2016-06-16 10:55:26 -0700709// List of file extensions that can cause a zip file attachment to be rejected by some email
710// service providers.
711static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
712 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
713 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
714 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
715};
716
Felipe Leme71ca15e2016-05-19 16:18:17 -0700717bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800718 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800719 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
720 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800721 return false;
722 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700723 std::string valid_name = entry_name;
724
725 // Rename extension if necessary.
726 size_t idx = entry_name.rfind(".");
727 if (idx != std::string::npos) {
728 std::string extension = entry_name.substr(idx);
729 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
730 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
731 valid_name = entry_name + ".renamed";
732 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
733 }
734 }
735
Felipe Leme6fe9db62016-02-12 09:04:16 -0800736 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
737 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700738 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800739 ZipWriter::kCompress, get_mtime(fd, now));
740 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700741 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800742 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800743 return false;
744 }
745
Felipe Leme770410d2016-01-26 17:07:14 -0800746 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800747 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400748 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800749 if (bytes_read == 0) {
750 break;
751 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800752 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800753 return false;
754 }
755 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
756 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800757 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800758 return false;
759 }
760 }
761
762 err = zip_writer->FinishEntry();
763 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800764 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800765 return false;
766 }
767
768 return true;
769}
770
Felipe Leme71ca15e2016-05-19 16:18:17 -0700771bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700772 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
773 | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700774 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800775 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800776 return false;
777 }
778
779 return add_zip_entry_from_fd(entry_name, fd.get());
780}
781
782/* adds a file to the existing zipped bugreport */
783static int _add_file_from_fd(const char *title, const char *path, int fd) {
784 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
785}
786
Felipe Leme24b66ee2016-06-16 10:55:26 -0700787// TODO: move to util.cpp
Felipe Lemee82a27d2016-01-05 13:35:44 -0800788void add_dir(const char *dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800789 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800790 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
Felipe Leme111b9d02016-02-03 09:28:24 -0800791 return;
792 }
Felipe Leme88c79332016-02-22 11:06:49 -0800793 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
Felipe Leme608385d2016-02-01 10:35:38 -0800794 DurationReporter duration_reporter(dir, NULL);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800795 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
796}
797
Felipe Leme809d74e2016-02-02 12:57:00 -0800798/* adds a text entry entry to the existing zip file. */
799static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800800 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800801 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 -0800802 return false;
803 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800804 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800805 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
806 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800807 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800808 ZipWriter::ErrorCodeString(err));
809 return false;
810 }
811
812 err = zip_writer->WriteBytes(content.c_str(), content.length());
813 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800814 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800815 ZipWriter::ErrorCodeString(err));
816 return false;
817 }
818
819 err = zip_writer->FinishEntry();
820 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800821 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800822 return false;
823 }
824
825 return true;
826}
827
Felipe Lemec0808152016-06-17 17:37:13 -0700828static void dump_iptables() {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700829 runCommand("IPTABLES", {"iptables", "-L", "-nvx"});
830 runCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
831 runCommand("IPTABLE NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700832 /* no ip6 nat */
Felipe Leme30dbfa12016-09-02 12:43:26 -0700833 runCommand("IPTABLE MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
834 runCommand("IP6TABLE MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
835 runCommand("IPTABLE RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
836 runCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700837}
838
Srinath Sridharanfdf52d32016-02-01 15:50:22 -0800839static void dumpstate(const std::string& screenshot_path, const std::string& version) {
Felipe Leme770410d2016-01-26 17:07:14 -0800840 DurationReporter duration_reporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800841 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700842
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700843 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Leme30dbfa12016-09-02 12:43:26 -0700844 runCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -0700845 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800846 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700847 dumpFile("MEMORY INFO", "/proc/meminfo");
Felipe Leme30dbfa12016-09-02 12:43:26 -0700848 runCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
849 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
850 runCommand("PROCRANK", {"procrank"}, CommandOptions::AS_ROOT_20);
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700851 dumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
852 dumpFile("VMALLOC INFO", "/proc/vmallocinfo");
853 dumpFile("SLAB INFO", "/proc/slabinfo");
854 dumpFile("ZONEINFO", "/proc/zoneinfo");
855 dumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
856 dumpFile("BUDDYINFO", "/proc/buddyinfo");
857 dumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700858
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700859 dumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
860 dumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
861 dumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700862
Felipe Leme30dbfa12016-09-02 12:43:26 -0700863 runCommand("PROCESSES AND THREADS",
864 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
865 runCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT_10);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700866
Felipe Leme30dbfa12016-09-02 12:43:26 -0700867 runCommand("PRINTENV", {"printenv"});
868 runCommand("NETSTAT", {"netstat", "-n"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700869 struct stat s;
870 if (stat("/proc/modules", &s) != 0) {
871 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
872 } else {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700873 runCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700874 }
Michal Karpinski4db754f2015-12-11 18:04:32 +0000875
Colin Crossf45fa6b2012-03-26 12:38:26 -0700876 do_dmesg();
877
Felipe Leme30dbfa12016-09-02 12:43:26 -0700878 runCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT_10);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700879 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
880 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800881 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700882
Felipe Leme6e01fa62015-11-11 19:35:14 -0800883 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800884 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800885 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800886 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700887 }
888
Felipe Leme0bcc7ca2016-09-13 16:45:56 -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 Leme30dbfa12016-09-02 12:43:26 -0700895 runCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
896 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 Leme30dbfa12016-09-02 12:43:26 -0700901 runCommand("EVENT LOG",
902 {"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 Leme30dbfa12016-09-02 12:43:26 -0700908 runCommand("RADIO LOG",
909 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
910 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700911
Felipe Leme30dbfa12016-09-02 12:43:26 -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 Leme0bcc7ca2016-09-13 16:45:56 -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;
921 char anr_traces_path[PATH_MAX];
922 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
923 if (!anr_traces_path[0]) {
924 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700925 } else {
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800926 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
927 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700928 if (fd < 0) {
929 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
930 } else {
931 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
932 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700933 }
934
935 /* slow traces for slow operations */
936 if (anr_traces_path[0] != 0) {
937 int tail = strlen(anr_traces_path)-1;
938 while (tail > 0 && anr_traces_path[tail] != '/') {
939 tail--;
940 }
941 int i = 0;
942 while (1) {
943 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
944 if (stat(anr_traces_path, &st)) {
945 // No traces file at this index, done with the files.
946 break;
947 }
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700948 dumpFile("VM TRACES WHEN SLOW", anr_traces_path);
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 Leme0bcc7ca2016-09-13 16:45:56 -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 Leme0bcc7ca2016-09-13 16:45:56 -0700982 dumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700983 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Leme0bcc7ca2016-09-13 16:45:56 -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 Leme0bcc7ca2016-09-13 16:45:56 -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 Leme30dbfa12016-09-02 12:43:26 -0700991 runCommand("LAST LOGCAT",
992 {"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 Leme30dbfa12016-09-02 12:43:26 -0700996 runCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +0900997
Felipe Leme30dbfa12016-09-02 12:43:26 -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 Leme30dbfa12016-09-02 12:43:26 -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 Leme30dbfa12016-09-02 12:43:26 -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"},
1010 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001011
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001012#ifdef FWDUMP_bcmdhd
Felipe Leme30dbfa12016-09-02 12:43:26 -07001013 runCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001014
Felipe Leme30dbfa12016-09-02 12:43:26 -07001015 runCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001016
Felipe Leme30dbfa12016-09-02 12:43:26 -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 Leme0bcc7ca2016-09-13 16:45:56 -07001020 dumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001021
Felipe Leme30dbfa12016-09-02 12:43:26 -07001022 runDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1023 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001024
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001025#ifdef FWDUMP_bcmdhd
Felipe Leme30dbfa12016-09-02 12:43:26 -07001026 runCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001027
Felipe Leme30dbfa12016-09-02 12:43:26 -07001028 runCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001029
Felipe Leme30dbfa12016-09-02 12:43:26 -07001030 runCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001031#endif
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001032 dumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001033
1034 print_properties();
1035
Felipe Leme30dbfa12016-09-02 12:43:26 -07001036 runCommand("VOLD DUMP", {"vdc", "dump"});
1037 runCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001038
Felipe Leme30dbfa12016-09-02 12:43:26 -07001039 runCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001040
Felipe Leme30dbfa12016-09-02 12:43:26 -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 Leme0bcc7ca2016-09-13 16:45:56 -07001045 dumpFile(nullptr, "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001046 printf("Button brightness=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001047 dumpFile(nullptr, "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001048 printf("Keyboard brightness=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001049 dumpFile(nullptr, "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001050 printf("ALS mode=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001051 dumpFile(nullptr, "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001052 printf("LCD driver registers:\n");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001053 dumpFile(nullptr, "/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 Leme0bcc7ca2016-09-13 16:45:56 -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()? */
1074 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1075 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1076 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001077 // su does not exist on user builds, so try running without it.
1078 // This way any implementations of vril-dump that do not require
1079 // root can run on user builds.
1080 CommandOptions::CommandOptionsBuilder options =
1081 CommandOptions::WithTimeout(atoi(ril_dumpstate_timeout));
1082 if (!is_user_build()) {
1083 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001084 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001085 runCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001086 }
1087
1088 printf("========================================================\n");
1089 printf("== Android Framework Services\n");
1090 printf("========================================================\n");
1091
Felipe Leme30dbfa12016-09-02 12:43:26 -07001092 runDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(60).Build());
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 Leme30dbfa12016-09-02 12:43:26 -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 Leme30dbfa12016-09-02 12:43:26 -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 Leme30dbfa12016-09-02 12:43:26 -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 Leme30dbfa12016-09-02 12:43:26 -07001121 runDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001122
1123 printf("========================================================\n");
Felipe Leme608385d2016-02-01 10:35:38 -08001124 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1125 getpid(), progress, weight_total, WEIGHT_TOTAL);
1126 printf("========================================================\n");
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001127 printf("== dumpstate: done (id %lu)\n", id);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001128 printf("========================================================\n");
1129}
1130
1131static void usage() {
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001132 fprintf(stderr,
Felipe Leme2628e9e2016-04-12 16:36:51 -07001133 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1134 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1135 " -h: display this help message\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001136 " -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"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001141 " -z: generate zipped file (requires -o)\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001142 " -s: write output to control socket (for init)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001143 " -S: write file location to control socket (for init; requires -o and -z)"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001144 " -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());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001152}
1153
Wei Liuf87959e2016-08-26 14:51:42 -07001154static void wake_lock_releaser() {
1155 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1156 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1157 } else {
1158 MYLOGD("Wake lock released.\n");
1159 }
1160}
1161
1162static void sig_handler(int signo) {
1163 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001164 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001165}
1166
Wei Liuf87959e2016-08-26 14:51:42 -07001167static void register_sig_handler() {
1168 struct sigaction sa;
1169 sigemptyset(&sa.sa_mask);
1170 sa.sa_flags = 0;
1171 sa.sa_handler = sig_handler;
1172 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1173 sigaction(SIGSEGV, &sa, NULL); // segment fault
1174 sigaction(SIGINT, &sa, NULL); // ctrl-c
1175 sigaction(SIGTERM, &sa, NULL); // killed
1176 sigaction(SIGQUIT, &sa, NULL); // quit
1177}
1178
Felipe Leme1e9edc62015-12-21 16:02:13 -08001179/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1180 temporary file.
1181 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001182static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Leme0f3fb202016-06-10 17:10:53 -07001183 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001184 // Final timestamp
1185 char date[80];
1186 time_t the_real_now_please_stand_up = time(nullptr);
1187 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
1188 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", id, date,
1189 the_real_now_please_stand_up - now);
1190
Felipe Lemee82a27d2016-01-05 13:35:44 -08001191 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001192 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001193 return false;
1194 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001195 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001196 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001197 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001198 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001199
Felipe Leme0f3fb202016-06-10 17:10:53 -07001200 // Add log file (which contains stderr output) to zip...
1201 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1202 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1203 MYLOGE("Failed to add dumpstate log to .zip file\n");
1204 return false;
1205 }
1206 // ... and re-opens it for further logging.
1207 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1208 fprintf(stderr, "\n");
1209
Felipe Lemee82a27d2016-01-05 13:35:44 -08001210 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001211 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001212 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001213 return false;
1214 }
1215
Felipe Lemec4eee562016-04-21 15:42:55 -07001216 if (is_user_build()) {
1217 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1218 if (remove(bugreport_path.c_str())) {
1219 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1220 }
1221 } else {
1222 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1223 }
1224
Felipe Leme1e9edc62015-12-21 16:02:13 -08001225 return true;
1226}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001227
Michal Karpinski4db754f2015-12-11 18:04:32 +00001228static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001229 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1230 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001231 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001232 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001233 return NULL;
1234 }
1235
1236 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001237 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001238
1239 std::vector<uint8_t> buffer(65536);
1240 while (1) {
1241 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1242 if (bytes_read == 0) {
1243 break;
1244 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001245 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001246 return NULL;
1247 }
1248
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001249 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001250 }
1251
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001252 uint8_t hash[SHA256_DIGEST_LENGTH];
1253 SHA256_Final(hash, &ctx);
1254
1255 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1256 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001257 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001258 }
1259 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1260 return std::string(hash_buffer);
1261}
1262
Colin Crossf45fa6b2012-03-26 12:38:26 -07001263int main(int argc, char *argv[]) {
1264 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001265 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001266 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001267 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001268 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001269 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001270 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001271 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001272 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001273 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001274 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001275
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001276 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001277
Felipe Lemecbce55d2016-02-08 09:53:18 -08001278 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001279
Wei Liuf87959e2016-08-26 14:51:42 -07001280 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1281 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1282 } else {
1283 MYLOGD("Wake lock acquired.\n");
1284 atexit(wake_lock_releaser);
1285 register_sig_handler();
1286 }
1287
Felipe Leme8268ed22016-08-02 18:18:25 -07001288 dry_run = property_get_bool("dumpstate.dry_run", 0) != 0;
1289 if (is_dry_run()) {
1290 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1291 }
1292
Felipe Leme30dbfa12016-09-02 12:43:26 -07001293 std::string args;
1294 for (int i = 0; i < argc; i++) {
1295 args += argv[i];
1296 args += " ";
1297 }
1298 MYLOGD("Dumpstate command line: %s\n", args.c_str());
1299
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001300 /* gets the sequential id */
1301 char last_id[PROPERTY_VALUE_MAX];
1302 property_get("dumpstate.last_id", last_id, "0");
1303 id = strtoul(last_id, NULL, 10) + 1;
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001304 snprintf(last_id, sizeof(last_id), "%lu", id);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001305 property_set("dumpstate.last_id", last_id);
1306 MYLOGI("dumpstate id: %lu\n", id);
1307
Colin Crossf45fa6b2012-03-26 12:38:26 -07001308 /* set as high priority, and protect from OOM killer */
1309 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001310
1311 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001312 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001313 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001314 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001315 } else {
1316 /* fallback to kernels <= 2.6.35 */
1317 oom_adj = fopen("/proc/self/oom_adj", "we");
1318 if (oom_adj) {
1319 fputs("-17", oom_adj);
1320 fclose(oom_adj);
1321 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001322 }
1323
Jeff Brown1dc94e32014-09-11 14:15:27 -07001324 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001325 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001326 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001327 switch (c) {
Felipe Leme71bbfc52015-11-23 14:14:51 -08001328 case 'd': do_add_date = 1; break;
1329 case 'z': do_zip_file = 1; break;
1330 case 'o': use_outfile = optarg; break;
1331 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001332 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001333 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001334 case 'q': do_vibrate = 0; break;
1335 case 'p': do_fb = 1; break;
1336 case 'P': do_update_progress = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001337 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001338 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001339 case 'V': version = optarg; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001340 case '?': printf("\n");
1341 case 'h':
1342 usage();
1343 exit(1);
1344 }
1345 }
1346
Felipe Leme71bbfc52015-11-23 14:14:51 -08001347 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001348 usage();
1349 exit(1);
1350 }
1351
Felipe Leme2628e9e2016-04-12 16:36:51 -07001352 if (use_control_socket && !do_zip_file) {
1353 usage();
1354 exit(1);
1355 }
1356
Felipe Leme71bbfc52015-11-23 14:14:51 -08001357 if (do_update_progress && !do_broadcast) {
1358 usage();
1359 exit(1);
1360 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001361
Michal Karpinski4db754f2015-12-11 18:04:32 +00001362 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1363 usage();
1364 exit(1);
1365 }
1366
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001367 if (version != VERSION_DEFAULT) {
1368 usage();
1369 exit(1);
Felipe Leme809d74e2016-02-02 12:57:00 -08001370 }
1371
Felipe Lemecbce55d2016-02-08 09:53:18 -08001372 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001373
Felipe Lemee338bf62015-12-07 14:03:50 -08001374 do_early_screenshot = do_update_progress;
1375
Christopher Ferrised9354f2014-10-01 17:35:01 -07001376 // If we are going to use a socket, do it as early as possible
1377 // to avoid timeouts from bugreport.
1378 if (use_socket) {
1379 redirect_to_socket(stdout, "dumpstate");
1380 }
1381
Felipe Leme2628e9e2016-04-12 16:36:51 -07001382 if (use_control_socket) {
1383 MYLOGD("Opening control socket\n");
1384 control_socket_fd = open_socket("dumpstate");
Felipe Leme02b7e002016-07-22 12:03:20 -07001385 do_update_progress = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001386 }
1387
Felipe Lemecbce55d2016-02-08 09:53:18 -08001388 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001389 std::string tmp_path;
1390
Felipe Leme0f3fb202016-06-10 17:10:53 -07001391 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001392 std::string log_path;
1393
Felipe Leme14e034a2016-03-30 18:51:03 -07001394 /* full path of the systrace file, when enabled */
1395 std::string systrace_path;
1396
Felipe Lemee338bf62015-12-07 14:03:50 -08001397 /* full path of the temporary file containing the screenshot (when requested) */
1398 std::string screenshot_path;
1399
Felipe Lemecbce55d2016-02-08 09:53:18 -08001400 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001401 std::string base_name;
1402
Felipe Leme71bbfc52015-11-23 14:14:51 -08001403 /* pointer to the actual path, be it zip or text */
1404 std::string path;
1405
Felipe Leme635ca312016-01-05 14:23:02 -08001406 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001407 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001408
Felipe Lemead5f6c42015-11-30 14:26:46 -08001409 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001410 bool is_redirecting = !use_socket && use_outfile;
1411
1412 if (is_redirecting) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001413 bugreport_dir = dirname(use_outfile);
1414 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001415 if (do_add_date) {
1416 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001417 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1418 suffix = date;
1419 } else {
1420 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001421 }
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001422 char build_id[PROPERTY_VALUE_MAX];
1423 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1424 base_name = base_name + "-" + build_id;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001425 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001426 // TODO: if dumpstate was an object, the paths could be internal variables and then
1427 // we could have a function to calculate the derived values, such as:
1428 // screenshot_path = GetPath(".png");
1429 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001430 }
Felipe Lemead5f6c42015-11-30 14:26:46 -08001431 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
Felipe Lemecbce55d2016-02-08 09:53:18 -08001432 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1433 + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001434
Felipe Lemecbce55d2016-02-08 09:53:18 -08001435 MYLOGD("Bugreport dir: %s\n"
1436 "Base name: %s\n"
1437 "Suffix: %s\n"
1438 "Log path: %s\n"
1439 "Temporary path: %s\n"
1440 "Screenshot path: %s\n",
1441 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1442 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001443
Felipe Leme1e9edc62015-12-21 16:02:13 -08001444 if (do_zip_file) {
Felipe Leme1e9edc62015-12-21 16:02:13 -08001445 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001446 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001447 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001448 zip_file.reset(fopen(path.c_str(), "wb"));
1449 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001450 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001451 do_zip_file = 0;
1452 } else {
1453 zip_writer.reset(new ZipWriter(zip_file.get()));
1454 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001455 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001456 }
1457
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001458 if (do_update_progress) {
1459 if (do_broadcast) {
1460 // clang-format off
1461 std::vector<std::string> am_args = {
1462 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1463 "--es", "android.intent.extra.NAME", suffix,
1464 "--ei", "android.intent.extra.ID", std::to_string(id),
1465 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1466 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1467 };
1468 // clang-format on
1469 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1470 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001471 if (use_control_socket) {
1472 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1473 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001474 }
1475 }
1476
Nick Kralevichf3599b32016-01-25 15:05:16 -08001477 /* read /proc/cmdline before dropping root */
1478 FILE *cmdline = fopen("/proc/cmdline", "re");
1479 if (cmdline) {
1480 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1481 fclose(cmdline);
1482 }
1483
Jeff Brown1dc94e32014-09-11 14:15:27 -07001484 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001485 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001486 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001487 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001488 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001489 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001490 }
John Michelau1f794c42012-09-17 11:20:19 -05001491 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001492
Felipe Leme3634a1e2015-12-09 10:11:47 -08001493 if (do_fb && do_early_screenshot) {
1494 if (screenshot_path.empty()) {
1495 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001496 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001497 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001498 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001499 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001500 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001501 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001502 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001503 screenshot_path.c_str(), strerror(errno));
1504 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001505 }
1506 }
1507
Felipe Leme1e9edc62015-12-21 16:02:13 -08001508 if (do_zip_file) {
1509 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001510 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001511 }
1512 }
1513
Felipe Leme71bbfc52015-11-23 14:14:51 -08001514 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001515 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001516 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1517 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1518 log_path.c_str(), strerror(errno));
1519 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001520 /* TODO: rather than generating a text file now and zipping it later,
1521 it would be more efficient to redirect stdout to the zip entry
1522 directly, but the libziparchive doesn't support that option yet. */
1523 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001524 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1525 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1526 tmp_path.c_str(), strerror(errno));
1527 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001528 }
Felipe Leme608385d2016-02-01 10:35:38 -08001529 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1530 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001531 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001532 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001533
Felipe Leme71a74ac2016-03-17 15:43:25 -07001534 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001535 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1536 // the raw trace.
1537 if (!dump_anrd_trace()) {
1538 dump_systrace();
1539 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001540
Wei Liu341938b2016-04-27 16:18:17 -07001541 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
Felipe Lemeefd7e272016-05-18 09:27:16 -07001542 dump_raft();
Wei Liu341938b2016-04-27 16:18:17 -07001543
Felipe Leme9c74aad2016-02-29 18:15:42 -08001544 // Invoking the following dumpsys calls before dump_traces() to try and
1545 // keep the system stats as close to its initial state as possible.
Felipe Leme30dbfa12016-09-02 12:43:26 -07001546 runDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1547 CommandOptions::WithTimeout(90).DropRoot().Build());
1548 runDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1549 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001550
1551 /* collect stack traces from Dalvik and native processes (needs root) */
1552 dump_traces_path = dump_traces();
1553
Felipe Lemec0808152016-06-17 17:37:13 -07001554 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001555 get_tombstone_fds(tombstone_data);
1556 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001557 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001558 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001559 if (!is_user_build()) {
1560 add_dir(PROFILE_DATA_DIR_CUR, true);
1561 add_dir(PROFILE_DATA_DIR_REF, true);
1562 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001563 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001564 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001565
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001566 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001567 return -1;
1568 }
1569
1570 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001571
Felipe Leme55b42a62015-11-10 17:39:08 -08001572 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001573 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001574 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001575 }
1576
Felipe Leme6e01fa62015-11-11 19:35:14 -08001577 /* rename or zip the (now complete) .tmp file to its final location */
1578 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001579
1580 /* check if user changed the suffix using system properties */
1581 char key[PROPERTY_KEY_MAX];
1582 char value[PROPERTY_VALUE_MAX];
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001583 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001584 property_get(key, value, "");
1585 bool change_suffix= false;
1586 if (value[0]) {
1587 /* must whitelist which characters are allowed, otherwise it could cross directories */
1588 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1589 if (std::regex_match(value, valid_regex)) {
1590 change_suffix = true;
1591 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001592 MYLOGE("invalid suffix provided by user: %s\n", value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001593 }
1594 }
1595 if (change_suffix) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001596 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001597 suffix = value;
1598 if (!screenshot_path.empty()) {
1599 std::string new_screenshot_path =
1600 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1601 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001602 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001603 new_screenshot_path.c_str(), strerror(errno));
1604 } else {
1605 screenshot_path = new_screenshot_path;
1606 }
1607 }
1608 }
1609
Felipe Leme6e01fa62015-11-11 19:35:14 -08001610 bool do_text_file = true;
1611 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001612 std::string entry_name = base_name + "-" + suffix + ".txt";
1613 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Leme0f3fb202016-06-10 17:10:53 -07001614 if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001615 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001616 do_text_file = true;
1617 } else {
1618 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001619 // Since zip file is already created, it needs to be renamed.
1620 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1621 if (path != new_path) {
1622 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1623 if (rename(path.c_str(), new_path.c_str())) {
1624 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1625 new_path.c_str(), strerror(errno));
1626 } else {
1627 path = new_path;
1628 }
1629 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001630 }
1631 }
1632 if (do_text_file) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001633 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001634 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001635 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001636 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001637 path.clear();
1638 }
1639 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001640 if (use_control_socket) {
1641 if (do_text_file) {
1642 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1643 "for more details\n", log_path.c_str());
1644 } else {
1645 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1646 }
1647 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001648 }
1649
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001650 /* vibrate a few but shortly times to let user know it's finished */
1651 if (vibrator) {
1652 for (int i = 0; i < 3; i++) {
1653 vibrate(vibrator.get(), 75);
1654 usleep((75 + 50) * 1000);
1655 }
1656 }
1657
Jeff Brown1dc94e32014-09-11 14:15:27 -07001658 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001659 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001660 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001661 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001662 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001663 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001664 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001665 "--ei", "android.intent.extra.ID", std::to_string(id),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001666 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemeee2e4a02016-02-22 18:12:11 -08001667 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001668 "--es", "android.intent.extra.BUGREPORT", path,
1669 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001670 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001671 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001672 if (do_fb) {
1673 am_args.push_back("--es");
1674 am_args.push_back("android.intent.extra.SCREENSHOT");
1675 am_args.push_back(screenshot_path);
1676 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001677 if (is_remote_mode) {
1678 am_args.push_back("--es");
1679 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1680 am_args.push_back(SHA256_file_hash(path));
1681 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1682 } else {
1683 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1684 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001685 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001686 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001687 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001688 }
1689
Felipe Lemecbce55d2016-02-08 09:53:18 -08001690 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001691 MYLOGI("done (id %lu)\n", id);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001692
Felipe Leme107a05f2016-03-08 15:11:15 -08001693 if (is_redirecting) {
1694 fclose(stderr);
1695 }
1696
Felipe Leme02b7e002016-07-22 12:03:20 -07001697 if (use_control_socket && control_socket_fd != -1) {
1698 MYLOGD("Closing control socket\n");
1699 close(control_socket_fd);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001700 }
1701
Colin Crossf45fa6b2012-03-26 12:38:26 -07001702 return 0;
1703}