blob: 637b7845b87235f7ab2b447954e1a698b24988be [file] [log] [blame]
Colin Crossf45fa6b2012-03-26 12:38:26 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070017#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070018#include <errno.h>
19#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080020#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070021#include <limits.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080022#include <memory>
Felipe Lemead5f6c42015-11-30 14:26:46 -080023#include <regex>
Felipe Leme635ca312016-01-05 14:23:02 -080024#include <set>
Wei Liuf87959e2016-08-26 14:51:42 -070025#include <signal.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070026#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070027#include <stdio.h>
28#include <stdlib.h>
Felipe Leme6e01fa62015-11-11 19:35:14 -080029#include <string>
Colin Crossf45fa6b2012-03-26 12:38:26 -070030#include <string.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070031#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070032#include <sys/resource.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35#include <sys/wait.h>
36#include <unistd.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070037
Felipe Leme96c2bbb2016-09-26 09:21:21 -070038#include <android-base/file.h>
39#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080040#include <android-base/stringprintf.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070041#include <android-base/unique_fd.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070042#include <cutils/properties.h>
Wei Liuf87959e2016-08-26 14:51:42 -070043#include <hardware_legacy/power.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070044
45#include "private/android_filesystem_config.h"
46
47#define LOG_TAG "dumpstate"
Alex Ray656a6b92013-07-23 13:44:34 -070048#include <cutils/log.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070049
50#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080051#include "ziparchive/zip_writer.h"
52
Elliott Hughesc4dc1412016-04-12 16:28:31 -070053#include <openssl/sha.h>
Michal Karpinski4db754f2015-12-11 18:04:32 +000054
Felipe Leme6e01fa62015-11-11 19:35:14 -080055using android::base::StringPrintf;
Colin Crossf45fa6b2012-03-26 12:38:26 -070056
57/* read before root is shed */
58static char cmdline_buf[16384] = "(unknown)";
59static const char *dump_traces_path = NULL;
60
Felipe Leme9ce6aa42016-09-21 10:02:25 -070061// Command-line arguments as string
62static std::string args;
63
Felipe Lemeefd7e272016-05-18 09:27:16 -070064// TODO: variables below should be part of dumpstate object
Felipe Lemee82a27d2016-01-05 13:35:44 -080065static time_t now;
66static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080067static std::set<std::string> mount_points;
68void add_mountinfo();
Felipe Lemeefd7e272016-05-18 09:27:16 -070069/* suffix of the bugreport files - it's typically the date (when invoked with -d),
70 * although it could be changed by the user using a system property */
71static std::string suffix;
Felipe Leme96c2bbb2016-09-26 09:21:21 -070072static std::string extraOptions;
Felipe Leme78f2c862015-12-21 09:55:22 -080073
Todd Poynor2a83daa2013-11-22 15:44:22 -080074#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070075#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080076
Wei Liu341938b2016-04-27 16:18:17 -070077#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080078#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070079#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070080#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010081#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
82#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070083#define TOMBSTONE_DIR "/data/tombstones"
84#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
85/* Can accomodate a tombstone number up to 9999. */
86#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
87#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090088#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070089#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070090
91typedef struct {
92 char name[TOMBSTONE_MAX_LEN];
93 int fd;
94} tombstone_data_t;
95
96static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
97
Felipe Lemee844a9d2016-09-21 15:01:39 -070098// TODO: temporary variables and functions used during C++ refactoring
99static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700100static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
101 const CommandOptions& options = CommandOptions::DEFAULT) {
102 return ds.RunCommand(title, fullCommand, options);
103}
104static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
105 const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
106 long dumpsysTimeout = 0) {
107 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
108}
109static int DumpFile(const std::string& title, const std::string& path) {
110 return ds.DumpFile(title, path);
111}
Felipe Leme6ad9c062016-09-28 11:58:36 -0700112bool IsUserBuild() {
113 return ds.IsUserBuild();
114}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800115
Felipe Leme809d74e2016-02-02 12:57:00 -0800116/*
117 * List of supported zip format versions.
118 *
Felipe Leme8268ed22016-08-02 18:18:25 -0700119 * See bugreport-format.md for more info.
Felipe Leme809d74e2016-02-02 12:57:00 -0800120 */
Felipe Lemeca9c12e2016-05-19 16:30:15 -0700121static std::string VERSION_DEFAULT = "1.0";
Felipe Leme809d74e2016-02-02 12:57:00 -0800122
Felipe Lemee844a9d2016-09-21 15:01:39 -0700123// Relative directory (inside the zip) for all files copied as-is into the bugreport.
124static const std::string ZIP_ROOT_DIR = "FS";
125
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700126static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700127static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700128
Felipe Leme3d305a12016-05-20 11:24:37 -0700129/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
130 * otherwise, gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700131static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800132 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700133 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
134 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800135 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
136 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700137 struct stat st;
Felipe Leme3d305a12016-05-20 11:24:37 -0700138 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800139 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
Felipe Leme3d305a12016-05-20 11:24:37 -0700140 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700141 } else {
Felipe Leme3d305a12016-05-20 11:24:37 -0700142 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700143 data[i].fd = -1;
144 }
145 }
146}
147
Felipe Leme635ca312016-01-05 14:23:02 -0800148// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700149void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800150 char path[PATH_MAX];
151
152 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
153 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700154 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800155 char linkname[PATH_MAX];
156 ssize_t r = readlink(path, linkname, PATH_MAX);
157 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800158 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800159 return;
160 }
161 linkname[r] = '\0';
162
163 if (mount_points.find(linkname) == mount_points.end()) {
164 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700165 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800166 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
167 mount_points.insert(linkname);
168 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800169 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800170 }
171 }
172}
173
174void add_mountinfo() {
175 if (!zip_writer) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700176 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800177 mount_points.clear();
Felipe Leme678727a2016-09-21 17:22:11 -0700178 DurationReporter durationReporter(title, nullptr);
179 for_each_pid(do_mountinfo, nullptr);
180 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800181}
182
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700183static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
184{
185 DIR *d;
186 struct dirent *de;
187 char path[PATH_MAX];
188
189 d = opendir(driverpath);
190 if (d == NULL) {
191 return;
192 }
193
194 while ((de = readdir(d))) {
195 if (de->d_type != DT_LNK) {
196 continue;
197 }
198 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700199 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700200 }
201
202 closedir(d);
203}
204
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700205// return pid of a userspace process. If not found or error, return 0.
206static unsigned int pid_of_process(const char* ps_name) {
207 DIR *proc_dir;
208 struct dirent *ps;
209 unsigned int pid;
210 std::string cmdline;
211
212 if (!(proc_dir = opendir("/proc"))) {
213 MYLOGE("Can't open /proc\n");
214 return 0;
215 }
216
217 while ((ps = readdir(proc_dir))) {
218 if (!(pid = atoi(ps->d_name))) {
219 continue;
220 }
221 android::base::ReadFileToString("/proc/"
222 + std::string(ps->d_name) + "/cmdline", &cmdline);
223 if (cmdline.find(ps_name) == std::string::npos) {
224 continue;
225 } else {
226 closedir(proc_dir);
227 return pid;
228 }
229 }
230 closedir(proc_dir);
231 return 0;
232}
233
234// dump anrd's trace and add to the zip file.
235// 1. check if anrd is running on this device.
236// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
237// 3. wait until the trace generation completes and add to the zip file.
238static bool dump_anrd_trace() {
239 unsigned int pid;
240 char buf[50], path[PATH_MAX];
241 struct dirent *trace;
242 struct stat st;
243 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700244 int retry = 5;
245 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700246 long long cur_size = 0;
247 const char *trace_path = "/data/misc/anrd/";
248
249 if (!zip_writer) {
250 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
251 return false;
252 }
253
254 // find anrd's pid if it is running.
255 pid = pid_of_process("/system/xbin/anrd");
256
257 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700258 if (stat(trace_path, &st) == 0) {
259 old_mtime = st.st_mtime;
260 } else {
261 MYLOGE("Failed to find: %s\n", trace_path);
262 return false;
263 }
264
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700265 // send SIGUSR1 to the anrd to generate a trace.
266 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700267 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700268 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700269 MYLOGE("anrd signal timed out. Please manually collect trace\n");
270 return false;
271 }
272
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700273 while (retry-- > 0 && old_mtime == st.st_mtime) {
274 sleep(1);
275 stat(trace_path, &st);
276 }
277
278 if (retry < 0 && old_mtime == st.st_mtime) {
279 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
280 return false;
281 }
282
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700283 // identify the trace file by its creation time.
284 if (!(trace_dir = opendir(trace_path))) {
285 MYLOGE("Can't open trace file under %s\n", trace_path);
286 }
287 while ((trace = readdir(trace_dir))) {
288 if (strcmp(trace->d_name, ".") == 0
289 || strcmp(trace->d_name, "..") == 0) {
290 continue;
291 }
292 sprintf(path, "%s%s", trace_path, trace->d_name);
293 if (stat(path, &st) == 0) {
294 if (st.st_ctime > max_ctime) {
295 max_ctime = st.st_ctime;
296 sprintf(buf, "%s", trace->d_name);
297 }
298 }
299 }
300 closedir(trace_dir);
301
302 // Wait until the dump completes by checking the size of the trace.
303 if (max_ctime > 0) {
304 sprintf(path, "%s%s", trace_path, buf);
305 while(true) {
306 sleep(1);
307 if (stat(path, &st) == 0) {
308 if (st.st_size == cur_size) {
309 break;
310 } else if (st.st_size > cur_size) {
311 cur_size = st.st_size;
312 } else {
313 return false;
314 }
315 } else {
316 MYLOGE("Cant stat() %s anymore\n", path);
317 return false;
318 }
319 }
320 // Add to the zip file.
321 if (!add_zip_entry("anrd_trace.txt", path)) {
322 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
323 } else {
324 if (remove(path)) {
325 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
326 }
327 return true;
328 }
329 } else {
330 MYLOGE("Can't stats any trace file under %s\n", trace_path);
331 }
332 }
333 return false;
334}
335
Felipe Lemeefd7e272016-05-18 09:27:16 -0700336static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700337 if (!zip_writer) {
338 MYLOGD("Not dumping systrace because zip_writer is not set\n");
339 return;
340 }
Felipe Lemee844a9d2016-09-21 15:01:39 -0700341 std::string systrace_path = ds.bugreportDir_ + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700342 if (systrace_path.empty()) {
343 MYLOGE("Not dumping systrace because path is empty\n");
344 return;
345 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700346 const char* path = "/sys/kernel/debug/tracing/tracing_on";
347 long int is_tracing;
348 if (read_file_as_long(path, &is_tracing)) {
349 return; // error already logged
350 }
351 if (is_tracing <= 0) {
352 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
353 return;
354 }
355
Felipe Leme14e034a2016-03-30 18:51:03 -0700356 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
357 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700358 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700359 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700360 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700361 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700362 // peacefully; ideally, we should call strace to stop itself, but there is no such option
363 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700364 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700365 // MYLOGE("could not stop systrace ");
366 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700367 }
368 if (!add_zip_entry("systrace.txt", systrace_path)) {
369 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700370 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700371 if (remove(systrace_path.c_str())) {
372 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
373 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700374 }
375}
376
Felipe Lemeefd7e272016-05-18 09:27:16 -0700377static void dump_raft() {
Felipe Leme6ad9c062016-09-28 11:58:36 -0700378 if (IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700379 return;
380 }
381
Felipe Lemee844a9d2016-09-21 15:01:39 -0700382 std::string raft_log_path = ds.bugreportDir_ + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700383 if (raft_log_path.empty()) {
384 MYLOGD("raft_log_path is empty\n");
385 return;
386 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700387
388 struct stat s;
389 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
390 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
391 return;
392 }
393
Felipe Leme30dbfa12016-09-02 12:43:26 -0700394 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Wei Liu341938b2016-04-27 16:18:17 -0700395 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700396 // Write compressed and encoded raft logs to stdout if not zip_writer.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700397 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700398 return;
399 }
400
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700401 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_log_path}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700402 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
403 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
404 } else {
405 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700406 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700407 }
408 }
409}
410
Mark Salyzyn326842f2015-04-30 09:49:41 -0700411static bool skip_not_stat(const char *path) {
412 static const char stat[] = "/stat";
413 size_t len = strlen(path);
414 if (path[len - 1] == '/') { /* Directory? */
415 return false;
416 }
417 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
418}
419
Felipe Leme4c2d6632016-09-28 14:32:00 -0700420static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800421 return false;
422}
423
Mark Salyzyn326842f2015-04-30 09:49:41 -0700424static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700425unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700426
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800427//
428// stat offsets
429// Name units description
430// ---- ----- -----------
431// read I/Os requests number of read I/Os processed
432#define __STAT_READ_IOS 0
433// read merges requests number of read I/Os merged with in-queue I/O
434#define __STAT_READ_MERGES 1
435// read sectors sectors number of sectors read
436#define __STAT_READ_SECTORS 2
437// read ticks milliseconds total wait time for read requests
438#define __STAT_READ_TICKS 3
439// write I/Os requests number of write I/Os processed
440#define __STAT_WRITE_IOS 4
441// write merges requests number of write I/Os merged with in-queue I/O
442#define __STAT_WRITE_MERGES 5
443// write sectors sectors number of sectors written
444#define __STAT_WRITE_SECTORS 6
445// write ticks milliseconds total wait time for write requests
446#define __STAT_WRITE_TICKS 7
447// in_flight requests number of I/Os currently in flight
448#define __STAT_IN_FLIGHT 8
449// io_ticks milliseconds total time this block device has been active
450#define __STAT_IO_TICKS 9
451// time_in_queue milliseconds total wait time for all requests
452#define __STAT_IN_QUEUE 10
453#define __STAT_NUMBER_FIELD 11
454//
455// read I/Os, write I/Os
456// =====================
457//
458// These values increment when an I/O request completes.
459//
460// read merges, write merges
461// =========================
462//
463// These values increment when an I/O request is merged with an
464// already-queued I/O request.
465//
466// read sectors, write sectors
467// ===========================
468//
469// These values count the number of sectors read from or written to this
470// block device. The "sectors" in question are the standard UNIX 512-byte
471// sectors, not any device- or filesystem-specific block size. The
472// counters are incremented when the I/O completes.
473#define SECTOR_SIZE 512
474//
475// read ticks, write ticks
476// =======================
477//
478// These values count the number of milliseconds that I/O requests have
479// waited on this block device. If there are multiple I/O requests waiting,
480// these values will increase at a rate greater than 1000/second; for
481// example, if 60 read requests wait for an average of 30 ms, the read_ticks
482// field will increase by 60*30 = 1800.
483//
484// in_flight
485// =========
486//
487// This value counts the number of I/O requests that have been issued to
488// the device driver but have not yet completed. It does not include I/O
489// requests that are in the queue but not yet issued to the device driver.
490//
491// io_ticks
492// ========
493//
494// This value counts the number of milliseconds during which the device has
495// had I/O requests queued.
496//
497// time_in_queue
498// =============
499//
500// This value counts the number of milliseconds that I/O requests have waited
501// on this block device. If there are multiple I/O requests waiting, this
502// value will increase as the product of the number of milliseconds times the
503// number of requests waiting (see "read ticks" above for an example).
504#define S_TO_MS 1000
505//
506
Mark Salyzyn326842f2015-04-30 09:49:41 -0700507static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800508 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700509 bool z;
510 char *cp, *buffer = NULL;
511 size_t i = 0;
512 FILE *fp = fdopen(fd, "rb");
513 getline(&buffer, &i, fp);
514 fclose(fp);
515 if (!buffer) {
516 return -errno;
517 }
518 i = strlen(buffer);
519 while ((i > 0) && (buffer[i - 1] == '\n')) {
520 buffer[--i] = '\0';
521 }
522 if (!*buffer) {
523 free(buffer);
524 return 0;
525 }
526 z = true;
527 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800528 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700529 if (fields[i] != 0) {
530 z = false;
531 }
532 }
533 if (z) { /* never accessed */
534 free(buffer);
535 return 0;
536 }
537
538 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
539 path += sizeof(mmcblk0) - 1;
540 }
541
542 printf("%s: %s\n", path, buffer);
543 free(buffer);
544
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800545 if (fields[__STAT_IO_TICKS]) {
546 unsigned long read_perf = 0;
547 unsigned long read_ios = 0;
548 if (fields[__STAT_READ_TICKS]) {
549 unsigned long long divisor = fields[__STAT_READ_TICKS]
550 * fields[__STAT_IO_TICKS];
551 read_perf = ((unsigned long long)SECTOR_SIZE
552 * fields[__STAT_READ_SECTORS]
553 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
554 / divisor;
555 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
556 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
557 / divisor;
558 }
559
560 unsigned long write_perf = 0;
561 unsigned long write_ios = 0;
562 if (fields[__STAT_WRITE_TICKS]) {
563 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
564 * fields[__STAT_IO_TICKS];
565 write_perf = ((unsigned long long)SECTOR_SIZE
566 * fields[__STAT_WRITE_SECTORS]
567 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
568 / divisor;
569 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
570 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
571 / divisor;
572 }
573
574 unsigned queue = (fields[__STAT_IN_QUEUE]
575 + (fields[__STAT_IO_TICKS] >> 1))
576 / fields[__STAT_IO_TICKS];
577
578 if (!write_perf && !write_ios) {
579 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
580 path, read_perf, read_ios, queue);
581 } else {
582 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
583 path, read_perf, read_ios, write_perf, write_ios, queue);
584 }
585
586 /* bugreport timeout factor adjustment */
587 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
588 worst_write_perf = write_perf;
589 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700590 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700591 return 0;
592}
593
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700594/* Copied policy from system/core/logd/LogBuffer.cpp */
595
596#define LOG_BUFFER_SIZE (256 * 1024)
597#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
598#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
599
600static bool valid_size(unsigned long value) {
601 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
602 return false;
603 }
604
605 long pages = sysconf(_SC_PHYS_PAGES);
606 if (pages < 1) {
607 return true;
608 }
609
610 long pagesize = sysconf(_SC_PAGESIZE);
611 if (pagesize <= 1) {
612 pagesize = PAGE_SIZE;
613 }
614
615 // maximum memory impact a somewhat arbitrary ~3%
616 pages = (pages + 31) / 32;
617 unsigned long maximum = pages * pagesize;
618
619 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
620 return true;
621 }
622
623 return value <= maximum;
624}
625
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700626// TODO: migrate to logd/LogBuffer.cpp or use android::base::GetProperty
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700627static unsigned long property_get_size(const char *key) {
628 unsigned long value;
629 char *cp, property[PROPERTY_VALUE_MAX];
630
631 property_get(key, property, "");
632 value = strtoul(property, &cp, 10);
633
634 switch(*cp) {
635 case 'm':
636 case 'M':
637 value *= 1024;
638 /* FALLTHRU */
639 case 'k':
640 case 'K':
641 value *= 1024;
642 /* FALLTHRU */
643 case '\0':
644 break;
645
646 default:
647 value = 0;
648 }
649
650 if (!valid_size(value)) {
651 value = 0;
652 }
653
654 return value;
655}
656
657/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800658static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700659 static const char global_tuneable[] = "persist.logd.size"; // Settings App
660 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
661 char key[PROP_NAME_MAX];
662 unsigned long property_size, default_size;
663
664 default_size = property_get_size(global_tuneable);
665 if (!default_size) {
666 default_size = property_get_size(global_default);
667 }
668
669 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
670 property_size = property_get_size(key);
671
672 if (!property_size) {
673 snprintf(key, sizeof(key), "%s.%s", global_default, name);
674 property_size = property_get_size(key);
675 }
676
677 if (!property_size) {
678 property_size = default_size;
679 }
680
681 if (!property_size) {
682 property_size = LOG_BUFFER_SIZE;
683 }
684
685 /* Engineering margin is ten-fold our guess */
686 return 10 * (property_size + worst_write_perf) / worst_write_perf;
687}
688
689/* End copy from system/core/logd/LogBuffer.cpp */
690
Colin Crossf45fa6b2012-03-26 12:38:26 -0700691/* dumps the current system state to stdout */
Felipe Lemee844a9d2016-09-21 15:01:39 -0700692void print_header(const std::string& version) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700693 std::string build, fingerprint, radio, bootloader, network;
694 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700695
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700696 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
697 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme4c2d6632016-09-28 14:32:00 -0700698 ds.buildType_ = android::base::GetProperty("ro.build.type", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700699 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
700 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
701 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700702 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
703
704 printf("========================================================\n");
705 printf("== dumpstate: %s\n", date);
706 printf("========================================================\n");
707
708 printf("\n");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700709 printf("Build: %s\n", build.c_str());
710 // NOTE: fingerprint entry format is important for other tools.
711 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
712 printf("Bootloader: %s\n", bootloader.c_str());
713 printf("Radio: %s\n", radio.c_str());
714 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700715
716 printf("Kernel: ");
Felipe Leme678727a2016-09-21 17:22:11 -0700717 DumpFile("", "/proc/version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700718 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800719 printf("Bugreport format version: %s\n", version.c_str());
Felipe Lemee844a9d2016-09-21 15:01:39 -0700720 printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
Felipe Leme4c2d6632016-09-28 14:32:00 -0700721 ds.IsDryRun(), args.c_str(), extraOptions.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700722 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800723}
724
Felipe Leme24b66ee2016-06-16 10:55:26 -0700725// List of file extensions that can cause a zip file attachment to be rejected by some email
726// service providers.
727static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
728 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
729 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
730 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
731};
732
Felipe Leme71ca15e2016-05-19 16:18:17 -0700733bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800734 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800735 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
736 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800737 return false;
738 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700739 std::string valid_name = entry_name;
740
741 // Rename extension if necessary.
742 size_t idx = entry_name.rfind(".");
743 if (idx != std::string::npos) {
744 std::string extension = entry_name.substr(idx);
745 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
746 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
747 valid_name = entry_name + ".renamed";
748 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
749 }
750 }
751
Felipe Leme6fe9db62016-02-12 09:04:16 -0800752 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
753 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700754 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800755 ZipWriter::kCompress, get_mtime(fd, now));
756 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700757 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800758 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800759 return false;
760 }
761
Felipe Leme770410d2016-01-26 17:07:14 -0800762 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800763 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400764 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800765 if (bytes_read == 0) {
766 break;
767 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800768 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800769 return false;
770 }
771 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
772 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800773 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800774 return false;
775 }
776 }
777
778 err = zip_writer->FinishEntry();
779 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800780 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800781 return false;
782 }
783
784 return true;
785}
786
Felipe Leme71ca15e2016-05-19 16:18:17 -0700787bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700788 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
789 | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700790 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800791 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800792 return false;
793 }
794
795 return add_zip_entry_from_fd(entry_name, fd.get());
796}
797
798/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700799static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800800 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
801}
802
Felipe Leme24b66ee2016-06-16 10:55:26 -0700803// TODO: move to util.cpp
Felipe Leme678727a2016-09-21 17:22:11 -0700804void add_dir(const std::string& dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800805 if (!zip_writer) {
Felipe Leme678727a2016-09-21 17:22:11 -0700806 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800807 return;
808 }
Felipe Leme678727a2016-09-21 17:22:11 -0700809 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
810 DurationReporter durationReporter(dir, nullptr);
811 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800812}
813
Felipe Leme809d74e2016-02-02 12:57:00 -0800814/* adds a text entry entry to the existing zip file. */
815static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800816 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800817 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 -0800818 return false;
819 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800820 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800821 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
822 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800823 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800824 ZipWriter::ErrorCodeString(err));
825 return false;
826 }
827
828 err = zip_writer->WriteBytes(content.c_str(), content.length());
829 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800830 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800831 ZipWriter::ErrorCodeString(err));
832 return false;
833 }
834
835 err = zip_writer->FinishEntry();
836 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800837 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800838 return false;
839 }
840
841 return true;
842}
843
Felipe Lemec0808152016-06-17 17:37:13 -0700844static void dump_iptables() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700845 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
846 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
847 RunCommand("IPTABLE NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700848 /* no ip6 nat */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700849 RunCommand("IPTABLE MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
850 RunCommand("IP6TABLE MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
851 RunCommand("IPTABLE RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
852 RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700853}
854
Felipe Leme4c2d6632016-09-28 14:32:00 -0700855static void dumpstate(const std::string& screenshot_path,
856 const std::string& version __attribute__((unused))) {
Felipe Leme678727a2016-09-21 17:22:11 -0700857 DurationReporter durationReporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800858 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700859
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700860 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700861 RunCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -0700862 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800863 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700864 DumpFile("MEMORY INFO", "/proc/meminfo");
865 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700866 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700867 RunCommand("PROCRANK", {"procrank"}, CommandOptions::AS_ROOT_20);
868 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
869 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
870 DumpFile("SLAB INFO", "/proc/slabinfo");
871 DumpFile("ZONEINFO", "/proc/zoneinfo");
872 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
873 DumpFile("BUDDYINFO", "/proc/buddyinfo");
874 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700875
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700876 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
877 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
878 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700879
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700880 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700881 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700882 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT_10);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700883
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700884 RunCommand("PRINTENV", {"printenv"});
885 RunCommand("NETSTAT", {"netstat", "-n"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700886 struct stat s;
887 if (stat("/proc/modules", &s) != 0) {
888 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
889 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700890 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700891 }
Michal Karpinski4db754f2015-12-11 18:04:32 +0000892
Colin Crossf45fa6b2012-03-26 12:38:26 -0700893 do_dmesg();
894
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700895 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT_10);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700896 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
897 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800898 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700899
Ajay Panickerd886ec42016-09-14 12:26:46 -0700900 /* Dump Bluetooth HCI logs */
901 add_dir("/data/misc/bluetooth/logs", true);
902
Felipe Leme6e01fa62015-11-11 19:35:14 -0800903 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800904 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800905 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800906 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700907 }
908
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700909 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700910 // calculate timeout
911 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
912 if (timeout < 20000) {
913 timeout = 20000;
914 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700915 RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700916 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800917 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700918 if (timeout < 20000) {
919 timeout = 20000;
920 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700921 RunCommand("EVENT LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700922 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
923 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700924 timeout = logcat_timeout("radio");
925 if (timeout < 20000) {
926 timeout = 20000;
927 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700928 RunCommand("RADIO LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700929 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
930 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700931
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700932 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
Mark Salyzynecc07632015-07-30 14:57:09 -0700933
Colin Crossf45fa6b2012-03-26 12:38:26 -0700934 /* show the traces we collected in main(), if that was done */
935 if (dump_traces_path != NULL) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700936 DumpFile("VM TRACES JUST NOW", dump_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700937 }
938
939 /* only show ANR traces if they're less than 15 minutes old */
940 struct stat st;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700941 std::string anrTracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
942 if (anrTracesPath.empty()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700943 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700944 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700945 int fd = TEMP_FAILURE_RETRY(
946 open(anrTracesPath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
947 if (fd < 0) {
948 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anrTracesPath.c_str(), strerror(errno));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700949 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700950 dump_file_from_fd("VM TRACES AT LAST ANR", anrTracesPath.c_str(), fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700951 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700952 }
953
954 /* slow traces for slow operations */
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700955 if (!anrTracesPath.empty()) {
956 int tail = anrTracesPath.size() - 1;
957 while (tail > 0 && anrTracesPath.at(tail) != '/') {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700958 tail--;
959 }
960 int i = 0;
961 while (1) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700962 anrTracesPath =
963 anrTracesPath.substr(0, tail + 1) + android::base::StringPrintf("slow%02d.txt", i);
964 if (stat(anrTracesPath.c_str(), &st)) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700965 // No traces file at this index, done with the files.
966 break;
967 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700968 DumpFile("VM TRACES WHEN SLOW", anrTracesPath.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700969 i++;
970 }
971 }
972
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700973 int dumped = 0;
974 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
975 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800976 const char *name = tombstone_data[i].name;
977 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700978 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800979 if (zip_writer) {
980 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800981 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800982 }
983 } else {
984 dump_file_from_fd("TOMBSTONE", name, fd);
985 }
986 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700987 tombstone_data[i].fd = -1;
988 }
989 }
990 if (!dumped) {
991 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
992 }
993
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700994 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
995 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
996 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
997 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
998 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700999
Todd Poynor2a83daa2013-11-22 15:44:22 -08001000 if (!stat(PSTORE_LAST_KMSG, &st)) {
1001 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001002 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -07001003 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001004 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -08001005 } else {
1006 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001007 DumpFile("LAST KMSG", "/proc/last_kmsg");
Todd Poynor2a83daa2013-11-22 15:44:22 -08001008 }
1009
Mark Salyzyn2262c162014-12-16 09:09:26 -08001010 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001011 RunCommand("LAST LOGCAT",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001012 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
Mark Salyzyn2262c162014-12-16 09:09:26 -08001013
Colin Crossf45fa6b2012-03-26 12:38:26 -07001014 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -08001015
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001016 RunCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001017
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001018 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1019 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001020
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001021 RunCommand("IP RULES", {"ip", "rule", "show"});
1022 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001023
1024 dump_route_tables();
1025
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001026 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1027 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1028 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1029 RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001030 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001031
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001032#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001033 RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001034
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001035 RunCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001036
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001037 RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001038
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001039#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001040 DumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001041
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001042 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001043 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001044
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001045#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001046 RunCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001047
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001048 RunCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001049
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001050 RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001051#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001052 DumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001053
1054 print_properties();
1055
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001056 RunCommand("VOLD DUMP", {"vdc", "dump"});
1057 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001058
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001059 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001060
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001061 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001062
1063 printf("------ BACKLIGHTS ------\n");
1064 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001065 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001066 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001067 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001068 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001069 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001070 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001071 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001072 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001073 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001074 printf("\n");
1075
1076 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001077 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1078 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1079 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1080 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1081 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001082
Colin Crossf45fa6b2012-03-26 12:38:26 -07001083 printf("========================================================\n");
1084 printf("== Board\n");
1085 printf("========================================================\n");
1086
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001087 {
1088 DurationReporter tmpDr("dumpstate_board()");
1089 dumpstate_board();
1090 printf("\n");
1091 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001092
1093 /* Migrate the ril_dumpstate to a dumpstate_board()? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001094 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1095 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001096 // su does not exist on user builds, so try running without it.
1097 // This way any implementations of vril-dump that do not require
1098 // root can run on user builds.
1099 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001100 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001101 if (!IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001102 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001103 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001104 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001105 }
1106
1107 printf("========================================================\n");
1108 printf("== Android Framework Services\n");
1109 printf("========================================================\n");
1110
Felipe Leme5bcce572016-09-27 09:21:08 -07001111 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1112 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001113
1114 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001115 printf("== Checkins\n");
1116 printf("========================================================\n");
1117
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001118 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1119 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1120 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1121 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1122 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1123 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001124
1125 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001126 printf("== Running Application Activities\n");
1127 printf("========================================================\n");
1128
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001129 RunDumpsys("APP ACTIVITIES", {"activity", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001130
1131 printf("========================================================\n");
1132 printf("== Running Application Services\n");
1133 printf("========================================================\n");
1134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001136
1137 printf("========================================================\n");
1138 printf("== Running Application Providers\n");
1139 printf("========================================================\n");
1140
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001141 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001142
1143 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001144 printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_,
1145 ds.weightTotal_, WEIGHT_TOTAL);
Felipe Leme608385d2016-02-01 10:35:38 -08001146 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001147 printf("== dumpstate: done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001148 printf("========================================================\n");
1149}
1150
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001151static void ShowUsageAndExit(int exitCode = 1) {
1152 fprintf(stderr,
1153 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1154 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1155 " -h: display this help message\n"
1156 " -b: play sound file instead of vibrate, at beginning of job\n"
1157 " -e: play sound file instead of vibrate, at end of job\n"
1158 " -o: write to file (instead of stdout)\n"
1159 " -d: append date to filename (requires -o)\n"
1160 " -p: capture screenshot to filename.png (requires -o)\n"
1161 " -z: generate zipped file (requires -o)\n"
1162 " -s: write output to control socket (for init)\n"
1163 " -S: write file location to control socket (for init; requires -o and -z)"
1164 " -q: disable vibrate\n"
1165 " -B: send broadcast when finished (requires -o)\n"
1166 " -P: send broadcast when started and update system properties on "
1167 "progress (requires -o and -B)\n"
1168 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1169 "shouldn't be used with -P)\n"
1170 " -V: sets the bugreport format version (valid values: %s)\n",
1171 VERSION_DEFAULT.c_str());
1172 exit(exitCode);
1173}
1174
1175static void ExitOnInvalidArgs() {
1176 fprintf(stderr, "invalid combination of args\n");
1177 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001178}
1179
Wei Liuf87959e2016-08-26 14:51:42 -07001180static void wake_lock_releaser() {
1181 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1182 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1183 } else {
1184 MYLOGD("Wake lock released.\n");
1185 }
1186}
1187
Felipe Leme4c2d6632016-09-28 14:32:00 -07001188static void sig_handler(int signo __attribute__((unused))) {
Wei Liuf87959e2016-08-26 14:51:42 -07001189 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001190 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001191}
1192
Wei Liuf87959e2016-08-26 14:51:42 -07001193static void register_sig_handler() {
1194 struct sigaction sa;
1195 sigemptyset(&sa.sa_mask);
1196 sa.sa_flags = 0;
1197 sa.sa_handler = sig_handler;
1198 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1199 sigaction(SIGSEGV, &sa, NULL); // segment fault
1200 sigaction(SIGINT, &sa, NULL); // ctrl-c
1201 sigaction(SIGTERM, &sa, NULL); // killed
1202 sigaction(SIGQUIT, &sa, NULL); // quit
1203}
1204
Felipe Leme1e9edc62015-12-21 16:02:13 -08001205/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1206 temporary file.
1207 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001208static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001209 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001210 // Final timestamp
1211 char date[80];
1212 time_t the_real_now_please_stand_up = time(nullptr);
1213 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001214 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
1215 the_real_now_please_stand_up - now);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001216
Felipe Lemee82a27d2016-01-05 13:35:44 -08001217 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001218 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001219 return false;
1220 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001221 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001222 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001223 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001224 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001225
Felipe Leme0f3fb202016-06-10 17:10:53 -07001226 // Add log file (which contains stderr output) to zip...
1227 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1228 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1229 MYLOGE("Failed to add dumpstate log to .zip file\n");
1230 return false;
1231 }
1232 // ... and re-opens it for further logging.
1233 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1234 fprintf(stderr, "\n");
1235
Felipe Lemee82a27d2016-01-05 13:35:44 -08001236 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001237 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001238 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001239 return false;
1240 }
1241
Felipe Leme6ad9c062016-09-28 11:58:36 -07001242 if (IsUserBuild()) {
Felipe Lemec4eee562016-04-21 15:42:55 -07001243 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1244 if (remove(bugreport_path.c_str())) {
1245 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1246 }
1247 } else {
1248 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1249 }
1250
Felipe Leme1e9edc62015-12-21 16:02:13 -08001251 return true;
1252}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001253
Michal Karpinski4db754f2015-12-11 18:04:32 +00001254static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001255 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1256 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001257 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001258 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001259 return NULL;
1260 }
1261
1262 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001263 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001264
1265 std::vector<uint8_t> buffer(65536);
1266 while (1) {
1267 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1268 if (bytes_read == 0) {
1269 break;
1270 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001271 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001272 return NULL;
1273 }
1274
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001275 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001276 }
1277
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001278 uint8_t hash[SHA256_DIGEST_LENGTH];
1279 SHA256_Final(hash, &ctx);
1280
1281 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1282 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001283 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001284 }
1285 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1286 return std::string(hash_buffer);
1287}
1288
Colin Crossf45fa6b2012-03-26 12:38:26 -07001289int main(int argc, char *argv[]) {
1290 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001291 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001292 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001294 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001295 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001296 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001297 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001298 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001299 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001300 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001301
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001302 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001303
Felipe Lemecbce55d2016-02-08 09:53:18 -08001304 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001305
Wei Liuf87959e2016-08-26 14:51:42 -07001306 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1307 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1308 } else {
1309 MYLOGD("Wake lock acquired.\n");
1310 atexit(wake_lock_releaser);
1311 register_sig_handler();
1312 }
1313
Felipe Leme4c2d6632016-09-28 14:32:00 -07001314 if (ds.IsDryRun()) {
Felipe Leme8268ed22016-08-02 18:18:25 -07001315 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1316 }
1317
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001318 // TODO: use helper function to convert argv into a string
Felipe Leme30dbfa12016-09-02 12:43:26 -07001319 for (int i = 0; i < argc; i++) {
1320 args += argv[i];
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001321 if (i < argc - 1) {
1322 args += " ";
1323 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001324 }
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001325
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001326 extraOptions = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1327 MYLOGI("Dumpstate args: %s (extra options: %s)\n", args.c_str(), extraOptions.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -07001328
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001329 /* gets the sequential id */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001330 int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemee844a9d2016-09-21 15:01:39 -07001331 ds.id_ = ++lastId;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001332 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001333 MYLOGI("dumpstate id: %lu\n", ds.id_);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001334
Colin Crossf45fa6b2012-03-26 12:38:26 -07001335 /* set as high priority, and protect from OOM killer */
1336 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001337
1338 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001339 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001340 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001341 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001342 } else {
1343 /* fallback to kernels <= 2.6.35 */
1344 oom_adj = fopen("/proc/self/oom_adj", "we");
1345 if (oom_adj) {
1346 fputs("-17", oom_adj);
1347 fclose(oom_adj);
1348 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001349 }
1350
Jeff Brown1dc94e32014-09-11 14:15:27 -07001351 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001352 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001353 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001354 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001355 // clang-format off
Felipe Leme71bbfc52015-11-23 14:14:51 -08001356 case 'd': do_add_date = 1; break;
1357 case 'z': do_zip_file = 1; break;
1358 case 'o': use_outfile = optarg; break;
1359 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001360 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001361 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001362 case 'q': do_vibrate = 0; break;
1363 case 'p': do_fb = 1; break;
Felipe Lemee844a9d2016-09-21 15:01:39 -07001364 case 'P': ds.updateProgress_ = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001365 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001366 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001367 case 'V': version = optarg; break;
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001368 case 'h':
1369 ShowUsageAndExit(0);
1370 break;
1371 default:
1372 fprintf(stderr, "Invalid option: %c\n", c);
1373 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001374 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001375 }
1376 }
1377
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001378 if (!extraOptions.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001379 // Framework uses a system property to override some command-line args.
1380 // Currently, it contains the type of the requested bugreport.
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001381 if (extraOptions == "bugreportplus") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001382 MYLOGD("Running as bugreportplus: add -P, remove -p\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001383 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001384 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001385 } else if (extraOptions == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001386 MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
1387 do_vibrate = 0;
1388 is_remote_mode = 1;
1389 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001390 } else if (extraOptions == "bugreportwear") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001391 MYLOGD("Running as bugreportwear: add -P\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001392 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001393 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001394 MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001395 }
1396 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001397 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001398 }
1399
Felipe Lemee844a9d2016-09-21 15:01:39 -07001400 if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001401 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001402 }
1403
Felipe Leme2628e9e2016-04-12 16:36:51 -07001404 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001405 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001406 }
1407
Felipe Lemee844a9d2016-09-21 15:01:39 -07001408 if (ds.updateProgress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001409 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001410 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001411
Felipe Lemee844a9d2016-09-21 15:01:39 -07001412 if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001413 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001414 }
1415
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001416 if (version != VERSION_DEFAULT) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001417 ShowUsageAndExit();
Felipe Leme809d74e2016-02-02 12:57:00 -08001418 }
1419
Felipe Lemecbce55d2016-02-08 09:53:18 -08001420 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001421
Felipe Lemee844a9d2016-09-21 15:01:39 -07001422 do_early_screenshot = ds.updateProgress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001423
Christopher Ferrised9354f2014-10-01 17:35:01 -07001424 // If we are going to use a socket, do it as early as possible
1425 // to avoid timeouts from bugreport.
1426 if (use_socket) {
1427 redirect_to_socket(stdout, "dumpstate");
1428 }
1429
Felipe Leme2628e9e2016-04-12 16:36:51 -07001430 if (use_control_socket) {
1431 MYLOGD("Opening control socket\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001432 ds.controlSocketFd_ = open_socket("dumpstate");
1433 ds.updateProgress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001434 }
1435
Felipe Lemecbce55d2016-02-08 09:53:18 -08001436 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001437 std::string tmp_path;
1438
Felipe Leme0f3fb202016-06-10 17:10:53 -07001439 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001440 std::string log_path;
1441
Felipe Leme14e034a2016-03-30 18:51:03 -07001442 /* full path of the systrace file, when enabled */
1443 std::string systrace_path;
1444
Felipe Lemee338bf62015-12-07 14:03:50 -08001445 /* full path of the temporary file containing the screenshot (when requested) */
1446 std::string screenshot_path;
1447
Felipe Lemecbce55d2016-02-08 09:53:18 -08001448 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001449 std::string base_name;
1450
Felipe Leme71bbfc52015-11-23 14:14:51 -08001451 /* pointer to the actual path, be it zip or text */
1452 std::string path;
1453
Felipe Leme635ca312016-01-05 14:23:02 -08001454 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001455 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001456
Felipe Lemead5f6c42015-11-30 14:26:46 -08001457 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001458 bool is_redirecting = !use_socket && use_outfile;
1459
1460 if (is_redirecting) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001461 ds.bugreportDir_ = dirname(use_outfile);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001462 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001463 if (do_add_date) {
1464 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001465 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1466 suffix = date;
1467 } else {
1468 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001469 }
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001470 std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1471 base_name = base_name + "-" + buildId;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001472 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001473 // TODO: if dumpstate was an object, the paths could be internal variables and then
1474 // we could have a function to calculate the derived values, such as:
1475 // screenshot_path = GetPath(".png");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001476 screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001477 }
Felipe Lemee844a9d2016-09-21 15:01:39 -07001478 tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
1479 log_path =
1480 ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001481
Felipe Lemee844a9d2016-09-21 15:01:39 -07001482 MYLOGD(
1483 "Bugreport dir: %s\n"
1484 "Base name: %s\n"
1485 "Suffix: %s\n"
1486 "Log path: %s\n"
1487 "Temporary path: %s\n"
1488 "Screenshot path: %s\n",
1489 ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
1490 tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001491
Felipe Leme1e9edc62015-12-21 16:02:13 -08001492 if (do_zip_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001493 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001494 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001495 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001496 zip_file.reset(fopen(path.c_str(), "wb"));
1497 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001498 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001499 do_zip_file = 0;
1500 } else {
1501 zip_writer.reset(new ZipWriter(zip_file.get()));
1502 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001503 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001504 }
1505
Felipe Lemee844a9d2016-09-21 15:01:39 -07001506 if (ds.updateProgress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001507 if (do_broadcast) {
1508 // clang-format off
1509 std::vector<std::string> am_args = {
1510 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1511 "--es", "android.intent.extra.NAME", suffix,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001512 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001513 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1514 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1515 };
1516 // clang-format on
1517 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1518 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001519 if (use_control_socket) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001520 dprintf(ds.controlSocketFd_, "BEGIN:%s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001521 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001522 }
1523 }
1524
Nick Kralevichf3599b32016-01-25 15:05:16 -08001525 /* read /proc/cmdline before dropping root */
1526 FILE *cmdline = fopen("/proc/cmdline", "re");
1527 if (cmdline) {
1528 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1529 fclose(cmdline);
1530 }
1531
Jeff Brown1dc94e32014-09-11 14:15:27 -07001532 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001533 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001534 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001535 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001536 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001537 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001538 }
John Michelau1f794c42012-09-17 11:20:19 -05001539 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001540
Felipe Leme3634a1e2015-12-09 10:11:47 -08001541 if (do_fb && do_early_screenshot) {
1542 if (screenshot_path.empty()) {
1543 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001544 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001545 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001546 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001547 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001548 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001549 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001550 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001551 screenshot_path.c_str(), strerror(errno));
1552 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001553 }
1554 }
1555
Felipe Leme1e9edc62015-12-21 16:02:13 -08001556 if (do_zip_file) {
1557 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001558 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001559 }
1560 }
1561
Felipe Leme71bbfc52015-11-23 14:14:51 -08001562 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001563 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001564 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1565 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1566 log_path.c_str(), strerror(errno));
1567 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001568 /* TODO: rather than generating a text file now and zipping it later,
1569 it would be more efficient to redirect stdout to the zip entry
1570 directly, but the libziparchive doesn't support that option yet. */
1571 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001572 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1573 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1574 tmp_path.c_str(), strerror(errno));
1575 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001576 }
Felipe Leme608385d2016-02-01 10:35:38 -08001577 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1578 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001579 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001580 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001581
Felipe Leme71a74ac2016-03-17 15:43:25 -07001582 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001583 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1584 // the raw trace.
1585 if (!dump_anrd_trace()) {
1586 dump_systrace();
1587 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001588
Felipe Leme9c74aad2016-02-29 18:15:42 -08001589 // Invoking the following dumpsys calls before dump_traces() to try and
1590 // keep the system stats as close to its initial state as possible.
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001591 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001592 CommandOptions::WithTimeout(90).DropRoot().Build());
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001593 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001594 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001595
Felipe Lemee844a9d2016-09-21 15:01:39 -07001596 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1597 dump_raft();
1598
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001599 /* collect stack traces from Dalvik and native processes (needs root) */
1600 dump_traces_path = dump_traces();
1601
Felipe Lemec0808152016-06-17 17:37:13 -07001602 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001603 get_tombstone_fds(tombstone_data);
1604 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001605 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001606 add_dir(LOGPERSIST_DATA_DIR, false);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001607 if (!IsUserBuild()) {
David Brazdild2991962016-06-03 14:40:44 +01001608 add_dir(PROFILE_DATA_DIR_CUR, true);
1609 add_dir(PROFILE_DATA_DIR_REF, true);
1610 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001611 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001612 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001613
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001614 // Run ss as root so we can see socket marks.
Felipe Lemec7fe8fe2016-09-21 18:13:20 -07001615 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001616
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001617 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001618 return -1;
1619 }
1620
1621 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001622
Felipe Leme55b42a62015-11-10 17:39:08 -08001623 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001624 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001625 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001626 }
1627
Felipe Leme6e01fa62015-11-11 19:35:14 -08001628 /* rename or zip the (now complete) .tmp file to its final location */
1629 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001630
1631 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001632 std::string name = android::base::GetProperty(
1633 android::base::StringPrintf("dumpstate.%d.name", getpid()), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001634 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001635 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001636 /* must whitelist which characters are allowed, otherwise it could cross directories */
1637 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001638 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001639 change_suffix = true;
1640 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001641 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001642 }
1643 }
1644 if (change_suffix) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001645 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), name.c_str());
1646 suffix = name;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001647 if (!screenshot_path.empty()) {
1648 std::string new_screenshot_path =
Felipe Lemee844a9d2016-09-21 15:01:39 -07001649 ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Lemead5f6c42015-11-30 14:26:46 -08001650 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001651 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001652 new_screenshot_path.c_str(), strerror(errno));
1653 } else {
1654 screenshot_path = new_screenshot_path;
1655 }
1656 }
1657 }
1658
Felipe Leme6e01fa62015-11-11 19:35:14 -08001659 bool do_text_file = true;
1660 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001661 std::string entry_name = base_name + "-" + suffix + ".txt";
1662 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Leme0f3fb202016-06-10 17:10:53 -07001663 if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001664 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001665 do_text_file = true;
1666 } else {
1667 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001668 // Since zip file is already created, it needs to be renamed.
Felipe Lemee844a9d2016-09-21 15:01:39 -07001669 std::string new_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme91274352016-02-26 15:03:52 -08001670 if (path != new_path) {
1671 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1672 if (rename(path.c_str(), new_path.c_str())) {
1673 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1674 new_path.c_str(), strerror(errno));
1675 } else {
1676 path = new_path;
1677 }
1678 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001679 }
1680 }
1681 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001682 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001683 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001684 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001685 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001686 path.clear();
1687 }
1688 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001689 if (use_control_socket) {
1690 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001691 dprintf(ds.controlSocketFd_,
1692 "FAIL:could not create zip file, check %s "
1693 "for more details\n",
1694 log_path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001695 } else {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001696 dprintf(ds.controlSocketFd_, "OK:%s\n", path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001697 }
1698 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001699 }
1700
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001701 /* vibrate a few but shortly times to let user know it's finished */
1702 if (vibrator) {
1703 for (int i = 0; i < 3; i++) {
1704 vibrate(vibrator.get(), 75);
1705 usleep((75 + 50) * 1000);
1706 }
1707 }
1708
Jeff Brown1dc94e32014-09-11 14:15:27 -07001709 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001710 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001711 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001712 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001713 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001714 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001715 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001716 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001717 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemee844a9d2016-09-21 15:01:39 -07001718 "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001719 "--es", "android.intent.extra.BUGREPORT", path,
1720 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001721 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001722 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001723 if (do_fb) {
1724 am_args.push_back("--es");
1725 am_args.push_back("android.intent.extra.SCREENSHOT");
1726 am_args.push_back(screenshot_path);
1727 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001728 if (is_remote_mode) {
1729 am_args.push_back("--es");
1730 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1731 am_args.push_back(SHA256_file_hash(path));
1732 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1733 } else {
1734 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1735 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001736 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001737 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001738 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001739 }
1740
Felipe Lemee844a9d2016-09-21 15:01:39 -07001741 MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL);
1742 MYLOGI("done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001743
Felipe Leme107a05f2016-03-08 15:11:15 -08001744 if (is_redirecting) {
1745 fclose(stderr);
1746 }
1747
Felipe Lemee844a9d2016-09-21 15:01:39 -07001748 if (use_control_socket && ds.controlSocketFd_ != -1) {
1749 MYLOGD("Closing control socket\n");
1750 close(ds.controlSocketFd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001751 }
1752
Colin Crossf45fa6b2012-03-26 12:38:26 -07001753 return 0;
1754}