blob: 3b9d5904e25a2ade265a0439e5cb467d8e7b7d2d [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
Ajay Panickerd886ec42016-09-14 12:26:46 -0700883 /* Dump Bluetooth HCI logs */
884 add_dir("/data/misc/bluetooth/logs", true);
885
Felipe Leme6e01fa62015-11-11 19:35:14 -0800886 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800887 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800888 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800889 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700890 }
891
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700892 // dumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700893 // calculate timeout
894 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
895 if (timeout < 20000) {
896 timeout = 20000;
897 }
Felipe Leme30dbfa12016-09-02 12:43:26 -0700898 runCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
899 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800900 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700901 if (timeout < 20000) {
902 timeout = 20000;
903 }
Felipe Leme30dbfa12016-09-02 12:43:26 -0700904 runCommand("EVENT LOG",
905 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
906 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700907 timeout = logcat_timeout("radio");
908 if (timeout < 20000) {
909 timeout = 20000;
910 }
Felipe Leme30dbfa12016-09-02 12:43:26 -0700911 runCommand("RADIO LOG",
912 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
913 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700914
Felipe Leme30dbfa12016-09-02 12:43:26 -0700915 runCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
Mark Salyzynecc07632015-07-30 14:57:09 -0700916
Colin Crossf45fa6b2012-03-26 12:38:26 -0700917 /* show the traces we collected in main(), if that was done */
918 if (dump_traces_path != NULL) {
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700919 dumpFile("VM TRACES JUST NOW", dump_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700920 }
921
922 /* only show ANR traces if they're less than 15 minutes old */
923 struct stat st;
924 char anr_traces_path[PATH_MAX];
925 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
926 if (!anr_traces_path[0]) {
927 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700928 } else {
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800929 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
930 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700931 if (fd < 0) {
932 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
933 } else {
934 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
935 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700936 }
937
938 /* slow traces for slow operations */
939 if (anr_traces_path[0] != 0) {
940 int tail = strlen(anr_traces_path)-1;
941 while (tail > 0 && anr_traces_path[tail] != '/') {
942 tail--;
943 }
944 int i = 0;
945 while (1) {
946 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
947 if (stat(anr_traces_path, &st)) {
948 // No traces file at this index, done with the files.
949 break;
950 }
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700951 dumpFile("VM TRACES WHEN SLOW", anr_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700952 i++;
953 }
954 }
955
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700956 int dumped = 0;
957 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
958 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800959 const char *name = tombstone_data[i].name;
960 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700961 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800962 if (zip_writer) {
963 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800964 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800965 }
966 } else {
967 dump_file_from_fd("TOMBSTONE", name, fd);
968 }
969 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700970 tombstone_data[i].fd = -1;
971 }
972 }
973 if (!dumped) {
974 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
975 }
976
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700977 dumpFile("NETWORK DEV INFO", "/proc/net/dev");
978 dumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
979 dumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
980 dumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
981 dumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700982
Todd Poynor2a83daa2013-11-22 15:44:22 -0800983 if (!stat(PSTORE_LAST_KMSG, &st)) {
984 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700985 dumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700986 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700987 dumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -0800988 } else {
989 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
Felipe Leme0bcc7ca2016-09-13 16:45:56 -0700990 dumpFile("LAST KMSG", "/proc/last_kmsg");
Todd Poynor2a83daa2013-11-22 15:44:22 -0800991 }
992
Mark Salyzyn2262c162014-12-16 09:09:26 -0800993 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Felipe Leme30dbfa12016-09-02 12:43:26 -0700994 runCommand("LAST LOGCAT",
995 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
Mark Salyzyn2262c162014-12-16 09:09:26 -0800996
Colin Crossf45fa6b2012-03-26 12:38:26 -0700997 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -0800998
Felipe Leme30dbfa12016-09-02 12:43:26 -0700999 runCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001000
Felipe Leme30dbfa12016-09-02 12:43:26 -07001001 runCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1002 runCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001003
Felipe Leme30dbfa12016-09-02 12:43:26 -07001004 runCommand("IP RULES", {"ip", "rule", "show"});
1005 runCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001006
1007 dump_route_tables();
1008
Felipe Leme30dbfa12016-09-02 12:43:26 -07001009 runCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1010 runCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1011 runCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1012 runCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
1013 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001014
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001015#ifdef FWDUMP_bcmdhd
Felipe Leme30dbfa12016-09-02 12:43:26 -07001016 runCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001017
Felipe Leme30dbfa12016-09-02 12:43:26 -07001018 runCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001019
Felipe Leme30dbfa12016-09-02 12:43:26 -07001020 runCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001021
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001022#endif
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001023 dumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001024
Felipe Leme30dbfa12016-09-02 12:43:26 -07001025 runDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1026 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001027
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001028#ifdef FWDUMP_bcmdhd
Felipe Leme30dbfa12016-09-02 12:43:26 -07001029 runCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001030
Felipe Leme30dbfa12016-09-02 12:43:26 -07001031 runCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001032
Felipe Leme30dbfa12016-09-02 12:43:26 -07001033 runCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001034#endif
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001035 dumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001036
1037 print_properties();
1038
Felipe Leme30dbfa12016-09-02 12:43:26 -07001039 runCommand("VOLD DUMP", {"vdc", "dump"});
1040 runCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001041
Felipe Leme30dbfa12016-09-02 12:43:26 -07001042 runCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001043
Felipe Leme30dbfa12016-09-02 12:43:26 -07001044 runCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001045
1046 printf("------ BACKLIGHTS ------\n");
1047 printf("LCD brightness=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001048 dumpFile(nullptr, "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001049 printf("Button brightness=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001050 dumpFile(nullptr, "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001051 printf("Keyboard brightness=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001052 dumpFile(nullptr, "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001053 printf("ALS mode=");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001054 dumpFile(nullptr, "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001055 printf("LCD driver registers:\n");
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001056 dumpFile(nullptr, "/sys/class/leds/lcd-backlight/registers");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001057 printf("\n");
1058
1059 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001060 dumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1061 dumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1062 dumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1063 dumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1064 dumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001065
Colin Crossf45fa6b2012-03-26 12:38:26 -07001066 printf("========================================================\n");
1067 printf("== Board\n");
1068 printf("========================================================\n");
1069
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001070 {
1071 DurationReporter tmpDr("dumpstate_board()");
1072 dumpstate_board();
1073 printf("\n");
1074 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001075
1076 /* Migrate the ril_dumpstate to a dumpstate_board()? */
1077 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
1078 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
1079 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001080 // su does not exist on user builds, so try running without it.
1081 // This way any implementations of vril-dump that do not require
1082 // root can run on user builds.
1083 CommandOptions::CommandOptionsBuilder options =
1084 CommandOptions::WithTimeout(atoi(ril_dumpstate_timeout));
1085 if (!is_user_build()) {
1086 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001087 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001088 runCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001089 }
1090
1091 printf("========================================================\n");
1092 printf("== Android Framework Services\n");
1093 printf("========================================================\n");
1094
Felipe Leme30dbfa12016-09-02 12:43:26 -07001095 runDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(60).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001096
1097 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001098 printf("== Checkins\n");
1099 printf("========================================================\n");
1100
Felipe Leme30dbfa12016-09-02 12:43:26 -07001101 runDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1102 runDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1103 runDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1104 runDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1105 runDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1106 runDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001107
1108 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001109 printf("== Running Application Activities\n");
1110 printf("========================================================\n");
1111
Felipe Leme30dbfa12016-09-02 12:43:26 -07001112 runDumpsys("APP ACTIVITIES", {"activity", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001113
1114 printf("========================================================\n");
1115 printf("== Running Application Services\n");
1116 printf("========================================================\n");
1117
Felipe Leme30dbfa12016-09-02 12:43:26 -07001118 runDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001119
1120 printf("========================================================\n");
1121 printf("== Running Application Providers\n");
1122 printf("========================================================\n");
1123
Felipe Leme30dbfa12016-09-02 12:43:26 -07001124 runDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001125
1126 printf("========================================================\n");
Felipe Leme608385d2016-02-01 10:35:38 -08001127 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1128 getpid(), progress, weight_total, WEIGHT_TOTAL);
1129 printf("========================================================\n");
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001130 printf("== dumpstate: done (id %lu)\n", id);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001131 printf("========================================================\n");
1132}
1133
1134static void usage() {
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001135 fprintf(stderr,
Felipe Leme2628e9e2016-04-12 16:36:51 -07001136 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1137 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1138 " -h: display this help message\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001139 " -b: play sound file instead of vibrate, at beginning of job\n"
1140 " -e: play sound file instead of vibrate, at end of job\n"
1141 " -o: write to file (instead of stdout)\n"
1142 " -d: append date to filename (requires -o)\n"
1143 " -p: capture screenshot to filename.png (requires -o)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001144 " -z: generate zipped file (requires -o)\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001145 " -s: write output to control socket (for init)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001146 " -S: write file location to control socket (for init; requires -o and -z)"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001147 " -q: disable vibrate\n"
1148 " -B: send broadcast when finished (requires -o)\n"
1149 " -P: send broadcast when started and update system properties on "
1150 "progress (requires -o and -B)\n"
1151 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1152 "shouldn't be used with -P)\n"
1153 " -V: sets the bugreport format version (valid values: %s)\n",
1154 VERSION_DEFAULT.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001155}
1156
Wei Liuf87959e2016-08-26 14:51:42 -07001157static void wake_lock_releaser() {
1158 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1159 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1160 } else {
1161 MYLOGD("Wake lock released.\n");
1162 }
1163}
1164
1165static void sig_handler(int signo) {
1166 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001167 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001168}
1169
Wei Liuf87959e2016-08-26 14:51:42 -07001170static void register_sig_handler() {
1171 struct sigaction sa;
1172 sigemptyset(&sa.sa_mask);
1173 sa.sa_flags = 0;
1174 sa.sa_handler = sig_handler;
1175 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1176 sigaction(SIGSEGV, &sa, NULL); // segment fault
1177 sigaction(SIGINT, &sa, NULL); // ctrl-c
1178 sigaction(SIGTERM, &sa, NULL); // killed
1179 sigaction(SIGQUIT, &sa, NULL); // quit
1180}
1181
Felipe Leme1e9edc62015-12-21 16:02:13 -08001182/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1183 temporary file.
1184 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001185static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Leme0f3fb202016-06-10 17:10:53 -07001186 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001187 // Final timestamp
1188 char date[80];
1189 time_t the_real_now_please_stand_up = time(nullptr);
1190 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
1191 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", id, date,
1192 the_real_now_please_stand_up - now);
1193
Felipe Lemee82a27d2016-01-05 13:35:44 -08001194 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001195 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001196 return false;
1197 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001198 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001199 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001200 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001201 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001202
Felipe Leme0f3fb202016-06-10 17:10:53 -07001203 // Add log file (which contains stderr output) to zip...
1204 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1205 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1206 MYLOGE("Failed to add dumpstate log to .zip file\n");
1207 return false;
1208 }
1209 // ... and re-opens it for further logging.
1210 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1211 fprintf(stderr, "\n");
1212
Felipe Lemee82a27d2016-01-05 13:35:44 -08001213 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001214 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001215 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001216 return false;
1217 }
1218
Felipe Lemec4eee562016-04-21 15:42:55 -07001219 if (is_user_build()) {
1220 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1221 if (remove(bugreport_path.c_str())) {
1222 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1223 }
1224 } else {
1225 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1226 }
1227
Felipe Leme1e9edc62015-12-21 16:02:13 -08001228 return true;
1229}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001230
Michal Karpinski4db754f2015-12-11 18:04:32 +00001231static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001232 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1233 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001234 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001235 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001236 return NULL;
1237 }
1238
1239 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001240 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001241
1242 std::vector<uint8_t> buffer(65536);
1243 while (1) {
1244 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1245 if (bytes_read == 0) {
1246 break;
1247 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001248 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001249 return NULL;
1250 }
1251
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001252 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001253 }
1254
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001255 uint8_t hash[SHA256_DIGEST_LENGTH];
1256 SHA256_Final(hash, &ctx);
1257
1258 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1259 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001260 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001261 }
1262 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1263 return std::string(hash_buffer);
1264}
1265
Colin Crossf45fa6b2012-03-26 12:38:26 -07001266int main(int argc, char *argv[]) {
1267 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001268 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001269 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001270 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001271 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001272 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001273 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001274 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001275 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001276 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001277 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001278
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001279 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001280
Felipe Lemecbce55d2016-02-08 09:53:18 -08001281 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001282
Wei Liuf87959e2016-08-26 14:51:42 -07001283 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1284 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1285 } else {
1286 MYLOGD("Wake lock acquired.\n");
1287 atexit(wake_lock_releaser);
1288 register_sig_handler();
1289 }
1290
Felipe Leme8268ed22016-08-02 18:18:25 -07001291 dry_run = property_get_bool("dumpstate.dry_run", 0) != 0;
1292 if (is_dry_run()) {
1293 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1294 }
1295
Felipe Leme30dbfa12016-09-02 12:43:26 -07001296 std::string args;
1297 for (int i = 0; i < argc; i++) {
1298 args += argv[i];
1299 args += " ";
1300 }
1301 MYLOGD("Dumpstate command line: %s\n", args.c_str());
1302
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001303 /* gets the sequential id */
1304 char last_id[PROPERTY_VALUE_MAX];
1305 property_get("dumpstate.last_id", last_id, "0");
1306 id = strtoul(last_id, NULL, 10) + 1;
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001307 snprintf(last_id, sizeof(last_id), "%lu", id);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001308 property_set("dumpstate.last_id", last_id);
1309 MYLOGI("dumpstate id: %lu\n", id);
1310
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 Leme71bbfc52015-11-23 14:14:51 -08001331 case 'd': do_add_date = 1; break;
1332 case 'z': do_zip_file = 1; break;
1333 case 'o': use_outfile = optarg; break;
1334 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001335 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001336 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001337 case 'q': do_vibrate = 0; break;
1338 case 'p': do_fb = 1; break;
1339 case 'P': do_update_progress = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001340 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001341 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001342 case 'V': version = optarg; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001343 case '?': printf("\n");
1344 case 'h':
1345 usage();
1346 exit(1);
1347 }
1348 }
1349
Felipe Leme71bbfc52015-11-23 14:14:51 -08001350 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001351 usage();
1352 exit(1);
1353 }
1354
Felipe Leme2628e9e2016-04-12 16:36:51 -07001355 if (use_control_socket && !do_zip_file) {
1356 usage();
1357 exit(1);
1358 }
1359
Felipe Leme71bbfc52015-11-23 14:14:51 -08001360 if (do_update_progress && !do_broadcast) {
1361 usage();
1362 exit(1);
1363 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001364
Michal Karpinski4db754f2015-12-11 18:04:32 +00001365 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1366 usage();
1367 exit(1);
1368 }
1369
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001370 if (version != VERSION_DEFAULT) {
1371 usage();
1372 exit(1);
Felipe Leme809d74e2016-02-02 12:57:00 -08001373 }
1374
Felipe Lemecbce55d2016-02-08 09:53:18 -08001375 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001376
Felipe Lemee338bf62015-12-07 14:03:50 -08001377 do_early_screenshot = do_update_progress;
1378
Christopher Ferrised9354f2014-10-01 17:35:01 -07001379 // If we are going to use a socket, do it as early as possible
1380 // to avoid timeouts from bugreport.
1381 if (use_socket) {
1382 redirect_to_socket(stdout, "dumpstate");
1383 }
1384
Felipe Leme2628e9e2016-04-12 16:36:51 -07001385 if (use_control_socket) {
1386 MYLOGD("Opening control socket\n");
1387 control_socket_fd = open_socket("dumpstate");
Felipe Leme02b7e002016-07-22 12:03:20 -07001388 do_update_progress = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001389 }
1390
Felipe Lemecbce55d2016-02-08 09:53:18 -08001391 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001392 std::string tmp_path;
1393
Felipe Leme0f3fb202016-06-10 17:10:53 -07001394 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001395 std::string log_path;
1396
Felipe Leme14e034a2016-03-30 18:51:03 -07001397 /* full path of the systrace file, when enabled */
1398 std::string systrace_path;
1399
Felipe Lemee338bf62015-12-07 14:03:50 -08001400 /* full path of the temporary file containing the screenshot (when requested) */
1401 std::string screenshot_path;
1402
Felipe Lemecbce55d2016-02-08 09:53:18 -08001403 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001404 std::string base_name;
1405
Felipe Leme71bbfc52015-11-23 14:14:51 -08001406 /* pointer to the actual path, be it zip or text */
1407 std::string path;
1408
Felipe Leme635ca312016-01-05 14:23:02 -08001409 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001410 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001411
Felipe Lemead5f6c42015-11-30 14:26:46 -08001412 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001413 bool is_redirecting = !use_socket && use_outfile;
1414
1415 if (is_redirecting) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001416 bugreport_dir = dirname(use_outfile);
1417 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001418 if (do_add_date) {
1419 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001420 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1421 suffix = date;
1422 } else {
1423 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001424 }
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001425 char build_id[PROPERTY_VALUE_MAX];
1426 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1427 base_name = base_name + "-" + build_id;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001428 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001429 // TODO: if dumpstate was an object, the paths could be internal variables and then
1430 // we could have a function to calculate the derived values, such as:
1431 // screenshot_path = GetPath(".png");
1432 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001433 }
Felipe Lemead5f6c42015-11-30 14:26:46 -08001434 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
Felipe Lemecbce55d2016-02-08 09:53:18 -08001435 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1436 + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001437
Felipe Lemecbce55d2016-02-08 09:53:18 -08001438 MYLOGD("Bugreport dir: %s\n"
1439 "Base name: %s\n"
1440 "Suffix: %s\n"
1441 "Log path: %s\n"
1442 "Temporary path: %s\n"
1443 "Screenshot path: %s\n",
1444 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1445 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001446
Felipe Leme1e9edc62015-12-21 16:02:13 -08001447 if (do_zip_file) {
Felipe Leme1e9edc62015-12-21 16:02:13 -08001448 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001449 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001450 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001451 zip_file.reset(fopen(path.c_str(), "wb"));
1452 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001453 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001454 do_zip_file = 0;
1455 } else {
1456 zip_writer.reset(new ZipWriter(zip_file.get()));
1457 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001458 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001459 }
1460
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001461 if (do_update_progress) {
1462 if (do_broadcast) {
1463 // clang-format off
1464 std::vector<std::string> am_args = {
1465 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1466 "--es", "android.intent.extra.NAME", suffix,
1467 "--ei", "android.intent.extra.ID", std::to_string(id),
1468 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1469 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1470 };
1471 // clang-format on
1472 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1473 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001474 if (use_control_socket) {
1475 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1476 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001477 }
1478 }
1479
Nick Kralevichf3599b32016-01-25 15:05:16 -08001480 /* read /proc/cmdline before dropping root */
1481 FILE *cmdline = fopen("/proc/cmdline", "re");
1482 if (cmdline) {
1483 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1484 fclose(cmdline);
1485 }
1486
Jeff Brown1dc94e32014-09-11 14:15:27 -07001487 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001488 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001489 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001490 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001491 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001492 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001493 }
John Michelau1f794c42012-09-17 11:20:19 -05001494 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001495
Felipe Leme3634a1e2015-12-09 10:11:47 -08001496 if (do_fb && do_early_screenshot) {
1497 if (screenshot_path.empty()) {
1498 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001499 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001500 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001501 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001502 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001503 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001504 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001505 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001506 screenshot_path.c_str(), strerror(errno));
1507 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001508 }
1509 }
1510
Felipe Leme1e9edc62015-12-21 16:02:13 -08001511 if (do_zip_file) {
1512 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001513 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001514 }
1515 }
1516
Felipe Leme71bbfc52015-11-23 14:14:51 -08001517 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001518 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001519 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1520 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1521 log_path.c_str(), strerror(errno));
1522 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001523 /* TODO: rather than generating a text file now and zipping it later,
1524 it would be more efficient to redirect stdout to the zip entry
1525 directly, but the libziparchive doesn't support that option yet. */
1526 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001527 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1528 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1529 tmp_path.c_str(), strerror(errno));
1530 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001531 }
Felipe Leme608385d2016-02-01 10:35:38 -08001532 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1533 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001534 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001535 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001536
Felipe Leme71a74ac2016-03-17 15:43:25 -07001537 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001538 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1539 // the raw trace.
1540 if (!dump_anrd_trace()) {
1541 dump_systrace();
1542 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001543
Wei Liu341938b2016-04-27 16:18:17 -07001544 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
Felipe Lemeefd7e272016-05-18 09:27:16 -07001545 dump_raft();
Wei Liu341938b2016-04-27 16:18:17 -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 Leme30dbfa12016-09-02 12:43:26 -07001549 runDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1550 CommandOptions::WithTimeout(90).DropRoot().Build());
1551 runDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1552 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001553
1554 /* collect stack traces from Dalvik and native processes (needs root) */
1555 dump_traces_path = dump_traces();
1556
Felipe Lemec0808152016-06-17 17:37:13 -07001557 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001558 get_tombstone_fds(tombstone_data);
1559 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001560 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001561 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001562 if (!is_user_build()) {
1563 add_dir(PROFILE_DATA_DIR_CUR, true);
1564 add_dir(PROFILE_DATA_DIR_REF, true);
1565 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001566 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001567 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001568
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001569 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001570 return -1;
1571 }
1572
1573 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001574
Felipe Leme55b42a62015-11-10 17:39:08 -08001575 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001576 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001577 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001578 }
1579
Felipe Leme6e01fa62015-11-11 19:35:14 -08001580 /* rename or zip the (now complete) .tmp file to its final location */
1581 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001582
1583 /* check if user changed the suffix using system properties */
1584 char key[PROPERTY_KEY_MAX];
1585 char value[PROPERTY_VALUE_MAX];
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001586 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001587 property_get(key, value, "");
1588 bool change_suffix= false;
1589 if (value[0]) {
1590 /* must whitelist which characters are allowed, otherwise it could cross directories */
1591 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1592 if (std::regex_match(value, valid_regex)) {
1593 change_suffix = true;
1594 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001595 MYLOGE("invalid suffix provided by user: %s\n", value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001596 }
1597 }
1598 if (change_suffix) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001599 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001600 suffix = value;
1601 if (!screenshot_path.empty()) {
1602 std::string new_screenshot_path =
1603 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1604 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001605 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001606 new_screenshot_path.c_str(), strerror(errno));
1607 } else {
1608 screenshot_path = new_screenshot_path;
1609 }
1610 }
1611 }
1612
Felipe Leme6e01fa62015-11-11 19:35:14 -08001613 bool do_text_file = true;
1614 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001615 std::string entry_name = base_name + "-" + suffix + ".txt";
1616 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Leme0f3fb202016-06-10 17:10:53 -07001617 if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001618 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001619 do_text_file = true;
1620 } else {
1621 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001622 // Since zip file is already created, it needs to be renamed.
1623 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1624 if (path != new_path) {
1625 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1626 if (rename(path.c_str(), new_path.c_str())) {
1627 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1628 new_path.c_str(), strerror(errno));
1629 } else {
1630 path = new_path;
1631 }
1632 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001633 }
1634 }
1635 if (do_text_file) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001636 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001637 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001638 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001639 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001640 path.clear();
1641 }
1642 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001643 if (use_control_socket) {
1644 if (do_text_file) {
1645 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1646 "for more details\n", log_path.c_str());
1647 } else {
1648 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1649 }
1650 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001651 }
1652
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001653 /* vibrate a few but shortly times to let user know it's finished */
1654 if (vibrator) {
1655 for (int i = 0; i < 3; i++) {
1656 vibrate(vibrator.get(), 75);
1657 usleep((75 + 50) * 1000);
1658 }
1659 }
1660
Jeff Brown1dc94e32014-09-11 14:15:27 -07001661 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001662 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001663 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001664 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001665 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001666 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001667 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001668 "--ei", "android.intent.extra.ID", std::to_string(id),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001669 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemeee2e4a02016-02-22 18:12:11 -08001670 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001671 "--es", "android.intent.extra.BUGREPORT", path,
1672 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001673 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001674 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001675 if (do_fb) {
1676 am_args.push_back("--es");
1677 am_args.push_back("android.intent.extra.SCREENSHOT");
1678 am_args.push_back(screenshot_path);
1679 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001680 if (is_remote_mode) {
1681 am_args.push_back("--es");
1682 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1683 am_args.push_back(SHA256_file_hash(path));
1684 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1685 } else {
1686 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1687 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001688 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001689 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001690 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001691 }
1692
Felipe Lemecbce55d2016-02-08 09:53:18 -08001693 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001694 MYLOGI("done (id %lu)\n", id);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001695
Felipe Leme107a05f2016-03-08 15:11:15 -08001696 if (is_redirecting) {
1697 fclose(stderr);
1698 }
1699
Felipe Leme02b7e002016-07-22 12:03:20 -07001700 if (use_control_socket && control_socket_fd != -1) {
1701 MYLOGD("Closing control socket\n");
1702 close(control_socket_fd);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001703 }
1704
Colin Crossf45fa6b2012-03-26 12:38:26 -07001705 return 0;
1706}