blob: e67b67f19ca2db083e56fa3d0db3d22d75f3fa34 [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 Gampefcc8db92016-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 Leme78f2c862015-12-21 09:55:22 -080071
Todd Poynor2a83daa2013-11-22 15:44:22 -080072#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070073#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080074
Wei Liu341938b2016-04-27 16:18:17 -070075#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080076#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070077#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070078#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010079#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
80#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070081#define TOMBSTONE_DIR "/data/tombstones"
82#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
83/* Can accomodate a tombstone number up to 9999. */
84#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
85#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090086#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070087#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070088
89typedef struct {
90 char name[TOMBSTONE_MAX_LEN];
91 int fd;
92} tombstone_data_t;
93
94static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
95
Felipe Leme71ca15e2016-05-19 16:18:17 -070096const std::string ZIP_ROOT_DIR = "FS";
97std::string bugreport_dir;
Felipe Lemee82a27d2016-01-05 13:35:44 -080098
Felipe Leme809d74e2016-02-02 12:57:00 -080099/*
100 * List of supported zip format versions.
101 *
102 * See bugreport-format.txt for more info.
103 */
Felipe Lemeca9c12e2016-05-19 16:30:15 -0700104static std::string VERSION_DEFAULT = "1.0";
Felipe Leme809d74e2016-02-02 12:57:00 -0800105
Calvin On249beee2016-06-03 15:17:07 -0700106bool is_user_build() {
Felipe Lemec4eee562016-04-21 15:42:55 -0700107 return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
108}
109
Felipe Lemee82a27d2016-01-05 13:35:44 -0800110/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
111 * otherwise gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700112static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800113 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700114 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
115 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800116 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
117 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700118 struct stat st;
119 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800120 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
121 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700122 } else {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800123 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700124 data[i].fd = -1;
125 }
126 }
127}
128
Felipe Leme635ca312016-01-05 14:23:02 -0800129// for_each_pid() callback to get mount info about a process.
130void do_mountinfo(int pid, const char *name) {
131 char path[PATH_MAX];
132
133 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
134 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700135 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800136 char linkname[PATH_MAX];
137 ssize_t r = readlink(path, linkname, PATH_MAX);
138 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800139 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800140 return;
141 }
142 linkname[r] = '\0';
143
144 if (mount_points.find(linkname) == mount_points.end()) {
145 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700146 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800147 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
148 mount_points.insert(linkname);
149 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800150 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800151 }
152 }
153}
154
155void add_mountinfo() {
156 if (!zip_writer) return;
157 const char *title = "MOUNT INFO";
158 mount_points.clear();
Felipe Leme608385d2016-02-01 10:35:38 -0800159 DurationReporter duration_reporter(title, NULL);
Felipe Leme635ca312016-01-05 14:23:02 -0800160 for_each_pid(do_mountinfo, NULL);
Felipe Leme1b0225a2016-02-09 16:35:14 -0800161 MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800162}
163
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700164static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
165{
166 DIR *d;
167 struct dirent *de;
168 char path[PATH_MAX];
169
170 d = opendir(driverpath);
171 if (d == NULL) {
172 return;
173 }
174
175 while ((de = readdir(d))) {
176 if (de->d_type != DT_LNK) {
177 continue;
178 }
179 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
180 dump_file(title, path);
181 }
182
183 closedir(d);
184}
185
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700186// return pid of a userspace process. If not found or error, return 0.
187static unsigned int pid_of_process(const char* ps_name) {
188 DIR *proc_dir;
189 struct dirent *ps;
190 unsigned int pid;
191 std::string cmdline;
192
193 if (!(proc_dir = opendir("/proc"))) {
194 MYLOGE("Can't open /proc\n");
195 return 0;
196 }
197
198 while ((ps = readdir(proc_dir))) {
199 if (!(pid = atoi(ps->d_name))) {
200 continue;
201 }
202 android::base::ReadFileToString("/proc/"
203 + std::string(ps->d_name) + "/cmdline", &cmdline);
204 if (cmdline.find(ps_name) == std::string::npos) {
205 continue;
206 } else {
207 closedir(proc_dir);
208 return pid;
209 }
210 }
211 closedir(proc_dir);
212 return 0;
213}
214
215// dump anrd's trace and add to the zip file.
216// 1. check if anrd is running on this device.
217// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
218// 3. wait until the trace generation completes and add to the zip file.
219static bool dump_anrd_trace() {
220 unsigned int pid;
221 char buf[50], path[PATH_MAX];
222 struct dirent *trace;
223 struct stat st;
224 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700225 int retry = 5;
226 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700227 long long cur_size = 0;
228 const char *trace_path = "/data/misc/anrd/";
229
230 if (!zip_writer) {
231 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
232 return false;
233 }
234
235 // find anrd's pid if it is running.
236 pid = pid_of_process("/system/xbin/anrd");
237
238 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700239 if (stat(trace_path, &st) == 0) {
240 old_mtime = st.st_mtime;
241 } else {
242 MYLOGE("Failed to find: %s\n", trace_path);
243 return false;
244 }
245
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700246 // send SIGUSR1 to the anrd to generate a trace.
247 sprintf(buf, "%u", pid);
248 if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) {
249 MYLOGE("anrd signal timed out. Please manually collect trace\n");
250 return false;
251 }
252
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700253 while (retry-- > 0 && old_mtime == st.st_mtime) {
254 sleep(1);
255 stat(trace_path, &st);
256 }
257
258 if (retry < 0 && old_mtime == st.st_mtime) {
259 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
260 return false;
261 }
262
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700263 // identify the trace file by its creation time.
264 if (!(trace_dir = opendir(trace_path))) {
265 MYLOGE("Can't open trace file under %s\n", trace_path);
266 }
267 while ((trace = readdir(trace_dir))) {
268 if (strcmp(trace->d_name, ".") == 0
269 || strcmp(trace->d_name, "..") == 0) {
270 continue;
271 }
272 sprintf(path, "%s%s", trace_path, trace->d_name);
273 if (stat(path, &st) == 0) {
274 if (st.st_ctime > max_ctime) {
275 max_ctime = st.st_ctime;
276 sprintf(buf, "%s", trace->d_name);
277 }
278 }
279 }
280 closedir(trace_dir);
281
282 // Wait until the dump completes by checking the size of the trace.
283 if (max_ctime > 0) {
284 sprintf(path, "%s%s", trace_path, buf);
285 while(true) {
286 sleep(1);
287 if (stat(path, &st) == 0) {
288 if (st.st_size == cur_size) {
289 break;
290 } else if (st.st_size > cur_size) {
291 cur_size = st.st_size;
292 } else {
293 return false;
294 }
295 } else {
296 MYLOGE("Cant stat() %s anymore\n", path);
297 return false;
298 }
299 }
300 // Add to the zip file.
301 if (!add_zip_entry("anrd_trace.txt", path)) {
302 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
303 } else {
304 if (remove(path)) {
305 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
306 }
307 return true;
308 }
309 } else {
310 MYLOGE("Can't stats any trace file under %s\n", trace_path);
311 }
312 }
313 return false;
314}
315
Felipe Lemeefd7e272016-05-18 09:27:16 -0700316static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700317 if (!zip_writer) {
318 MYLOGD("Not dumping systrace because zip_writer is not set\n");
319 return;
320 }
Felipe Lemeefd7e272016-05-18 09:27:16 -0700321 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700322 if (systrace_path.empty()) {
323 MYLOGE("Not dumping systrace because path is empty\n");
324 return;
325 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700326 const char* path = "/sys/kernel/debug/tracing/tracing_on";
327 long int is_tracing;
328 if (read_file_as_long(path, &is_tracing)) {
329 return; // error already logged
330 }
331 if (is_tracing <= 0) {
332 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
333 return;
334 }
335
Felipe Leme14e034a2016-03-30 18:51:03 -0700336 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
337 systrace_path.c_str());
338 if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
339 systrace_path.c_str(), NULL)) {
340 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
341 // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
342 // we should call strace to stop itself, but there is no such option yet (just a
343 // --async_stop, which stops and dump
344 // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
345 // MYLOGE("could not stop systrace ");
346 // }
347 }
348 if (!add_zip_entry("systrace.txt", systrace_path)) {
349 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700350 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700351 if (remove(systrace_path.c_str())) {
352 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
353 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700354 }
355}
356
Felipe Lemeefd7e272016-05-18 09:27:16 -0700357static void dump_raft() {
Wei Liu341938b2016-04-27 16:18:17 -0700358 if (is_user_build()) {
359 return;
360 }
361
Felipe Lemeefd7e272016-05-18 09:27:16 -0700362 std::string raft_log_path = bugreport_dir + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700363 if (raft_log_path.empty()) {
364 MYLOGD("raft_log_path is empty\n");
365 return;
366 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700367
368 struct stat s;
369 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
370 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
371 return;
372 }
373
Wei Liu341938b2016-04-27 16:18:17 -0700374 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700375 // Write compressed and encoded raft logs to stdout if not zip_writer.
376 run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL);
Wei Liu341938b2016-04-27 16:18:17 -0700377 return;
378 }
379
380 run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR,
381 "-o", raft_log_path.c_str(), NULL);
382 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
383 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
384 } else {
385 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700386 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700387 }
388 }
389}
390
Mark Salyzyn326842f2015-04-30 09:49:41 -0700391static bool skip_not_stat(const char *path) {
392 static const char stat[] = "/stat";
393 size_t len = strlen(path);
394 if (path[len - 1] == '/') { /* Directory? */
395 return false;
396 }
397 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
398}
399
Felipe Lemee82a27d2016-01-05 13:35:44 -0800400static bool skip_none(const char *path) {
401 return false;
402}
403
Mark Salyzyn326842f2015-04-30 09:49:41 -0700404static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700405unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700406
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800407//
408// stat offsets
409// Name units description
410// ---- ----- -----------
411// read I/Os requests number of read I/Os processed
412#define __STAT_READ_IOS 0
413// read merges requests number of read I/Os merged with in-queue I/O
414#define __STAT_READ_MERGES 1
415// read sectors sectors number of sectors read
416#define __STAT_READ_SECTORS 2
417// read ticks milliseconds total wait time for read requests
418#define __STAT_READ_TICKS 3
419// write I/Os requests number of write I/Os processed
420#define __STAT_WRITE_IOS 4
421// write merges requests number of write I/Os merged with in-queue I/O
422#define __STAT_WRITE_MERGES 5
423// write sectors sectors number of sectors written
424#define __STAT_WRITE_SECTORS 6
425// write ticks milliseconds total wait time for write requests
426#define __STAT_WRITE_TICKS 7
427// in_flight requests number of I/Os currently in flight
428#define __STAT_IN_FLIGHT 8
429// io_ticks milliseconds total time this block device has been active
430#define __STAT_IO_TICKS 9
431// time_in_queue milliseconds total wait time for all requests
432#define __STAT_IN_QUEUE 10
433#define __STAT_NUMBER_FIELD 11
434//
435// read I/Os, write I/Os
436// =====================
437//
438// These values increment when an I/O request completes.
439//
440// read merges, write merges
441// =========================
442//
443// These values increment when an I/O request is merged with an
444// already-queued I/O request.
445//
446// read sectors, write sectors
447// ===========================
448//
449// These values count the number of sectors read from or written to this
450// block device. The "sectors" in question are the standard UNIX 512-byte
451// sectors, not any device- or filesystem-specific block size. The
452// counters are incremented when the I/O completes.
453#define SECTOR_SIZE 512
454//
455// read ticks, write ticks
456// =======================
457//
458// These values count the number of milliseconds that I/O requests have
459// waited on this block device. If there are multiple I/O requests waiting,
460// these values will increase at a rate greater than 1000/second; for
461// example, if 60 read requests wait for an average of 30 ms, the read_ticks
462// field will increase by 60*30 = 1800.
463//
464// in_flight
465// =========
466//
467// This value counts the number of I/O requests that have been issued to
468// the device driver but have not yet completed. It does not include I/O
469// requests that are in the queue but not yet issued to the device driver.
470//
471// io_ticks
472// ========
473//
474// This value counts the number of milliseconds during which the device has
475// had I/O requests queued.
476//
477// time_in_queue
478// =============
479//
480// This value counts the number of milliseconds that I/O requests have waited
481// on this block device. If there are multiple I/O requests waiting, this
482// value will increase as the product of the number of milliseconds times the
483// number of requests waiting (see "read ticks" above for an example).
484#define S_TO_MS 1000
485//
486
Mark Salyzyn326842f2015-04-30 09:49:41 -0700487static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800488 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700489 bool z;
490 char *cp, *buffer = NULL;
491 size_t i = 0;
492 FILE *fp = fdopen(fd, "rb");
493 getline(&buffer, &i, fp);
494 fclose(fp);
495 if (!buffer) {
496 return -errno;
497 }
498 i = strlen(buffer);
499 while ((i > 0) && (buffer[i - 1] == '\n')) {
500 buffer[--i] = '\0';
501 }
502 if (!*buffer) {
503 free(buffer);
504 return 0;
505 }
506 z = true;
507 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800508 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700509 if (fields[i] != 0) {
510 z = false;
511 }
512 }
513 if (z) { /* never accessed */
514 free(buffer);
515 return 0;
516 }
517
518 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
519 path += sizeof(mmcblk0) - 1;
520 }
521
522 printf("%s: %s\n", path, buffer);
523 free(buffer);
524
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800525 if (fields[__STAT_IO_TICKS]) {
526 unsigned long read_perf = 0;
527 unsigned long read_ios = 0;
528 if (fields[__STAT_READ_TICKS]) {
529 unsigned long long divisor = fields[__STAT_READ_TICKS]
530 * fields[__STAT_IO_TICKS];
531 read_perf = ((unsigned long long)SECTOR_SIZE
532 * fields[__STAT_READ_SECTORS]
533 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
534 / divisor;
535 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
536 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
537 / divisor;
538 }
539
540 unsigned long write_perf = 0;
541 unsigned long write_ios = 0;
542 if (fields[__STAT_WRITE_TICKS]) {
543 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
544 * fields[__STAT_IO_TICKS];
545 write_perf = ((unsigned long long)SECTOR_SIZE
546 * fields[__STAT_WRITE_SECTORS]
547 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
548 / divisor;
549 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
550 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
551 / divisor;
552 }
553
554 unsigned queue = (fields[__STAT_IN_QUEUE]
555 + (fields[__STAT_IO_TICKS] >> 1))
556 / fields[__STAT_IO_TICKS];
557
558 if (!write_perf && !write_ios) {
559 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
560 path, read_perf, read_ios, queue);
561 } else {
562 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
563 path, read_perf, read_ios, write_perf, write_ios, queue);
564 }
565
566 /* bugreport timeout factor adjustment */
567 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
568 worst_write_perf = write_perf;
569 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700570 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700571 return 0;
572}
573
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700574/* Copied policy from system/core/logd/LogBuffer.cpp */
575
576#define LOG_BUFFER_SIZE (256 * 1024)
577#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
578#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
579
580static bool valid_size(unsigned long value) {
581 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
582 return false;
583 }
584
585 long pages = sysconf(_SC_PHYS_PAGES);
586 if (pages < 1) {
587 return true;
588 }
589
590 long pagesize = sysconf(_SC_PAGESIZE);
591 if (pagesize <= 1) {
592 pagesize = PAGE_SIZE;
593 }
594
595 // maximum memory impact a somewhat arbitrary ~3%
596 pages = (pages + 31) / 32;
597 unsigned long maximum = pages * pagesize;
598
599 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
600 return true;
601 }
602
603 return value <= maximum;
604}
605
606static unsigned long property_get_size(const char *key) {
607 unsigned long value;
608 char *cp, property[PROPERTY_VALUE_MAX];
609
610 property_get(key, property, "");
611 value = strtoul(property, &cp, 10);
612
613 switch(*cp) {
614 case 'm':
615 case 'M':
616 value *= 1024;
617 /* FALLTHRU */
618 case 'k':
619 case 'K':
620 value *= 1024;
621 /* FALLTHRU */
622 case '\0':
623 break;
624
625 default:
626 value = 0;
627 }
628
629 if (!valid_size(value)) {
630 value = 0;
631 }
632
633 return value;
634}
635
636/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800637static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700638 static const char global_tuneable[] = "persist.logd.size"; // Settings App
639 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
640 char key[PROP_NAME_MAX];
641 unsigned long property_size, default_size;
642
643 default_size = property_get_size(global_tuneable);
644 if (!default_size) {
645 default_size = property_get_size(global_default);
646 }
647
648 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
649 property_size = property_get_size(key);
650
651 if (!property_size) {
652 snprintf(key, sizeof(key), "%s.%s", global_default, name);
653 property_size = property_get_size(key);
654 }
655
656 if (!property_size) {
657 property_size = default_size;
658 }
659
660 if (!property_size) {
661 property_size = LOG_BUFFER_SIZE;
662 }
663
664 /* Engineering margin is ten-fold our guess */
665 return 10 * (property_size + worst_write_perf) / worst_write_perf;
666}
667
668/* End copy from system/core/logd/LogBuffer.cpp */
669
Colin Crossf45fa6b2012-03-26 12:38:26 -0700670/* dumps the current system state to stdout */
Felipe Leme809d74e2016-02-02 12:57:00 -0800671static void print_header(std::string version) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700672 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
673 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
674 char network[PROPERTY_VALUE_MAX], date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700675
676 property_get("ro.build.display.id", build, "(unknown)");
677 property_get("ro.build.fingerprint", fingerprint, "(unknown)");
678 property_get("ro.build.type", build_type, "(unknown)");
Junda Liu58ad9292016-06-12 11:51:54 -0700679 property_get("gsm.version.baseband", radio, "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700680 property_get("ro.bootloader", bootloader, "(unknown)");
681 property_get("gsm.operator.alpha", network, "(unknown)");
682 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
683
684 printf("========================================================\n");
685 printf("== dumpstate: %s\n", date);
686 printf("========================================================\n");
687
688 printf("\n");
689 printf("Build: %s\n", build);
690 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
691 printf("Bootloader: %s\n", bootloader);
692 printf("Radio: %s\n", radio);
693 printf("Network: %s\n", network);
694
695 printf("Kernel: ");
696 dump_file(NULL, "/proc/version");
697 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800698 printf("Bugreport format version: %s\n", version.c_str());
Felipe Leme8fecfdd2016-02-09 10:40:07 -0800699 printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700700 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800701}
702
Felipe Leme24b66ee2016-06-16 10:55:26 -0700703// List of file extensions that can cause a zip file attachment to be rejected by some email
704// service providers.
705static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
706 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
707 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
708 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
709};
710
Felipe Leme71ca15e2016-05-19 16:18:17 -0700711bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800712 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800713 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
714 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800715 return false;
716 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700717 std::string valid_name = entry_name;
718
719 // Rename extension if necessary.
720 size_t idx = entry_name.rfind(".");
721 if (idx != std::string::npos) {
722 std::string extension = entry_name.substr(idx);
723 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
724 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
725 valid_name = entry_name + ".renamed";
726 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
727 }
728 }
729
Felipe Leme6fe9db62016-02-12 09:04:16 -0800730 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
731 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700732 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800733 ZipWriter::kCompress, get_mtime(fd, now));
734 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700735 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800736 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800737 return false;
738 }
739
Felipe Leme770410d2016-01-26 17:07:14 -0800740 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800741 while (1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800742 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
743 if (bytes_read == 0) {
744 break;
745 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800746 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800747 return false;
748 }
749 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
750 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800751 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800752 return false;
753 }
754 }
755
756 err = zip_writer->FinishEntry();
757 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800758 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800759 return false;
760 }
761
762 return true;
763}
764
Felipe Leme71ca15e2016-05-19 16:18:17 -0700765bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700766 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
767 | O_CLOEXEC)));
Andreas Gampefcc8db92016-07-18 18:01:27 -0700768 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800769 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800770 return false;
771 }
772
773 return add_zip_entry_from_fd(entry_name, fd.get());
774}
775
776/* adds a file to the existing zipped bugreport */
777static int _add_file_from_fd(const char *title, const char *path, int fd) {
778 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
779}
780
Felipe Leme24b66ee2016-06-16 10:55:26 -0700781// TODO: move to util.cpp
Felipe Lemee82a27d2016-01-05 13:35:44 -0800782void add_dir(const char *dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800783 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800784 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
Felipe Leme111b9d02016-02-03 09:28:24 -0800785 return;
786 }
Felipe Leme88c79332016-02-22 11:06:49 -0800787 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
Felipe Leme608385d2016-02-01 10:35:38 -0800788 DurationReporter duration_reporter(dir, NULL);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800789 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
790}
791
Felipe Leme809d74e2016-02-02 12:57:00 -0800792/* adds a text entry entry to the existing zip file. */
793static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800794 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800795 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 -0800796 return false;
797 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800798 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800799 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
800 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800801 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800802 ZipWriter::ErrorCodeString(err));
803 return false;
804 }
805
806 err = zip_writer->WriteBytes(content.c_str(), content.length());
807 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800808 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800809 ZipWriter::ErrorCodeString(err));
810 return false;
811 }
812
813 err = zip_writer->FinishEntry();
814 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800815 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800816 return false;
817 }
818
819 return true;
820}
821
Felipe Lemec0808152016-06-17 17:37:13 -0700822static void dump_iptables() {
823 run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL);
824 run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL);
Erik Kline53ca94a2016-09-28 17:26:26 +0900825 run_command("IPTABLES NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -0700826 /* no ip6 nat */
Erik Kline53ca94a2016-09-28 17:26:26 +0900827 run_command("IPTABLES MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL);
828 run_command("IP6TABLES MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL);
829 run_command("IPTABLES RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL);
830 run_command("IP6TABLES RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -0700831}
832
Srinath Sridharanfdf52d32016-02-01 15:50:22 -0800833static void dumpstate(const std::string& screenshot_path, const std::string& version) {
Felipe Leme770410d2016-01-26 17:07:14 -0800834 DurationReporter duration_reporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800835 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700836
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700837 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700838 run_command("UPTIME", 10, "uptime", NULL);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700839 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800840 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700841 dump_file("MEMORY INFO", "/proc/meminfo");
Elliott Hughes52860032016-06-14 13:56:00 -0700842 run_command("CPU INFO", 10, "top", "-b", "-n", "1", "-H", "-s", "6",
Elliott Hughes646e92f2016-06-13 17:35:07 -0700843 "-o", "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name", NULL);
Nick Kralevich2b1f88b2015-10-07 16:38:42 -0700844 run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700845 dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
846 dump_file("VMALLOC INFO", "/proc/vmallocinfo");
847 dump_file("SLAB INFO", "/proc/slabinfo");
848 dump_file("ZONEINFO", "/proc/zoneinfo");
849 dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
850 dump_file("BUDDYINFO", "/proc/buddyinfo");
Colin Cross2281af92012-10-28 22:41:06 -0700851 dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700852
Todd Poynor29e27a82012-05-22 17:54:59 -0700853 dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700854 dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
Mathias Agopian85aea742012-08-08 15:32:02 -0700855 dump_file("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700856
Elliott Hughes52860032016-06-14 13:56:00 -0700857 run_command("PROCESSES AND THREADS", 10, "ps", "-A", "-T", "-Z",
Elliott Hughes32caf1d2016-05-04 14:03:54 -0700858 "-O", "pri,nice,rtprio,sched,pcy", NULL);
Nick Kralevichb82c9252015-11-27 17:56:13 -0800859 run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700860
Michal Karpinski4db754f2015-12-11 18:04:32 +0000861 run_command("PRINTENV", 10, "printenv", NULL);
Lorenzo Colittif7f26512016-03-11 10:58:55 +0900862 run_command("NETSTAT", 10, "netstat", "-n", NULL);
Michal Karpinski4db754f2015-12-11 18:04:32 +0000863 run_command("LSMOD", 10, "lsmod", NULL);
864
Colin Crossf45fa6b2012-03-26 12:38:26 -0700865 do_dmesg();
866
867 run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700868 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
869 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800870 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700871
Ajay Panicker2f531772016-09-14 12:26:46 -0700872 /* Dump Bluetooth HCI logs */
873 add_dir("/data/misc/bluetooth/logs", true);
874
Felipe Leme6e01fa62015-11-11 19:35:14 -0800875 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800876 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800877 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800878 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700879 }
880
Colin Crossf45fa6b2012-03-26 12:38:26 -0700881 // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700882 // calculate timeout
883 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
884 if (timeout < 20000) {
885 timeout = 20000;
886 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700887 run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
888 "-v", "printable",
889 "-d",
890 "*:v", NULL);
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800891 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700892 if (timeout < 20000) {
893 timeout = 20000;
894 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700895 run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
896 "-v", "threadtime",
897 "-v", "printable",
898 "-d",
899 "*:v", NULL);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700900 timeout = logcat_timeout("radio");
901 if (timeout < 20000) {
902 timeout = 20000;
903 }
Mark Salyzyn78316382015-10-09 14:02:07 -0700904 run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
905 "-v", "threadtime",
906 "-v", "printable",
907 "-d",
908 "*:v", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700909
Mark Salyzynecc07632015-07-30 14:57:09 -0700910 run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
911
Colin Crossf45fa6b2012-03-26 12:38:26 -0700912 /* show the traces we collected in main(), if that was done */
913 if (dump_traces_path != NULL) {
914 dump_file("VM TRACES JUST NOW", dump_traces_path);
915 }
916
917 /* only show ANR traces if they're less than 15 minutes old */
918 struct stat st;
919 char anr_traces_path[PATH_MAX];
920 property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
921 if (!anr_traces_path[0]) {
922 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700923 } else {
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800924 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
925 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700926 if (fd < 0) {
927 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
928 } else {
929 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
930 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700931 }
932
933 /* slow traces for slow operations */
934 if (anr_traces_path[0] != 0) {
935 int tail = strlen(anr_traces_path)-1;
936 while (tail > 0 && anr_traces_path[tail] != '/') {
937 tail--;
938 }
939 int i = 0;
940 while (1) {
941 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
942 if (stat(anr_traces_path, &st)) {
943 // No traces file at this index, done with the files.
944 break;
945 }
946 dump_file("VM TRACES WHEN SLOW", anr_traces_path);
947 i++;
948 }
949 }
950
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700951 int dumped = 0;
952 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
953 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800954 const char *name = tombstone_data[i].name;
955 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700956 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800957 if (zip_writer) {
958 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800959 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800960 }
961 } else {
962 dump_file_from_fd("TOMBSTONE", name, fd);
963 }
964 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700965 tombstone_data[i].fd = -1;
966 }
967 }
968 if (!dumped) {
969 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
970 }
971
Colin Crossf45fa6b2012-03-26 12:38:26 -0700972 dump_file("NETWORK DEV INFO", "/proc/net/dev");
973 dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
JP Abgrall012c2ea2012-05-16 20:49:29 -0700974 dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700975 dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
976 dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
977
Todd Poynor2a83daa2013-11-22 15:44:22 -0800978 if (!stat(PSTORE_LAST_KMSG, &st)) {
979 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
980 dump_file("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -0700981 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
982 dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -0800983 } else {
984 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
985 dump_file("LAST KMSG", "/proc/last_kmsg");
986 }
987
Mark Salyzyn2262c162014-12-16 09:09:26 -0800988 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Mark Salyzyn78316382015-10-09 14:02:07 -0700989 run_command("LAST LOGCAT", 10, "logcat", "-L",
990 "-b", "all",
991 "-v", "threadtime",
992 "-v", "printable",
993 "-d",
994 "*:v", NULL);
Mark Salyzyn2262c162014-12-16 09:09:26 -0800995
Colin Crossf45fa6b2012-03-26 12:38:26 -0700996 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -0800997
998 run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
Lorenzo Colittid4c3d382014-07-30 14:38:20 +0900999
1000 run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
1001 run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
1002
Colin Crossf45fa6b2012-03-26 12:38:26 -07001003 run_command("IP RULES", 10, "ip", "rule", "show", NULL);
1004 run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001005
1006 dump_route_tables();
1007
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001008 run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
1009 run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
Erik Klinef7f2b0f2016-05-27 11:29:19 +09001010 run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL);
Felipe Lemec0808152016-06-17 17:37:13 -07001011 run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001012
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001013#ifdef FWDUMP_bcmdhd
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001014 run_command("ND OFFLOAD TABLE", 5,
Erik Kline08165202016-05-30 11:55:44 +09001015 SU_PATH, "root", WLUTIL, "nd_hostip", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001016
1017 run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
Erik Kline08165202016-05-30 11:55:44 +09001018 SU_PATH, "root", WLUTIL, "counters", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001019
1020 run_command("ND OFFLOAD STATUS (1)", 5,
Erik Kline08165202016-05-30 11:55:44 +09001021 SU_PATH, "root", WLUTIL, "nd_status", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001022
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001023#endif
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001024 dump_file("INTERRUPTS (1)", "/proc/interrupts");
1025
Felipe Leme7cff4622016-06-08 09:51:29 -07001026 run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001027
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001028#ifdef FWDUMP_bcmdhd
Colin Crossf45fa6b2012-03-26 12:38:26 -07001029 run_command("DUMP WIFI STATUS", 20,
1030 SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001031
1032 run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
Erik Kline08165202016-05-30 11:55:44 +09001033 SU_PATH, "root", WLUTIL, "counters", NULL);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001034
1035 run_command("ND OFFLOAD STATUS (2)", 5,
Erik Kline08165202016-05-30 11:55:44 +09001036 SU_PATH, "root", WLUTIL, "nd_status", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001037#endif
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001038 dump_file("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001039
1040 print_properties();
1041
1042 run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
1043 run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
1044
Ken Sumrall8f75fa72013-02-08 17:35:58 -08001045 run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001046
Colin Crossf45fa6b2012-03-26 12:38:26 -07001047 run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
1048
1049 printf("------ BACKLIGHTS ------\n");
1050 printf("LCD brightness=");
1051 dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
1052 printf("Button brightness=");
1053 dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
1054 printf("Keyboard brightness=");
1055 dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
1056 printf("ALS mode=");
1057 dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
1058 printf("LCD driver registers:\n");
1059 dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
1060 printf("\n");
1061
1062 /* Binder state is expensive to look at as it uses a lot of memory. */
1063 dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1064 dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1065 dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1066 dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
1067 dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
1068
Colin Crossf45fa6b2012-03-26 12:38:26 -07001069 printf("========================================================\n");
1070 printf("== Board\n");
1071 printf("========================================================\n");
1072
1073 dumpstate_board();
1074 printf("\n");
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 Lemec4eee562016-04-21 15:42:55 -07001080 if (is_user_build()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001081 // su does not exist on user builds, so try running without it.
1082 // This way any implementations of vril-dump that do not require
1083 // root can run on user builds.
1084 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1085 "vril-dump", NULL);
1086 } else {
1087 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
1088 SU_PATH, "root", "vril-dump", NULL);
1089 }
1090 }
1091
1092 printf("========================================================\n");
1093 printf("== Android Framework Services\n");
1094 printf("========================================================\n");
1095
Wei Liu34222562016-05-19 13:59:01 -07001096 run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001097
1098 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001099 printf("== Checkins\n");
1100 printf("========================================================\n");
1101
Felipe Leme7cff4622016-06-08 09:51:29 -07001102 run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL);
1103 run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL);
1104 run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL);
1105 run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL);
1106 run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL);
1107 run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL);
Dianne Hackborn02bea972013-06-26 18:59:09 -07001108
1109 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001110 printf("== Running Application Activities\n");
1111 printf("========================================================\n");
1112
Felipe Leme3f83dbe2016-06-10 16:56:33 -07001113 run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001114
1115 printf("========================================================\n");
1116 printf("== Running Application Services\n");
1117 printf("========================================================\n");
1118
Felipe Leme3f83dbe2016-06-10 16:56:33 -07001119 run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001120
1121 printf("========================================================\n");
1122 printf("== Running Application Providers\n");
1123 printf("========================================================\n");
1124
Junda Liucfc33d42016-06-14 00:09:10 -07001125 run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001126
1127
1128 printf("========================================================\n");
Felipe Leme608385d2016-02-01 10:35:38 -08001129 printf("== Final progress (pid %d): %d/%d (originally %d)\n",
1130 getpid(), progress, weight_total, WEIGHT_TOTAL);
1131 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001132 printf("== dumpstate: done\n");
1133 printf("========================================================\n");
1134}
1135
1136static void usage() {
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001137 fprintf(stderr,
Felipe Leme2628e9e2016-04-12 16:36:51 -07001138 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1139 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1140 " -h: display this help message\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001141 " -b: play sound file instead of vibrate, at beginning of job\n"
1142 " -e: play sound file instead of vibrate, at end of job\n"
1143 " -o: write to file (instead of stdout)\n"
1144 " -d: append date to filename (requires -o)\n"
1145 " -p: capture screenshot to filename.png (requires -o)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001146 " -z: generate zipped file (requires -o)\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001147 " -s: write output to control socket (for init)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001148 " -S: write file location to control socket (for init; requires -o and -z)"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001149 " -q: disable vibrate\n"
1150 " -B: send broadcast when finished (requires -o)\n"
1151 " -P: send broadcast when started and update system properties on "
1152 "progress (requires -o and -B)\n"
1153 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1154 "shouldn't be used with -P)\n"
1155 " -V: sets the bugreport format version (valid values: %s)\n",
1156 VERSION_DEFAULT.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001157}
1158
Wei Liuf87959e2016-08-26 14:51:42 -07001159static void wake_lock_releaser() {
1160 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1161 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1162 } else {
1163 MYLOGD("Wake lock released.\n");
1164 }
1165}
1166
1167static void sig_handler(int signo) {
1168 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001169 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001170}
1171
Wei Liuf87959e2016-08-26 14:51:42 -07001172static void register_sig_handler() {
1173 struct sigaction sa;
1174 sigemptyset(&sa.sa_mask);
1175 sa.sa_flags = 0;
1176 sa.sa_handler = sig_handler;
1177 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1178 sigaction(SIGSEGV, &sa, NULL); // segment fault
1179 sigaction(SIGINT, &sa, NULL); // ctrl-c
1180 sigaction(SIGTERM, &sa, NULL); // killed
1181 sigaction(SIGQUIT, &sa, NULL); // quit
1182}
1183
Felipe Leme1e9edc62015-12-21 16:02:13 -08001184/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1185 temporary file.
1186 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001187static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Leme1e9edc62015-12-21 16:02:13 -08001188 time_t now) {
Felipe Lemee82a27d2016-01-05 13:35:44 -08001189 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001190 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001191 return false;
1192 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001193 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001194 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001195 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001196 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001197
Felipe Lemee82a27d2016-01-05 13:35:44 -08001198 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001199 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001200 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001201 return false;
1202 }
1203
Felipe Lemec4eee562016-04-21 15:42:55 -07001204 if (is_user_build()) {
1205 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1206 if (remove(bugreport_path.c_str())) {
1207 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1208 }
1209 } else {
1210 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1211 }
1212
Felipe Leme1e9edc62015-12-21 16:02:13 -08001213 return true;
1214}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001215
Michal Karpinski4db754f2015-12-11 18:04:32 +00001216static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001217 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1218 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampefcc8db92016-07-18 18:01:27 -07001219 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001220 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001221 return NULL;
1222 }
1223
1224 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001225 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001226
1227 std::vector<uint8_t> buffer(65536);
1228 while (1) {
1229 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1230 if (bytes_read == 0) {
1231 break;
1232 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001233 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001234 return NULL;
1235 }
1236
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001237 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001238 }
1239
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001240 uint8_t hash[SHA256_DIGEST_LENGTH];
1241 SHA256_Final(hash, &ctx);
1242
1243 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1244 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001245 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001246 }
1247 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1248 return std::string(hash_buffer);
1249}
1250
Colin Crossf45fa6b2012-03-26 12:38:26 -07001251int main(int argc, char *argv[]) {
1252 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001253 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001254 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001255 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001256 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001257 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001258 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001259 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001260 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001261 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001262 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001263
Felipe Lemee82a27d2016-01-05 13:35:44 -08001264 now = time(NULL);
1265
Felipe Lemecbce55d2016-02-08 09:53:18 -08001266 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001267
Wei Liuf87959e2016-08-26 14:51:42 -07001268 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1269 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1270 } else {
1271 MYLOGD("Wake lock acquired.\n");
1272 atexit(wake_lock_releaser);
1273 register_sig_handler();
1274 }
1275
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001276 /* gets the sequential id */
1277 char last_id[PROPERTY_VALUE_MAX];
1278 property_get("dumpstate.last_id", last_id, "0");
1279 id = strtoul(last_id, NULL, 10) + 1;
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001280 snprintf(last_id, sizeof(last_id), "%lu", id);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001281 property_set("dumpstate.last_id", last_id);
1282 MYLOGI("dumpstate id: %lu\n", id);
1283
Colin Crossf45fa6b2012-03-26 12:38:26 -07001284 /* set as high priority, and protect from OOM killer */
1285 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001286
1287 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001288 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001289 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001290 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001291 } else {
1292 /* fallback to kernels <= 2.6.35 */
1293 oom_adj = fopen("/proc/self/oom_adj", "we");
1294 if (oom_adj) {
1295 fputs("-17", oom_adj);
1296 fclose(oom_adj);
1297 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001298 }
1299
Jeff Brown1dc94e32014-09-11 14:15:27 -07001300 /* parse arguments */
Felipe Lemea34efb72016-03-11 09:33:32 -08001301 std::string args;
1302 format_args(argc, const_cast<const char **>(argv), &args);
1303 MYLOGD("Dumpstate command line: %s\n", args.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001304 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001305 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306 switch (c) {
Felipe Leme71bbfc52015-11-23 14:14:51 -08001307 case 'd': do_add_date = 1; break;
1308 case 'z': do_zip_file = 1; break;
1309 case 'o': use_outfile = optarg; break;
1310 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001311 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001312 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001313 case 'q': do_vibrate = 0; break;
1314 case 'p': do_fb = 1; break;
1315 case 'P': do_update_progress = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001316 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001317 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001318 case 'V': version = optarg; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001319 case '?': printf("\n");
1320 case 'h':
1321 usage();
1322 exit(1);
1323 }
1324 }
1325
Felipe Leme71bbfc52015-11-23 14:14:51 -08001326 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001327 usage();
1328 exit(1);
1329 }
1330
Felipe Leme2628e9e2016-04-12 16:36:51 -07001331 if (use_control_socket && !do_zip_file) {
1332 usage();
1333 exit(1);
1334 }
1335
Felipe Leme71bbfc52015-11-23 14:14:51 -08001336 if (do_update_progress && !do_broadcast) {
1337 usage();
1338 exit(1);
1339 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001340
Michal Karpinski4db754f2015-12-11 18:04:32 +00001341 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
1342 usage();
1343 exit(1);
1344 }
1345
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001346 if (version != VERSION_DEFAULT) {
1347 usage();
1348 exit(1);
Felipe Leme809d74e2016-02-02 12:57:00 -08001349 }
1350
Felipe Lemecbce55d2016-02-08 09:53:18 -08001351 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001352
Felipe Lemee338bf62015-12-07 14:03:50 -08001353 do_early_screenshot = do_update_progress;
1354
Christopher Ferrised9354f2014-10-01 17:35:01 -07001355 // If we are going to use a socket, do it as early as possible
1356 // to avoid timeouts from bugreport.
1357 if (use_socket) {
1358 redirect_to_socket(stdout, "dumpstate");
1359 }
1360
Felipe Leme2628e9e2016-04-12 16:36:51 -07001361 if (use_control_socket) {
1362 MYLOGD("Opening control socket\n");
1363 control_socket_fd = open_socket("dumpstate");
Felipe Leme02b7e002016-07-22 12:03:20 -07001364 do_update_progress = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001365 }
1366
Felipe Lemecbce55d2016-02-08 09:53:18 -08001367 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001368 std::string tmp_path;
1369
Felipe Lemecbce55d2016-02-08 09:53:18 -08001370 /* full path of the file containing the dumpstate logs*/
1371 std::string log_path;
1372
Felipe Leme14e034a2016-03-30 18:51:03 -07001373 /* full path of the systrace file, when enabled */
1374 std::string systrace_path;
1375
Felipe Lemee338bf62015-12-07 14:03:50 -08001376 /* full path of the temporary file containing the screenshot (when requested) */
1377 std::string screenshot_path;
1378
Felipe Lemecbce55d2016-02-08 09:53:18 -08001379 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001380 std::string base_name;
1381
Felipe Leme71bbfc52015-11-23 14:14:51 -08001382 /* pointer to the actual path, be it zip or text */
1383 std::string path;
1384
Felipe Leme635ca312016-01-05 14:23:02 -08001385 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001386 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001387
Felipe Lemead5f6c42015-11-30 14:26:46 -08001388 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001389 bool is_redirecting = !use_socket && use_outfile;
1390
1391 if (is_redirecting) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001392 bugreport_dir = dirname(use_outfile);
1393 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001394 if (do_add_date) {
1395 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001396 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1397 suffix = date;
1398 } else {
1399 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001400 }
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001401 char build_id[PROPERTY_VALUE_MAX];
1402 property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
1403 base_name = base_name + "-" + build_id;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001404 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001405 // TODO: if dumpstate was an object, the paths could be internal variables and then
1406 // we could have a function to calculate the derived values, such as:
1407 // screenshot_path = GetPath(".png");
1408 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001409 }
Felipe Lemead5f6c42015-11-30 14:26:46 -08001410 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
Felipe Lemecbce55d2016-02-08 09:53:18 -08001411 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
1412 + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001413
Felipe Lemecbce55d2016-02-08 09:53:18 -08001414 MYLOGD("Bugreport dir: %s\n"
1415 "Base name: %s\n"
1416 "Suffix: %s\n"
1417 "Log path: %s\n"
1418 "Temporary path: %s\n"
1419 "Screenshot path: %s\n",
1420 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
1421 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001422
Felipe Leme1e9edc62015-12-21 16:02:13 -08001423 if (do_zip_file) {
Felipe Leme1e9edc62015-12-21 16:02:13 -08001424 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001425 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001426 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001427 zip_file.reset(fopen(path.c_str(), "wb"));
1428 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001429 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001430 do_zip_file = 0;
1431 } else {
1432 zip_writer.reset(new ZipWriter(zip_file.get()));
1433 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001434 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001435 }
1436
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001437 if (do_update_progress) {
1438 if (do_broadcast) {
1439 // clang-format off
1440 std::vector<std::string> am_args = {
1441 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1442 "--es", "android.intent.extra.NAME", suffix,
1443 "--ei", "android.intent.extra.ID", std::to_string(id),
1444 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1445 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1446 };
1447 // clang-format on
1448 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1449 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001450 if (use_control_socket) {
1451 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str());
1452 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001453 }
1454 }
1455
Nick Kralevichf3599b32016-01-25 15:05:16 -08001456 /* read /proc/cmdline before dropping root */
1457 FILE *cmdline = fopen("/proc/cmdline", "re");
1458 if (cmdline) {
1459 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1460 fclose(cmdline);
1461 }
1462
Jeff Brown1dc94e32014-09-11 14:15:27 -07001463 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001464 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001465 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001466 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001467 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001468 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001469 }
John Michelau1f794c42012-09-17 11:20:19 -05001470 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001471
Felipe Leme3634a1e2015-12-09 10:11:47 -08001472 if (do_fb && do_early_screenshot) {
1473 if (screenshot_path.empty()) {
1474 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001475 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001476 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001477 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001478 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001479 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001480 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001481 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001482 screenshot_path.c_str(), strerror(errno));
1483 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001484 }
1485 }
1486
Felipe Leme1e9edc62015-12-21 16:02:13 -08001487 if (do_zip_file) {
1488 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001489 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001490 }
1491 }
1492
Felipe Leme71bbfc52015-11-23 14:14:51 -08001493 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001494 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001495 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1496 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1497 log_path.c_str(), strerror(errno));
1498 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001499 /* TODO: rather than generating a text file now and zipping it later,
1500 it would be more efficient to redirect stdout to the zip entry
1501 directly, but the libziparchive doesn't support that option yet. */
1502 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001503 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1504 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1505 tmp_path.c_str(), strerror(errno));
1506 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001507 }
Felipe Leme608385d2016-02-01 10:35:38 -08001508 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1509 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001510 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001511 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001512
Felipe Leme71a74ac2016-03-17 15:43:25 -07001513 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001514 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1515 // the raw trace.
1516 if (!dump_anrd_trace()) {
1517 dump_systrace();
1518 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001519
Wei Liu341938b2016-04-27 16:18:17 -07001520 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
Felipe Lemeefd7e272016-05-18 09:27:16 -07001521 dump_raft();
Wei Liu341938b2016-04-27 16:18:17 -07001522
Felipe Leme9c74aad2016-02-29 18:15:42 -08001523 // Invoking the following dumpsys calls before dump_traces() to try and
1524 // keep the system stats as close to its initial state as possible.
Thierry Strudel8b78b752016-03-22 10:25:44 -07001525 run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
Felipe Leme7cff4622016-06-08 09:51:29 -07001526 run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL);
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001527
1528 /* collect stack traces from Dalvik and native processes (needs root) */
1529 dump_traces_path = dump_traces();
1530
Felipe Lemec0808152016-06-17 17:37:13 -07001531 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001532 get_tombstone_fds(tombstone_data);
1533 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001534 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001535 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001536 if (!is_user_build()) {
1537 add_dir(PROFILE_DATA_DIR_CUR, true);
1538 add_dir(PROFILE_DATA_DIR_REF, true);
1539 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001540 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001541 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001542
Erik Kline53ca94a2016-09-28 17:26:26 +09001543 // Capture any IPSec policies in play. No keys are exposed here.
1544 run_command("IP XFRM POLICY", 10, "ip", "xfrm", "policy", nullptr);
1545
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001546 // Run ss as root so we can see socket marks.
1547 run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1548
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001549 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001550 return -1;
1551 }
1552
1553 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001554
Felipe Leme55b42a62015-11-10 17:39:08 -08001555 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001556 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001557 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001558 }
1559
Felipe Leme6e01fa62015-11-11 19:35:14 -08001560 /* rename or zip the (now complete) .tmp file to its final location */
1561 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001562
1563 /* check if user changed the suffix using system properties */
1564 char key[PROPERTY_KEY_MAX];
1565 char value[PROPERTY_VALUE_MAX];
Nick Kralevichf0922cc2016-05-14 16:47:44 -07001566 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001567 property_get(key, value, "");
1568 bool change_suffix= false;
1569 if (value[0]) {
1570 /* must whitelist which characters are allowed, otherwise it could cross directories */
1571 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
1572 if (std::regex_match(value, valid_regex)) {
1573 change_suffix = true;
1574 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001575 MYLOGE("invalid suffix provided by user: %s\n", value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001576 }
1577 }
1578 if (change_suffix) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001579 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001580 suffix = value;
1581 if (!screenshot_path.empty()) {
1582 std::string new_screenshot_path =
1583 bugreport_dir + "/" + base_name + "-" + suffix + ".png";
1584 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001585 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001586 new_screenshot_path.c_str(), strerror(errno));
1587 } else {
1588 screenshot_path = new_screenshot_path;
1589 }
1590 }
1591 }
1592
Felipe Leme6e01fa62015-11-11 19:35:14 -08001593 bool do_text_file = true;
1594 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001595 std::string entry_name = base_name + "-" + suffix + ".txt";
1596 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
1597 if (!finish_zip_file(entry_name, tmp_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001598 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001599 do_text_file = true;
1600 } else {
1601 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001602 // Since zip file is already created, it needs to be renamed.
1603 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
1604 if (path != new_path) {
1605 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1606 if (rename(path.c_str(), new_path.c_str())) {
1607 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1608 new_path.c_str(), strerror(errno));
1609 } else {
1610 path = new_path;
1611 }
1612 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001613 }
1614 }
1615 if (do_text_file) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001616 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001617 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001618 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001619 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001620 path.clear();
1621 }
1622 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001623 if (use_control_socket) {
1624 if (do_text_file) {
1625 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
1626 "for more details\n", log_path.c_str());
1627 } else {
1628 dprintf(control_socket_fd, "OK:%s\n", path.c_str());
1629 }
1630 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001631 }
1632
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001633 /* vibrate a few but shortly times to let user know it's finished */
1634 if (vibrator) {
1635 for (int i = 0; i < 3; i++) {
1636 vibrate(vibrator.get(), 75);
1637 usleep((75 + 50) * 1000);
1638 }
1639 }
1640
Jeff Brown1dc94e32014-09-11 14:15:27 -07001641 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001642 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001643 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001644 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001645 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001646 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001647 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001648 "--ei", "android.intent.extra.ID", std::to_string(id),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001649 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemeee2e4a02016-02-22 18:12:11 -08001650 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001651 "--es", "android.intent.extra.BUGREPORT", path,
1652 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001653 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001654 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001655 if (do_fb) {
1656 am_args.push_back("--es");
1657 am_args.push_back("android.intent.extra.SCREENSHOT");
1658 am_args.push_back(screenshot_path);
1659 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001660 if (is_remote_mode) {
1661 am_args.push_back("--es");
1662 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1663 am_args.push_back(SHA256_file_hash(path));
1664 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1665 } else {
1666 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1667 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001668 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001669 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001670 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001671 }
1672
Felipe Lemecbce55d2016-02-08 09:53:18 -08001673 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
1674 MYLOGI("done\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001675
Felipe Leme107a05f2016-03-08 15:11:15 -08001676 if (is_redirecting) {
1677 fclose(stderr);
1678 }
1679
Felipe Leme02b7e002016-07-22 12:03:20 -07001680 if (use_control_socket && control_socket_fd != -1) {
1681 MYLOGD("Closing control socket\n");
1682 close(control_socket_fd);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001683 }
1684
Colin Crossf45fa6b2012-03-26 12:38:26 -07001685 return 0;
1686}