blob: 93f17fe144b0b191e0e53d3f7beadf1c92c78f5d [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 */
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070016#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070017
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070018#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070019#include <errno.h>
20#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080021#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070022#include <limits.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080023#include <memory>
Felipe Lemead5f6c42015-11-30 14:26:46 -080024#include <regex>
Felipe Leme635ca312016-01-05 14:23:02 -080025#include <set>
Wei Liuf87959e2016-08-26 14:51:42 -070026#include <signal.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070027#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070028#include <stdio.h>
29#include <stdlib.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080030#include <string>
Colin Crossf45fa6b2012-03-26 12:38:26 -070031#include <string.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070032#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070033#include <sys/resource.h>
34#include <sys/stat.h>
35#include <sys/time.h>
36#include <sys/wait.h>
37#include <unistd.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070038
Elliott Hughes9dc117c2015-12-07 14:21:50 -080039#include <android-base/stringprintf.h>
Andreas Gampefcc8db92016-07-18 18:01:27 -070040#include <android-base/unique_fd.h>
Zhengyin Qian068ecc72016-08-10 16:48:14 -070041#include <android-base/file.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Wei Liuf87959e2016-08-26 14:51:42 -070043#include <hardware_legacy/power.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070045#include <private/android_filesystem_config.h>
46#include <private/android_logger.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070047
48#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080049#include "ziparchive/zip_writer.h"
50
Elliott Hughesc4dc1412016-04-12 16:28:31 -070051#include <openssl/sha.h>
Michal Karpinski4db754f2015-12-11 18:04:32 +000052
Felipe Leme6e01fa62015-11-11 19:35:14 -080053using android::base::StringPrintf;
Colin Crossf45fa6b2012-03-26 12:38:26 -070054
55/* read before root is shed */
56static char cmdline_buf[16384] = "(unknown)";
57static const char *dump_traces_path = NULL;
58
Felipe Lemeefd7e272016-05-18 09:27:16 -070059// TODO: variables below should be part of dumpstate object
Felipe Leme8fecfdd2016-02-09 10:40:07 -080060static unsigned long id;
Felipe Leme78f2c862015-12-21 09:55:22 -080061static char build_type[PROPERTY_VALUE_MAX];
Felipe Lemee82a27d2016-01-05 13:35:44 -080062static time_t now;
63static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080064static std::set<std::string> mount_points;
65void add_mountinfo();
Felipe Leme02b7e002016-07-22 12:03:20 -070066int control_socket_fd = -1;
Felipe Lemeefd7e272016-05-18 09:27:16 -070067/* suffix of the bugreport files - it's typically the date (when invoked with -d),
68 * although it could be changed by the user using a system property */
69static std::string suffix;
Felipe Leme78f2c862015-12-21 09:55:22 -080070
Todd Poynor2a83daa2013-11-22 15:44:22 -080071#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070072#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080073
Wei Liu341938b2016-04-27 16:18:17 -070074#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080075#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070076#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070077#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010078#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
79#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070080#define TOMBSTONE_DIR "/data/tombstones"
81#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
82/* Can accomodate a tombstone number up to 9999. */
83#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
84#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090085#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070086#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070087
88typedef struct {
89 char name[TOMBSTONE_MAX_LEN];
90 int fd;
91} tombstone_data_t;
92
93static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
94
Felipe Leme71ca15e2016-05-19 16:18:17 -070095const std::string ZIP_ROOT_DIR = "FS";
96std::string bugreport_dir;
Felipe Lemee82a27d2016-01-05 13:35:44 -080097
Felipe Leme809d74e2016-02-02 12:57:00 -080098/*
99 * List of supported zip format versions.
100 *
101 * See bugreport-format.txt for more info.
102 */
Felipe Lemeca9c12e2016-05-19 16:30:15 -0700103static std::string VERSION_DEFAULT = "1.0";
Felipe Leme809d74e2016-02-02 12:57:00 -0800104
Calvin On249beee2016-06-03 15:17:07 -0700105bool is_user_build() {
Felipe Lemec4eee562016-04-21 15:42:55 -0700106 return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
107}
108
Felipe Lemee82a27d2016-01-05 13:35:44 -0800109/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
110 * otherwise gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700111static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800112 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700113 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
114 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800115 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
116 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700117 struct stat st;
118 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800119 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
120 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700121 } else {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800122 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700123 data[i].fd = -1;
124 }
125 }
126}
127
Felipe Leme635ca312016-01-05 14:23:02 -0800128// for_each_pid() callback to get mount info about a process.
129void do_mountinfo(int pid, const char *name) {
130 char path[PATH_MAX];
131
132 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
133 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700134 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800135 char linkname[PATH_MAX];
136 ssize_t r = readlink(path, linkname, PATH_MAX);
137 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800138 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800139 return;
140 }
141 linkname[r] = '\0';
142
143 if (mount_points.find(linkname) == mount_points.end()) {
144 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700145 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800146 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
147 mount_points.insert(linkname);
148 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800149 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800150 }
151 }
152}
153
154void add_mountinfo() {
155 if (!zip_writer) return;
156 const char *title = "MOUNT INFO";
157 mount_points.clear();
Felipe Leme608385d2016-02-01 10:35:38 -0800158 DurationReporter duration_reporter(title, NULL);
Felipe Leme635ca312016-01-05 14:23:02 -0800159 for_each_pid(do_mountinfo, NULL);
Felipe Leme1b0225a2016-02-09 16:35:14 -0800160 MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800161}
162
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700163static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
164{
165 DIR *d;
166 struct dirent *de;
167 char path[PATH_MAX];
168
169 d = opendir(driverpath);
170 if (d == NULL) {
171 return;
172 }
173
174 while ((de = readdir(d))) {
175 if (de->d_type != DT_LNK) {
176 continue;
177 }
178 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
179 dump_file(title, path);
180 }
181
182 closedir(d);
183}
184
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700185// return pid of a userspace process. If not found or error, return 0.
186static unsigned int pid_of_process(const char* ps_name) {
187 DIR *proc_dir;
188 struct dirent *ps;
189 unsigned int pid;
190 std::string cmdline;
191
192 if (!(proc_dir = opendir("/proc"))) {
193 MYLOGE("Can't open /proc\n");
194 return 0;
195 }
196
197 while ((ps = readdir(proc_dir))) {
198 if (!(pid = atoi(ps->d_name))) {
199 continue;
200 }
201 android::base::ReadFileToString("/proc/"
202 + std::string(ps->d_name) + "/cmdline", &cmdline);
203 if (cmdline.find(ps_name) == std::string::npos) {
204 continue;
205 } else {
206 closedir(proc_dir);
207 return pid;
208 }
209 }
210 closedir(proc_dir);
211 return 0;
212}
213
214// dump anrd's trace and add to the zip file.
215// 1. check if anrd is running on this device.
216// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
217// 3. wait until the trace generation completes and add to the zip file.
218static bool dump_anrd_trace() {
219 unsigned int pid;
220 char buf[50], path[PATH_MAX];
221 struct dirent *trace;
222 struct stat st;
223 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700224 int retry = 5;
225 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700226 long long cur_size = 0;
227 const char *trace_path = "/data/misc/anrd/";
228
229 if (!zip_writer) {
230 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
231 return false;
232 }
233
234 // find anrd's pid if it is running.
235 pid = pid_of_process("/system/xbin/anrd");
236
237 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700238 if (stat(trace_path, &st) == 0) {
239 old_mtime = st.st_mtime;
240 } else {
241 MYLOGE("Failed to find: %s\n", trace_path);
242 return false;
243 }
244
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700245 // send SIGUSR1 to the anrd to generate a trace.
246 sprintf(buf, "%u", pid);
247 if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
248 MYLOGE("anrd signal timed out. Please manually collect trace\n");
249 return false;
250 }
251
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700252 while (retry-- > 0 && old_mtime == st.st_mtime) {
253 sleep(1);
254 stat(trace_path, &st);
255 }
256
257 if (retry < 0 && old_mtime == st.st_mtime) {
258 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
259 return false;
260 }
261
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700262 // identify the trace file by its creation time.
263 if (!(trace_dir = opendir(trace_path))) {
264 MYLOGE("Can't open trace file under %s\n", trace_path);
265 }
266 while ((trace = readdir(trace_dir))) {
267 if (strcmp(trace->d_name, ".") == 0
268 || strcmp(trace->d_name, "..") == 0) {
269 continue;
270 }
271 sprintf(path, "%s%s", trace_path, trace->d_name);
272 if (stat(path, &st) == 0) {
273 if (st.st_ctime > max_ctime) {
274 max_ctime = st.st_ctime;
275 sprintf(buf, "%s", trace->d_name);
276 }
277 }
278 }
279 closedir(trace_dir);
280
281 // Wait until the dump completes by checking the size of the trace.
282 if (max_ctime > 0) {
283 sprintf(path, "%s%s", trace_path, buf);
284 while(true) {
285 sleep(1);
286 if (stat(path, &st) == 0) {
287 if (st.st_size == cur_size) {
288 break;
289 } else if (st.st_size > cur_size) {
290 cur_size = st.st_size;
291 } else {
292 return false;
293 }
294 } else {
295 MYLOGE("Cant stat() %s anymore\n", path);
296 return false;
297 }
298 }
299 // Add to the zip file.
300 if (!add_zip_entry("anrd_trace.txt", path)) {
301 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
302 } else {
303 if (remove(path)) {
304 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
305 }
306 return true;
307 }
308 } else {
309 MYLOGE("Can't stats any trace file under %s\n", trace_path);
310 }
311 }
312 return false;
313}
314
Felipe Lemeefd7e272016-05-18 09:27:16 -0700315static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700316 if (!zip_writer) {
317 MYLOGD("Not dumping systrace because zip_writer is not set\n");
318 return;
319 }
Felipe Lemeefd7e272016-05-18 09:27:16 -0700320 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700321 if (systrace_path.empty()) {
322 MYLOGE("Not dumping systrace because path is empty\n");
323 return;
324 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700325 const char* path = "/sys/kernel/debug/tracing/tracing_on";
326 long int is_tracing;
327 if (read_file_as_long(path, &is_tracing)) {
328 return; // error already logged
329 }
330 if (is_tracing <= 0) {
331 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
332 return;
333 }
334
Felipe Leme14e034a2016-03-30 18:51:03 -0700335 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
336 systrace_path.c_str());
337 if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
338 systrace_path.c_str(), NULL)) {
339 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
340 // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
341 // we should call strace to stop itself, but there is no such option yet (just a
342 // --async_stop, which stops and dump
343 // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
344 // MYLOGE("could not stop systrace ");
345 // }
346 }
347 if (!add_zip_entry("systrace.txt", systrace_path)) {
348 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700349 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700350 if (remove(systrace_path.c_str())) {
351 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
352 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700353 }
354}
355
Felipe Lemeefd7e272016-05-18 09:27:16 -0700356static void dump_raft() {
Wei Liu341938b2016-04-27 16:18:17 -0700357 if (is_user_build()) {
358 return;
359 }
360
Felipe Lemeefd7e272016-05-18 09:27:16 -0700361 std::string raft_log_path = bugreport_dir + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700362 if (raft_log_path.empty()) {
363 MYLOGD("raft_log_path is empty\n");
364 return;
365 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700366
367 struct stat s;
368 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
369 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
370 return;
371 }
372
Wei Liu341938b2016-04-27 16:18:17 -0700373 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700374 // Write compressed and encoded raft logs to stdout if not zip_writer.
375 run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
Wei Liu341938b2016-04-27 16:18:17 -0700376 return;
377 }
378
379 run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
380 "-o", raft_log_path.c_str(), NULL);
381 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
382 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
383 } else {
384 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700385 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700386 }
387 }
388}
389
Mark Salyzyn326842f2015-04-30 09:49:41 -0700390static bool skip_not_stat(const char *path) {
391 static const char stat[] = "/stat";
392 size_t len = strlen(path);
393 if (path[len - 1] == '/') { /* Directory? */
394 return false;
395 }
396 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
397}
398
Felipe Lemee82a27d2016-01-05 13:35:44 -0800399static bool skip_none(const char *path) {
400 return false;
401}
402
Mark Salyzyn326842f2015-04-30 09:49:41 -0700403static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700404unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700405
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800406//
407// stat offsets
408// Name units description
409// ---- ----- -----------
410// read I/Os requests number of read I/Os processed
411#define __STAT_READ_IOS 0
412// read merges requests number of read I/Os merged with in-queue I/O
413#define __STAT_READ_MERGES 1
414// read sectors sectors number of sectors read
415#define __STAT_READ_SECTORS 2
416// read ticks milliseconds total wait time for read requests
417#define __STAT_READ_TICKS 3
418// write I/Os requests number of write I/Os processed
419#define __STAT_WRITE_IOS 4
420// write merges requests number of write I/Os merged with in-queue I/O
421#define __STAT_WRITE_MERGES 5
422// write sectors sectors number of sectors written
423#define __STAT_WRITE_SECTORS 6
424// write ticks milliseconds total wait time for write requests
425#define __STAT_WRITE_TICKS 7
426// in_flight requests number of I/Os currently in flight
427#define __STAT_IN_FLIGHT 8
428// io_ticks milliseconds total time this block device has been active
429#define __STAT_IO_TICKS 9
430// time_in_queue milliseconds total wait time for all requests
431#define __STAT_IN_QUEUE 10
432#define __STAT_NUMBER_FIELD 11
433//
434// read I/Os, write I/Os
435// =====================
436//
437// These values increment when an I/O request completes.
438//
439// read merges, write merges
440// =========================
441//
442// These values increment when an I/O request is merged with an
443// already-queued I/O request.
444//
445// read sectors, write sectors
446// ===========================
447//
448// These values count the number of sectors read from or written to this
449// block device. The "sectors" in question are the standard UNIX 512-byte
450// sectors, not any device- or filesystem-specific block size. The
451// counters are incremented when the I/O completes.
452#define SECTOR_SIZE 512
453//
454// read ticks, write ticks
455// =======================
456//
457// These values count the number of milliseconds that I/O requests have
458// waited on this block device. If there are multiple I/O requests waiting,
459// these values will increase at a rate greater than 1000/second; for
460// example, if 60 read requests wait for an average of 30 ms, the read_ticks
461// field will increase by 60*30 = 1800.
462//
463// in_flight
464// =========
465//
466// This value counts the number of I/O requests that have been issued to
467// the device driver but have not yet completed. It does not include I/O
468// requests that are in the queue but not yet issued to the device driver.
469//
470// io_ticks
471// ========
472//
473// This value counts the number of milliseconds during which the device has
474// had I/O requests queued.
475//
476// time_in_queue
477// =============
478//
479// This value counts the number of milliseconds that I/O requests have waited
480// on this block device. If there are multiple I/O requests waiting, this
481// value will increase as the product of the number of milliseconds times the
482// number of requests waiting (see "read ticks" above for an example).
483#define S_TO_MS 1000
484//
485
Mark Salyzyn326842f2015-04-30 09:49:41 -0700486static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800487 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700488 bool z;
489 char *cp, *buffer = NULL;
490 size_t i = 0;
491 FILE *fp = fdopen(fd, "rb");
492 getline(&buffer, &i, fp);
493 fclose(fp);
494 if (!buffer) {
495 return -errno;
496 }
497 i = strlen(buffer);
498 while ((i > 0) && (buffer[i - 1] == '\n')) {
499 buffer[--i] = '\0';
500 }
501 if (!*buffer) {
502 free(buffer);
503 return 0;
504 }
505 z = true;
506 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800507 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700508 if (fields[i] != 0) {
509 z = false;
510 }
511 }
512 if (z) { /* never accessed */
513 free(buffer);
514 return 0;
515 }
516
517 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
518 path += sizeof(mmcblk0) - 1;
519 }
520
521 printf("%s: %s\n", path, buffer);
522 free(buffer);
523
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800524 if (fields[__STAT_IO_TICKS]) {
525 unsigned long read_perf = 0;
526 unsigned long read_ios = 0;
527 if (fields[__STAT_READ_TICKS]) {
528 unsigned long long divisor = fields[__STAT_READ_TICKS]
529 * fields[__STAT_IO_TICKS];
530 read_perf = ((unsigned long long)SECTOR_SIZE
531 * fields[__STAT_READ_SECTORS]
532 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
533 / divisor;
534 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
535 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
536 / divisor;
537 }
538
539 unsigned long write_perf = 0;
540 unsigned long write_ios = 0;
541 if (fields[__STAT_WRITE_TICKS]) {
542 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
543 * fields[__STAT_IO_TICKS];
544 write_perf = ((unsigned long long)SECTOR_SIZE
545 * fields[__STAT_WRITE_SECTORS]
546 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
547 / divisor;
548 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
549 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
550 / divisor;
551 }
552
553 unsigned queue = (fields[__STAT_IN_QUEUE]
554 + (fields[__STAT_IO_TICKS] >> 1))
555 / fields[__STAT_IO_TICKS];
556
557 if (!write_perf && !write_ios) {
558 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
559 path, read_perf, read_ios, queue);
560 } else {
561 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
562 path, read_perf, read_ios, write_perf, write_ios, queue);
563 }
564
565 /* bugreport timeout factor adjustment */
566 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
567 worst_write_perf = write_perf;
568 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700569 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700570 return 0;
571}
572
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700573/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800574static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700575 log_id_t id = android_name_to_log_id(name);
576 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700577 /* Engineering margin is ten-fold our guess */
578 return 10 * (property_size + worst_write_perf) / worst_write_perf;
579}
580
Colin Crossf45fa6b2012-03-26 12:38:26 -0700581/* dumps the current system state to stdout */
Felipe Leme809d74e2016-02-02 12:57:00 -0800582static void print_header(std::string version) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700583 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
584 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
585 char network[PROPERTY_VALUE_MAX], date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700586
587 property_get("ro.build.display.id", build, "(unknown)");
588 property_get("ro.build.fingerprint", fingerprint, "(unknown)");
589 property_get("ro.build.type", build_type, "(unknown)");
Junda Liu58ad9292016-06-12 11:51:54 -0700590 property_get("gsm.version.baseband", radio, "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700591 property_get("ro.bootloader", bootloader, "(unknown)");
592 property_get("gsm.operator.alpha", network, "(unknown)");
593 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
594
595 printf("========================================================\n");
596 printf("== dumpstate: %s\n", date);
597 printf("========================================================\n");
598
599 printf("\n");
600 printf("Build: %s\n", build);
601 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
602 printf("Bootloader: %s\n", bootloader);
603 printf("Radio: %s\n", radio);
604 printf("Network: %s\n", network);
605
606 printf("Kernel: ");
607 dump_file(NULL, "/proc/version");
608 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800609 printf("Bugreport format version: %s\n", version.c_str());
Felipe Leme8fecfdd2016-02-09 10:40:07 -0800610 printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700611 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800612}
613
Felipe Leme24b66ee2016-06-16 10:55:26 -0700614// List of file extensions that can cause a zip file attachment to be rejected by some email
615// service providers.
616static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
617 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
618 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
619 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
620};
621
Felipe Leme71ca15e2016-05-19 16:18:17 -0700622bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800623 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800624 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
625 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800626 return false;
627 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700628 std::string valid_name = entry_name;
629
630 // Rename extension if necessary.
631 size_t idx = entry_name.rfind(".");
632 if (idx != std::string::npos) {
633 std::string extension = entry_name.substr(idx);
634 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
635 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
636 valid_name = entry_name + ".renamed";
637 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
638 }
639 }
640
Felipe Leme6fe9db62016-02-12 09:04:16 -0800641 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
642 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700643 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800644 ZipWriter::kCompress, get_mtime(fd, now));
645 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700646 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800647 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800648 return false;
649 }
650
Felipe Leme770410d2016-01-26 17:07:14 -0800651 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800652 while (1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800653 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
654 if (bytes_read == 0) {
655 break;
656 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800657 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800658 return false;
659 }
660 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
661 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800662 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800663 return false;
664 }
665 }
666
667 err = zip_writer->FinishEntry();
668 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800669 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800670 return false;
671 }
672
673 return true;
674}
675
Felipe Leme71ca15e2016-05-19 16:18:17 -0700676bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700677 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
678 | O_CLOEXEC)));
Andreas Gampefcc8db92016-07-18 18:01:27 -0700679 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800680 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800681 return false;
682 }
683
684 return add_zip_entry_from_fd(entry_name, fd.get());
685}
686
687/* adds a file to the existing zipped bugreport */
688static int _add_file_from_fd(const char *title, const char *path, int fd) {
689 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
690}
691
Felipe Leme24b66ee2016-06-16 10:55:26 -0700692// TODO: move to util.cpp
Felipe Lemee82a27d2016-01-05 13:35:44 -0800693void add_dir(const char *dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800694 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800695 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
Felipe Leme111b9d02016-02-03 09:28:24 -0800696 return;
697 }
Felipe Leme88c79332016-02-22 11:06:49 -0800698 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
Felipe Leme608385d2016-02-01 10:35:38 -0800699 DurationReporter duration_reporter(dir, NULL);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800700 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
701}
702
Felipe Leme809d74e2016-02-02 12:57:00 -0800703/* adds a text entry entry to the existing zip file. */
704static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800705 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800706 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 -0800707 return false;
708 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800709 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800710 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
711 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800712 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800713 ZipWriter::ErrorCodeString(err));
714 return false;
715 }
716
717 err = zip_writer->WriteBytes(content.c_str(), content.length());
718 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800719 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800720 ZipWriter::ErrorCodeString(err));
721 return false;
722 }
723
724 err = zip_writer->FinishEntry();
725 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800726 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800727 return false;
728 }
729
730 return true;
731}
732
Felipe Lemec0808152016-06-17 17:37:13 -0700733static void dump_iptables() {
734 run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
735 run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
Erik Kline53ca94a2016-09-28 17:26:26 +0900736 run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -0700737 /* no ip6 nat */
Erik Kline53ca94a2016-09-28 17:26:26 +0900738 run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
739 run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
740 run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
741 run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -0700742}
743
Srinath Sridharanfdf52d32016-02-01 15:50:22 -0800744static void dumpstate(const std::string& screenshot_path, const std::string& version) {
Felipe Leme770410d2016-01-26 17:07:14 -0800745 DurationReporter duration_reporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800746 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700747
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700748 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700749 run_command("UPTIME", 10, "uptime", NULL);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700750 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800751 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700752 dump_file("MEMORY INFO", "/proc/meminfo");
Elliott Hughes52860032016-06-14 13:56:00 -0700753 run_command("CPU INFO", 10, "top", "-b", "-n", "1", "-H", "-s", "6",
Elliott Hughes646e92f2016-06-13 17:35:07 -0700754 "-o", "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name", NULL);
Nick Kralevich2b1f88b2015-10-07 16:38:42 -0700755 run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700756 dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
757 dump_file("VMALLOC INFO", "/proc/vmallocinfo");
758 dump_file("SLAB INFO", "/proc/slabinfo");
759 dump_file("ZONEINFO", "/proc/zoneinfo");
760 dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
761 dump_file("BUDDYINFO", "/proc/buddyinfo");
Colin Cross2281af92012-10-28 22:41:06 -0700762 dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700763
Todd Poynor29e27a82012-05-22 17:54:59 -0700764 dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700765 dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Mathias Agopian85aea742012-08-08 15:32:02 -0700766 dump_file("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700767
Elliott Hughes52860032016-06-14 13:56:00 -0700768 run_command("PROCESSES AND THREADS", 10, "ps", "-A", "-T", "-Z",
Elliott Hughes32caf1d2016-05-04 14:03:54 -0700769 "-O", "pri,nice,rtprio,sched,pcy", NULL);
Nick Kralevichb82c9252015-11-27 17:56:13 -0800770 run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700771
Michal Karpinski4db754f2015-12-11 18:04:32 +0000772 run_command("PRINTENV", 10, "printenv", NULL);
Elliott Hughes0adb3a32016-10-28 08:53:02 -0700773 run_command("NETSTAT", 10, "netstat", "-nW", NULL);
Michal Karpinski4db754f2015-12-11 18:04:32 +0000774 run_command("LSMOD", 10, "lsmod", NULL);
775
Colin Crossf45fa6b2012-03-26 12:38:26 -0700776 do_dmesg();
777
778 run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700779 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
780 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800781 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700782
Ajay Panicker2f531772016-09-14 12:26:46 -0700783 /* Dump Bluetooth HCI logs */
784 add_dir("/data/misc/bluetooth/logs", true);
785
Felipe Leme6e01fa62015-11-11 19:35:14 -0800786 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800787 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800788 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800789 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700790 }
791
Colin Crossf45fa6b2012-03-26 12:38:26 -0700792 // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700793 // calculate timeout
794 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
795 if (timeout < 20000) {
796 timeout = 20000;
797 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700798 run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
799 "-v", "printable",
800 "-d",
801 "*:v", NULL);
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800802 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700803 if (timeout < 20000) {
804 timeout = 20000;
805 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700806 run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
807 "-v", "threadtime",
808 "-v", "printable",
809 "-d",
810 "*:v", NULL);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700811 timeout = logcat_timeout("radio");
812 if (timeout < 20000) {
813 timeout = 20000;
814 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700815 run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
816 "-v", "threadtime",
817 "-v", "printable",
818 "-d",
819 "*:v", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700820
Mark Salyzynecc07632015-07-30 14:57:09 -0700821 run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
822
Colin Crossf45fa6b2012-03-26 12:38:26 -0700823 /* show the traces we collected in main(), if that was done */
824 if (dump_traces_path != NULL) {
825 dump_file("VM TRACES JUST NOW", dump_traces_path);
826 }
827
828 /* only show ANR traces if they're less than 15 minutes old */
829 struct stat st;
830 char anr_traces_path[PATH_MAX];
831 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
832 if (!anr_traces_path[0]) {
833 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700834 } else {
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800835 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
836 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700837 if (fd < 0) {
838 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
839 } else {
840 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
841 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700842 }
843
844 /* slow traces for slow operations */
845 if (anr_traces_path[0] != 0) {
846 int tail = strlen(anr_traces_path)-1;
847 while (tail > 0 && anr_traces_path[tail] != '/') {
848 tail--;
849 }
850 int i = 0;
851 while (1) {
852 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
853 if (stat(anr_traces_path, &st)) {
854 // No traces file at this index, done with the files.
855 break;
856 }
857 dump_file("VM TRACES WHEN SLOW", anr_traces_path);
858 i++;
859 }
860 }
861
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700862 int dumped = 0;
863 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
864 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800865 const char *name = tombstone_data[i].name;
866 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700867 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800868 if (zip_writer) {
869 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800870 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800871 }
872 } else {
873 dump_file_from_fd("TOMBSTONE", name, fd);
874 }
875 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700876 tombstone_data[i].fd = -1;
877 }
878 }
879 if (!dumped) {
880 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
881 }
882
Colin Crossf45fa6b2012-03-26 12:38:26 -0700883 dump_file("NETWORK DEV INFO", "/proc/net/dev");
884 dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
JP Abgrall012c2ea2012-05-16 20:49:29 -0700885 dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700886 dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
887 dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
888
Todd Poynor2a83daa2013-11-22 15:44:22 -0800889 if (!stat(PSTORE_LAST_KMSG, &st)) {
890 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
891 dump_file("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700892 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
893 dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -0800894 } else {
895 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
896 dump_file("LAST KMSG", "/proc/last_kmsg");
897 }
898
Mark Salyzyn2262c162014-12-16 09:09:26 -0800899 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Mark Salyzyn78316382015-10-09 14:02:07 -0700900 run_command("LAST LOGCAT", 10, "logcat", "-L",
901 "-b", "all",
902 "-v", "threadtime",
903 "-v", "printable",
904 "-d",
905 "*:v", NULL);
Mark Salyzyn2262c162014-12-16 09:09:26 -0800906
Colin Crossf45fa6b2012-03-26 12:38:26 -0700907 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -0800908
909 run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
Lorenzo Colittid4c3d382014-07-30 14:38:20 +0900910
911 run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
912 run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
913
Colin Crossf45fa6b2012-03-26 12:38:26 -0700914 run_command("IP RULES", 10, "ip", "rule", "show", NULL);
915 run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -0700916
917 dump_route_tables();
918
Lorenzo Colittid4c3d382014-07-30 14:38:20 +0900919 run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
920 run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
Erik Klinef7f2b0f2016-05-27 11:29:19 +0900921 run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -0700922 run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700923
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -0800924#ifdef FWDUMP_bcmdhd
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900925 run_command("ND OFFLOAD TABLE", 5,
Erik Kline08165202016-05-30 11:55:44 +0900926 SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900927
928 run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
Erik Kline08165202016-05-30 11:55:44 +0900929 SU_PATH, "root", WLUTIL, "counters", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900930
931 run_command("ND OFFLOAD STATUS (1)", 5,
Erik Kline08165202016-05-30 11:55:44 +0900932 SU_PATH, "root", WLUTIL, "nd_status", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900933
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -0800934#endif
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -0800935 dump_file("INTERRUPTS (1)", "/proc/interrupts");
936
Felipe Leme7cff4622016-06-08 09:51:29 -0700937 run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900938
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -0800939#ifdef FWDUMP_bcmdhd
Colin Crossf45fa6b2012-03-26 12:38:26 -0700940 run_command("DUMP WIFI STATUS", 20,
941 SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900942
943 run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
Erik Kline08165202016-05-30 11:55:44 +0900944 SU_PATH, "root", WLUTIL, "counters", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +0900945
946 run_command("ND OFFLOAD STATUS (2)", 5,
Erik Kline08165202016-05-30 11:55:44 +0900947 SU_PATH, "root", WLUTIL, "nd_status", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700948#endif
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -0800949 dump_file("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700950
Elliott Hughes52eddba2017-02-28 10:14:22 -0800951 run_command("SYSTEM PROPERTIES", 5, "getprop", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700952
953 run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
954 run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
955
Ken Sumrall8f75fa72013-02-08 17:35:58 -0800956 run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700957
Colin Crossf45fa6b2012-03-26 12:38:26 -0700958 run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
959
960 printf("------ BACKLIGHTS ------\n");
961 printf("LCD brightness=");
962 dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
963 printf("Button brightness=");
964 dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
965 printf("Keyboard brightness=");
966 dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
967 printf("ALS mode=");
968 dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
969 printf("LCD driver registers:\n");
970 dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
971 printf("\n");
972
973 /* Binder state is expensive to look at as it uses a lot of memory. */
974 dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
975 dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
976 dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
977 dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
978 dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
979
Colin Crossf45fa6b2012-03-26 12:38:26 -0700980 printf("========================================================\n");
981 printf("== Board\n");
982 printf("========================================================\n");
983
984 dumpstate_board();
985 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700986
987 /* Migrate the ril_dumpstate to a dumpstate_board()? */
988 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
989 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
990 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
Felipe Lemec4eee562016-04-21 15:42:55 -0700991 if (is_user_build()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700992 // su does not exist on user builds, so try running without it.
993 // This way any implementations of vril-dump that do not require
994 // root can run on user builds.
995 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
996 "vril-dump", NULL);
997 } else {
998 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
999 SU_PATH, "root", "vril-dump", NULL);
1000 }
1001 }
1002
1003 printf("========================================================\n");
1004 printf("== Android Framework Services\n");
1005 printf("========================================================\n");
1006
Wei Liu34222562016-05-19 13:59:01 -07001007 run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001008
1009 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001010 printf("== Checkins\n");
1011 printf("========================================================\n");
1012
Felipe Leme7cff4622016-06-08 09:51:29 -07001013 run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1014 run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1015 run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1016 run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1017 run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1018 run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
Dianne Hackborn02bea972013-06-26 18:59:09 -07001019
1020 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001021 printf("== Running Application Activities\n");
1022 printf("========================================================\n");
1023
Felipe Leme3f83dbe2016-06-10 16:56:33 -07001024 run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001025
1026 printf("========================================================\n");
1027 printf("== Running Application Services\n");
1028 printf("========================================================\n");
1029
Felipe Leme3f83dbe2016-06-10 16:56:33 -07001030 run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001031
1032 printf("========================================================\n");
1033 printf("== Running Application Providers\n");
1034 printf("========================================================\n");
1035
Junda Liucfc33d42016-06-14 00:09:10 -07001036 run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001037
1038
1039 printf("========================================================\n");
Felipe Leme608385d2016-02-01 10:35:38 -08001040 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1041 getpid(), progress, weight_total, WEIGHT_TOTAL);
1042 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001043 printf("== dumpstate: done\n");
1044 printf("========================================================\n");
1045}
1046
1047static void usage() {
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001048 fprintf(stderr,
Felipe Leme2628e9e2016-04-12 16:36:51 -07001049 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1050 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1051 " -h: display this help message\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001052 " -b: play sound file instead of vibrate, at beginning of job\n"
1053 " -e: play sound file instead of vibrate, at end of job\n"
1054 " -o: write to file (instead of stdout)\n"
1055 " -d: append date to filename (requires -o)\n"
1056 " -p: capture screenshot to filename.png (requires -o)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001057 " -z: generate zipped file (requires -o)\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001058 " -s: write output to control socket (for init)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001059 " -S: write file location to control socket (for init; requires -o and -z)"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001060 " -q: disable vibrate\n"
1061 " -B: send broadcast when finished (requires -o)\n"
1062 " -P: send broadcast when started and update system properties on "
1063 "progress (requires -o and -B)\n"
1064 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1065 "shouldn't be used with -P)\n"
1066 " -V: sets the bugreport format version (valid values: %s)\n",
1067 VERSION_DEFAULT.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001068}
1069
Wei Liuf87959e2016-08-26 14:51:42 -07001070static void wake_lock_releaser() {
1071 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1072 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1073 } else {
1074 MYLOGD("Wake lock released.\n");
1075 }
1076}
1077
1078static void sig_handler(int signo) {
1079 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001080 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001081}
1082
Wei Liuf87959e2016-08-26 14:51:42 -07001083static void register_sig_handler() {
1084 struct sigaction sa;
1085 sigemptyset(&sa.sa_mask);
1086 sa.sa_flags = 0;
1087 sa.sa_handler = sig_handler;
1088 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1089 sigaction(SIGSEGV, &sa, NULL); // segment fault
1090 sigaction(SIGINT, &sa, NULL); // ctrl-c
1091 sigaction(SIGTERM, &sa, NULL); // killed
1092 sigaction(SIGQUIT, &sa, NULL); // quit
1093}
1094
Felipe Leme1e9edc62015-12-21 16:02:13 -08001095/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1096 temporary file.
1097 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001098static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Leme1e9edc62015-12-21 16:02:13 -08001099 time_t now) {
Felipe Lemee82a27d2016-01-05 13:35:44 -08001100 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001101 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001102 return false;
1103 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001104 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001105 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001106 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001107 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001108
Felipe Lemee82a27d2016-01-05 13:35:44 -08001109 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001110 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001111 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001112 return false;
1113 }
1114
Felipe Lemec4eee562016-04-21 15:42:55 -07001115 if (is_user_build()) {
1116 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1117 if (remove(bugreport_path.c_str())) {
1118 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1119 }
1120 } else {
1121 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1122 }
1123
Felipe Leme1e9edc62015-12-21 16:02:13 -08001124 return true;
1125}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001126
Michal Karpinski4db754f2015-12-11 18:04:32 +00001127static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001128 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1129 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampefcc8db92016-07-18 18:01:27 -07001130 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001131 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001132 return NULL;
1133 }
1134
1135 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001136 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001137
1138 std::vector<uint8_t> buffer(65536);
1139 while (1) {
1140 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1141 if (bytes_read == 0) {
1142 break;
1143 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001144 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001145 return NULL;
1146 }
1147
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001148 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001149 }
1150
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001151 uint8_t hash[SHA256_DIGEST_LENGTH];
1152 SHA256_Final(hash, &ctx);
1153
1154 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1155 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001156 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001157 }
1158 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1159 return std::string(hash_buffer);
1160}
1161
Colin Crossf45fa6b2012-03-26 12:38:26 -07001162int main(int argc, char *argv[]) {
1163 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001164 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001165 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001166 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001167 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001168 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001169 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001170 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001171 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001172 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001173 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001174
Felipe Lemee82a27d2016-01-05 13:35:44 -08001175 now = time(NULL);
1176
Felipe Lemecbce55d2016-02-08 09:53:18 -08001177 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001178
Wei Liuf87959e2016-08-26 14:51:42 -07001179 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1180 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1181 } else {
1182 MYLOGD("Wake lock acquired.\n");
1183 atexit(wake_lock_releaser);
1184 register_sig_handler();
1185 }
1186
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001187 /* gets the sequential id */
1188 char last_id[PROPERTY_VALUE_MAX];
1189 property_get("dumpstate.last_id", last_id, "0");
1190 id = strtoul(last_id, NULL, 10) + 1;
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001191 snprintf(last_id, sizeof(last_id), "%lu", id);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001192 property_set("dumpstate.last_id", last_id);
1193 MYLOGI("dumpstate id: %lu\n", id);
1194
Colin Crossf45fa6b2012-03-26 12:38:26 -07001195 /* set as high priority, and protect from OOM killer */
1196 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001197
1198 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001199 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001200 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001201 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001202 } else {
1203 /* fallback to kernels <= 2.6.35 */
1204 oom_adj = fopen("/proc/self/oom_adj", "we");
1205 if (oom_adj) {
1206 fputs("-17", oom_adj);
1207 fclose(oom_adj);
1208 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001209 }
1210
Jeff Brown1dc94e32014-09-11 14:15:27 -07001211 /* parse arguments */
Felipe Lemea34efb72016-03-11 09:33:32 -08001212 std::string args;
1213 format_args(argc, const_cast<const char **>(argv), &args);
1214 MYLOGD("Dumpstate command line: %s\n", args.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001215 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001216 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001217 switch (c) {
Felipe Leme71bbfc52015-11-23 14:14:51 -08001218 case 'd': do_add_date = 1; break;
1219 case 'z': do_zip_file = 1; break;
1220 case 'o': use_outfile = optarg; break;
1221 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001222 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001223 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001224 case 'q': do_vibrate = 0; break;
1225 case 'p': do_fb = 1; break;
1226 case 'P': do_update_progress = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001227 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001228 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001229 case 'V': version = optarg; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230 case '?': printf("\n");
1231 case 'h':
1232 usage();
1233 exit(1);
1234 }
1235 }
1236
Felipe Leme71bbfc52015-11-23 14:14:51 -08001237 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001238 usage();
1239 exit(1);
1240 }
1241
Felipe Leme2628e9e2016-04-12 16:36:51 -07001242 if (use_control_socket && !do_zip_file) {
1243 usage();
1244 exit(1);
1245 }
1246
Felipe Leme71bbfc52015-11-23 14:14:51 -08001247 if (do_update_progress && !do_broadcast) {
1248 usage();
1249 exit(1);
1250 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001251
Michal Karpinski4db754f2015-12-11 18:04:32 +00001252 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1253 usage();
1254 exit(1);
1255 }
1256
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001257 if (version != VERSION_DEFAULT) {
1258 usage();
1259 exit(1);
Felipe Leme809d74e2016-02-02 12:57:00 -08001260 }
1261
Felipe Lemecbce55d2016-02-08 09:53:18 -08001262 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001263
Felipe Lemee338bf62015-12-07 14:03:50 -08001264 do_early_screenshot = do_update_progress;
1265
Christopher Ferrised9354f2014-10-01 17:35:01 -07001266 // If we are going to use a socket, do it as early as possible
1267 // to avoid timeouts from bugreport.
1268 if (use_socket) {
1269 redirect_to_socket(stdout, "dumpstate");
1270 }
1271
Felipe Leme2628e9e2016-04-12 16:36:51 -07001272 if (use_control_socket) {
1273 MYLOGD("Opening control socket\n");
1274 control_socket_fd = open_socket("dumpstate");
Felipe Leme02b7e002016-07-22 12:03:20 -07001275 do_update_progress = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001276 }
1277
Felipe Lemecbce55d2016-02-08 09:53:18 -08001278 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001279 std::string tmp_path;
1280
Felipe Lemecbce55d2016-02-08 09:53:18 -08001281 /* full path of the file containing the dumpstate logs*/
1282 std::string log_path;
1283
Felipe Leme14e034a2016-03-30 18:51:03 -07001284 /* full path of the systrace file, when enabled */
1285 std::string systrace_path;
1286
Felipe Lemee338bf62015-12-07 14:03:50 -08001287 /* full path of the temporary file containing the screenshot (when requested) */
1288 std::string screenshot_path;
1289
Felipe Lemecbce55d2016-02-08 09:53:18 -08001290 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001291 std::string base_name;
1292
Felipe Leme71bbfc52015-11-23 14:14:51 -08001293 /* pointer to the actual path, be it zip or text */
1294 std::string path;
1295
Felipe Leme635ca312016-01-05 14:23:02 -08001296 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001297 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001298
Felipe Lemead5f6c42015-11-30 14:26:46 -08001299 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001300 bool is_redirecting = !use_socket && use_outfile;
1301
1302 if (is_redirecting) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001303 bugreport_dir = dirname(use_outfile);
1304 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001305 if (do_add_date) {
1306 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001307 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1308 suffix = date;
1309 } else {
1310 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001311 }
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001312 char build_id[PROPERTY_VALUE_MAX];
1313 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1314 base_name = base_name + "-" + build_id;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001315 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001316 // TODO: if dumpstate was an object, the paths could be internal variables and then
1317 // we could have a function to calculate the derived values, such as:
1318 // screenshot_path = GetPath(".png");
1319 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001320 }
Felipe Lemead5f6c42015-11-30 14:26:46 -08001321 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
Felipe Lemecbce55d2016-02-08 09:53:18 -08001322 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1323 + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001324
Felipe Lemecbce55d2016-02-08 09:53:18 -08001325 MYLOGD("Bugreport dir: %s\n"
1326 "Base name: %s\n"
1327 "Suffix: %s\n"
1328 "Log path: %s\n"
1329 "Temporary path: %s\n"
1330 "Screenshot path: %s\n",
1331 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1332 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001333
Felipe Leme1e9edc62015-12-21 16:02:13 -08001334 if (do_zip_file) {
Felipe Leme1e9edc62015-12-21 16:02:13 -08001335 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001336 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001337 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001338 zip_file.reset(fopen(path.c_str(), "wb"));
1339 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001340 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001341 do_zip_file = 0;
1342 } else {
1343 zip_writer.reset(new ZipWriter(zip_file.get()));
1344 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001345 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001346 }
1347
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001348 if (do_update_progress) {
1349 if (do_broadcast) {
1350 // clang-format off
1351 std::vector<std::string> am_args = {
1352 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1353 "--es", "android.intent.extra.NAME", suffix,
1354 "--ei", "android.intent.extra.ID", std::to_string(id),
1355 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1356 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1357 };
1358 // clang-format on
1359 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1360 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001361 if (use_control_socket) {
1362 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1363 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001364 }
1365 }
1366
Nick Kralevichf3599b32016-01-25 15:05:16 -08001367 /* read /proc/cmdline before dropping root */
1368 FILE *cmdline = fopen("/proc/cmdline", "re");
1369 if (cmdline) {
1370 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1371 fclose(cmdline);
1372 }
1373
Jeff Brown1dc94e32014-09-11 14:15:27 -07001374 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001375 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001376 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001377 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001378 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001379 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001380 }
John Michelau1f794c42012-09-17 11:20:19 -05001381 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001382
Felipe Leme3634a1e2015-12-09 10:11:47 -08001383 if (do_fb && do_early_screenshot) {
1384 if (screenshot_path.empty()) {
1385 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001386 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001387 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001388 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001389 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001390 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001391 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001392 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001393 screenshot_path.c_str(), strerror(errno));
1394 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001395 }
1396 }
1397
Felipe Leme1e9edc62015-12-21 16:02:13 -08001398 if (do_zip_file) {
1399 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001400 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001401 }
1402 }
1403
Felipe Leme71bbfc52015-11-23 14:14:51 -08001404 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001405 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001406 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1407 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1408 log_path.c_str(), strerror(errno));
1409 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001410 /* TODO: rather than generating a text file now and zipping it later,
1411 it would be more efficient to redirect stdout to the zip entry
1412 directly, but the libziparchive doesn't support that option yet. */
1413 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001414 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1415 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1416 tmp_path.c_str(), strerror(errno));
1417 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001418 }
Felipe Leme608385d2016-02-01 10:35:38 -08001419 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1420 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001421 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001422 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001423
Felipe Leme71a74ac2016-03-17 15:43:25 -07001424 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001425 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1426 // the raw trace.
1427 if (!dump_anrd_trace()) {
1428 dump_systrace();
1429 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001430
Wei Liu341938b2016-04-27 16:18:17 -07001431 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
Felipe Lemeefd7e272016-05-18 09:27:16 -07001432 dump_raft();
Wei Liu341938b2016-04-27 16:18:17 -07001433
Felipe Leme9c74aad2016-02-29 18:15:42 -08001434 // Invoking the following dumpsys calls before dump_traces() to try and
1435 // keep the system stats as close to its initial state as possible.
Thierry Strudel8b78b752016-03-22 10:25:44 -07001436 run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
Felipe Leme7cff4622016-06-08 09:51:29 -07001437 run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001438
1439 /* collect stack traces from Dalvik and native processes (needs root) */
1440 dump_traces_path = dump_traces();
1441
Felipe Lemec0808152016-06-17 17:37:13 -07001442 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001443 get_tombstone_fds(tombstone_data);
1444 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001445 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001446 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001447 if (!is_user_build()) {
1448 add_dir(PROFILE_DATA_DIR_CUR, true);
1449 add_dir(PROFILE_DATA_DIR_REF, true);
1450 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001451 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001452 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001453
Erik Kline53ca94a2016-09-28 17:26:26 +09001454 // Capture any IPSec policies in play. No keys are exposed here.
1455 run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
1456
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001457 // Run ss as root so we can see socket marks.
1458 run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1459
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001460 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001461 return -1;
1462 }
1463
1464 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001465
Felipe Leme55b42a62015-11-10 17:39:08 -08001466 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001467 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001468 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001469 }
1470
Felipe Leme6e01fa62015-11-11 19:35:14 -08001471 /* rename or zip the (now complete) .tmp file to its final location */
1472 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001473
1474 /* check if user changed the suffix using system properties */
1475 char key[PROPERTY_KEY_MAX];
1476 char value[PROPERTY_VALUE_MAX];
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001477 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001478 property_get(key, value, "");
1479 bool change_suffix= false;
1480 if (value[0]) {
1481 /* must whitelist which characters are allowed, otherwise it could cross directories */
1482 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1483 if (std::regex_match(value, valid_regex)) {
1484 change_suffix = true;
1485 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001486 MYLOGE("invalid suffix provided by user: %s\n", value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001487 }
1488 }
1489 if (change_suffix) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001490 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001491 suffix = value;
1492 if (!screenshot_path.empty()) {
1493 std::string new_screenshot_path =
1494 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1495 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001496 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001497 new_screenshot_path.c_str(), strerror(errno));
1498 } else {
1499 screenshot_path = new_screenshot_path;
1500 }
1501 }
1502 }
1503
Felipe Leme6e01fa62015-11-11 19:35:14 -08001504 bool do_text_file = true;
1505 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001506 std::string entry_name = base_name + "-" + suffix + ".txt";
1507 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1508 if (!finish_zip_file(entry_name, tmp_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001509 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001510 do_text_file = true;
1511 } else {
1512 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001513 // Since zip file is already created, it needs to be renamed.
1514 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1515 if (path != new_path) {
1516 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1517 if (rename(path.c_str(), new_path.c_str())) {
1518 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1519 new_path.c_str(), strerror(errno));
1520 } else {
1521 path = new_path;
1522 }
1523 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001524 }
1525 }
1526 if (do_text_file) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001527 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001528 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001529 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001530 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001531 path.clear();
1532 }
1533 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001534 if (use_control_socket) {
1535 if (do_text_file) {
1536 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1537 "for more details\n", log_path.c_str());
1538 } else {
1539 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1540 }
1541 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001542 }
1543
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001544 /* vibrate a few but shortly times to let user know it's finished */
1545 if (vibrator) {
1546 for (int i = 0; i < 3; i++) {
1547 vibrate(vibrator.get(), 75);
1548 usleep((75 + 50) * 1000);
1549 }
1550 }
1551
Jeff Brown1dc94e32014-09-11 14:15:27 -07001552 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001553 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001554 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001555 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001556 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001557 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001558 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001559 "--ei", "android.intent.extra.ID", std::to_string(id),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001560 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemeee2e4a02016-02-22 18:12:11 -08001561 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001562 "--es", "android.intent.extra.BUGREPORT", path,
1563 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001564 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001565 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001566 if (do_fb) {
1567 am_args.push_back("--es");
1568 am_args.push_back("android.intent.extra.SCREENSHOT");
1569 am_args.push_back(screenshot_path);
1570 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001571 if (is_remote_mode) {
1572 am_args.push_back("--es");
1573 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1574 am_args.push_back(SHA256_file_hash(path));
1575 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1576 } else {
1577 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1578 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001579 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001580 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001581 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001582 }
1583
Felipe Lemecbce55d2016-02-08 09:53:18 -08001584 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1585 MYLOGI("done\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001586
Felipe Leme107a05f2016-03-08 15:11:15 -08001587 if (is_redirecting) {
1588 fclose(stderr);
1589 }
1590
Felipe Leme02b7e002016-07-22 12:03:20 -07001591 if (use_control_socket && control_socket_fd != -1) {
1592 MYLOGD("Closing control socket\n");
1593 close(control_socket_fd);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001594 }
1595
Colin Crossf45fa6b2012-03-26 12:38:26 -07001596 return 0;
1597}