blob: b5a335214acc0737a953d5c9592aa060ba61410d [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 Leme96c2bbb2016-09-26 09:21:21 -070065static std::string buildType;
Felipe Lemee82a27d2016-01-05 13:35:44 -080066static time_t now;
67static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080068static std::set<std::string> mount_points;
69void add_mountinfo();
Felipe Lemeefd7e272016-05-18 09:27:16 -070070/* suffix of the bugreport files - it's typically the date (when invoked with -d),
71 * although it could be changed by the user using a system property */
72static std::string suffix;
Felipe Leme96c2bbb2016-09-26 09:21:21 -070073static std::string extraOptions;
Felipe Leme78f2c862015-12-21 09:55:22 -080074
Todd Poynor2a83daa2013-11-22 15:44:22 -080075#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070076#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080077
Wei Liu341938b2016-04-27 16:18:17 -070078#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080079#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070080#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070081#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010082#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
83#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070084#define TOMBSTONE_DIR "/data/tombstones"
85#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
86/* Can accomodate a tombstone number up to 9999. */
87#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
88#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090089#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070090#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070091
92typedef struct {
93 char name[TOMBSTONE_MAX_LEN];
94 int fd;
95} tombstone_data_t;
96
97static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
98
Felipe Lemee844a9d2016-09-21 15:01:39 -070099// TODO: temporary variables and functions used during C++ refactoring
100static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700101static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
102 const CommandOptions& options = CommandOptions::DEFAULT) {
103 return ds.RunCommand(title, fullCommand, options);
104}
105static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
106 const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
107 long dumpsysTimeout = 0) {
108 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
109}
110static int DumpFile(const std::string& title, const std::string& path) {
111 return ds.DumpFile(title, path);
112}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800113
Felipe Leme809d74e2016-02-02 12:57:00 -0800114/*
115 * List of supported zip format versions.
116 *
Felipe Leme8268ed22016-08-02 18:18:25 -0700117 * See bugreport-format.md for more info.
Felipe Leme809d74e2016-02-02 12:57:00 -0800118 */
Felipe Lemeca9c12e2016-05-19 16:30:15 -0700119static std::string VERSION_DEFAULT = "1.0";
Felipe Leme809d74e2016-02-02 12:57:00 -0800120
Felipe Lemee844a9d2016-09-21 15:01:39 -0700121// Relative directory (inside the zip) for all files copied as-is into the bugreport.
122static const std::string ZIP_ROOT_DIR = "FS";
123
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700124static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700125static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700126
Calvin On249beee2016-06-03 15:17:07 -0700127bool is_user_build() {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700128 return "user" == buildType;
Felipe Lemec4eee562016-04-21 15:42:55 -0700129}
130
Felipe Lemee844a9d2016-09-21 15:01:39 -0700131bool Dumpstate::IsDryRun() {
132 return dryRun_;
Felipe Leme8268ed22016-08-02 18:18:25 -0700133}
134
Felipe Leme3d305a12016-05-20 11:24:37 -0700135/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
136 * otherwise, gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700137static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800138 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700139 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
140 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800141 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
142 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700143 struct stat st;
Felipe Leme3d305a12016-05-20 11:24:37 -0700144 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800145 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
Felipe Leme3d305a12016-05-20 11:24:37 -0700146 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700147 } else {
Felipe Leme3d305a12016-05-20 11:24:37 -0700148 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700149 data[i].fd = -1;
150 }
151 }
152}
153
Felipe Leme635ca312016-01-05 14:23:02 -0800154// for_each_pid() callback to get mount info about a process.
155void do_mountinfo(int pid, const char *name) {
156 char path[PATH_MAX];
157
158 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
159 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700160 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800161 char linkname[PATH_MAX];
162 ssize_t r = readlink(path, linkname, PATH_MAX);
163 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800164 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800165 return;
166 }
167 linkname[r] = '\0';
168
169 if (mount_points.find(linkname) == mount_points.end()) {
170 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700171 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800172 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
173 mount_points.insert(linkname);
174 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800175 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800176 }
177 }
178}
179
180void add_mountinfo() {
181 if (!zip_writer) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700182 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800183 mount_points.clear();
Felipe Leme678727a2016-09-21 17:22:11 -0700184 DurationReporter durationReporter(title, nullptr);
185 for_each_pid(do_mountinfo, nullptr);
186 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800187}
188
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700189static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
190{
191 DIR *d;
192 struct dirent *de;
193 char path[PATH_MAX];
194
195 d = opendir(driverpath);
196 if (d == NULL) {
197 return;
198 }
199
200 while ((de = readdir(d))) {
201 if (de->d_type != DT_LNK) {
202 continue;
203 }
204 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700205 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700206 }
207
208 closedir(d);
209}
210
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700211// return pid of a userspace process. If not found or error, return 0.
212static unsigned int pid_of_process(const char* ps_name) {
213 DIR *proc_dir;
214 struct dirent *ps;
215 unsigned int pid;
216 std::string cmdline;
217
218 if (!(proc_dir = opendir("/proc"))) {
219 MYLOGE("Can't open /proc\n");
220 return 0;
221 }
222
223 while ((ps = readdir(proc_dir))) {
224 if (!(pid = atoi(ps->d_name))) {
225 continue;
226 }
227 android::base::ReadFileToString("/proc/"
228 + std::string(ps->d_name) + "/cmdline", &cmdline);
229 if (cmdline.find(ps_name) == std::string::npos) {
230 continue;
231 } else {
232 closedir(proc_dir);
233 return pid;
234 }
235 }
236 closedir(proc_dir);
237 return 0;
238}
239
240// dump anrd's trace and add to the zip file.
241// 1. check if anrd is running on this device.
242// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
243// 3. wait until the trace generation completes and add to the zip file.
244static bool dump_anrd_trace() {
245 unsigned int pid;
246 char buf[50], path[PATH_MAX];
247 struct dirent *trace;
248 struct stat st;
249 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700250 int retry = 5;
251 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700252 long long cur_size = 0;
253 const char *trace_path = "/data/misc/anrd/";
254
255 if (!zip_writer) {
256 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
257 return false;
258 }
259
260 // find anrd's pid if it is running.
261 pid = pid_of_process("/system/xbin/anrd");
262
263 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700264 if (stat(trace_path, &st) == 0) {
265 old_mtime = st.st_mtime;
266 } else {
267 MYLOGE("Failed to find: %s\n", trace_path);
268 return false;
269 }
270
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700271 // send SIGUSR1 to the anrd to generate a trace.
272 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700273 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700274 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700275 MYLOGE("anrd signal timed out. Please manually collect trace\n");
276 return false;
277 }
278
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700279 while (retry-- > 0 && old_mtime == st.st_mtime) {
280 sleep(1);
281 stat(trace_path, &st);
282 }
283
284 if (retry < 0 && old_mtime == st.st_mtime) {
285 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
286 return false;
287 }
288
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700289 // identify the trace file by its creation time.
290 if (!(trace_dir = opendir(trace_path))) {
291 MYLOGE("Can't open trace file under %s\n", trace_path);
292 }
293 while ((trace = readdir(trace_dir))) {
294 if (strcmp(trace->d_name, ".") == 0
295 || strcmp(trace->d_name, "..") == 0) {
296 continue;
297 }
298 sprintf(path, "%s%s", trace_path, trace->d_name);
299 if (stat(path, &st) == 0) {
300 if (st.st_ctime > max_ctime) {
301 max_ctime = st.st_ctime;
302 sprintf(buf, "%s", trace->d_name);
303 }
304 }
305 }
306 closedir(trace_dir);
307
308 // Wait until the dump completes by checking the size of the trace.
309 if (max_ctime > 0) {
310 sprintf(path, "%s%s", trace_path, buf);
311 while(true) {
312 sleep(1);
313 if (stat(path, &st) == 0) {
314 if (st.st_size == cur_size) {
315 break;
316 } else if (st.st_size > cur_size) {
317 cur_size = st.st_size;
318 } else {
319 return false;
320 }
321 } else {
322 MYLOGE("Cant stat() %s anymore\n", path);
323 return false;
324 }
325 }
326 // Add to the zip file.
327 if (!add_zip_entry("anrd_trace.txt", path)) {
328 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
329 } else {
330 if (remove(path)) {
331 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
332 }
333 return true;
334 }
335 } else {
336 MYLOGE("Can't stats any trace file under %s\n", trace_path);
337 }
338 }
339 return false;
340}
341
Felipe Lemeefd7e272016-05-18 09:27:16 -0700342static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700343 if (!zip_writer) {
344 MYLOGD("Not dumping systrace because zip_writer is not set\n");
345 return;
346 }
Felipe Lemee844a9d2016-09-21 15:01:39 -0700347 std::string systrace_path = ds.bugreportDir_ + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700348 if (systrace_path.empty()) {
349 MYLOGE("Not dumping systrace because path is empty\n");
350 return;
351 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700352 const char* path = "/sys/kernel/debug/tracing/tracing_on";
353 long int is_tracing;
354 if (read_file_as_long(path, &is_tracing)) {
355 return; // error already logged
356 }
357 if (is_tracing <= 0) {
358 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
359 return;
360 }
361
Felipe Leme14e034a2016-03-30 18:51:03 -0700362 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
363 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700364 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700365 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700366 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Leme30dbfa12016-09-02 12:43:26 -0700367 // TODO: run_command tries to kill the process, but atrace doesn't die
368 // peacefully; ideally, we should call strace to stop itself, but there is no such option
369 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700370 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700371 // MYLOGE("could not stop systrace ");
372 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700373 }
374 if (!add_zip_entry("systrace.txt", systrace_path)) {
375 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700376 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700377 if (remove(systrace_path.c_str())) {
378 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
379 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700380 }
381}
382
Felipe Lemeefd7e272016-05-18 09:27:16 -0700383static void dump_raft() {
Wei Liu341938b2016-04-27 16:18:17 -0700384 if (is_user_build()) {
385 return;
386 }
387
Felipe Lemee844a9d2016-09-21 15:01:39 -0700388 std::string raft_log_path = ds.bugreportDir_ + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700389 if (raft_log_path.empty()) {
390 MYLOGD("raft_log_path is empty\n");
391 return;
392 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700393
394 struct stat s;
395 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
396 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
397 return;
398 }
399
Felipe Leme30dbfa12016-09-02 12:43:26 -0700400 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Wei Liu341938b2016-04-27 16:18:17 -0700401 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700402 // Write compressed and encoded raft logs to stdout if not zip_writer.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700403 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700404 return;
405 }
406
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700407 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_log_path}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700408 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
409 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
410 } else {
411 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700412 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700413 }
414 }
415}
416
Mark Salyzyn326842f2015-04-30 09:49:41 -0700417static bool skip_not_stat(const char *path) {
418 static const char stat[] = "/stat";
419 size_t len = strlen(path);
420 if (path[len - 1] == '/') { /* Directory? */
421 return false;
422 }
423 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
424}
425
Felipe Lemee82a27d2016-01-05 13:35:44 -0800426static bool skip_none(const char *path) {
427 return false;
428}
429
Mark Salyzyn326842f2015-04-30 09:49:41 -0700430static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700431unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700432
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800433//
434// stat offsets
435// Name units description
436// ---- ----- -----------
437// read I/Os requests number of read I/Os processed
438#define __STAT_READ_IOS 0
439// read merges requests number of read I/Os merged with in-queue I/O
440#define __STAT_READ_MERGES 1
441// read sectors sectors number of sectors read
442#define __STAT_READ_SECTORS 2
443// read ticks milliseconds total wait time for read requests
444#define __STAT_READ_TICKS 3
445// write I/Os requests number of write I/Os processed
446#define __STAT_WRITE_IOS 4
447// write merges requests number of write I/Os merged with in-queue I/O
448#define __STAT_WRITE_MERGES 5
449// write sectors sectors number of sectors written
450#define __STAT_WRITE_SECTORS 6
451// write ticks milliseconds total wait time for write requests
452#define __STAT_WRITE_TICKS 7
453// in_flight requests number of I/Os currently in flight
454#define __STAT_IN_FLIGHT 8
455// io_ticks milliseconds total time this block device has been active
456#define __STAT_IO_TICKS 9
457// time_in_queue milliseconds total wait time for all requests
458#define __STAT_IN_QUEUE 10
459#define __STAT_NUMBER_FIELD 11
460//
461// read I/Os, write I/Os
462// =====================
463//
464// These values increment when an I/O request completes.
465//
466// read merges, write merges
467// =========================
468//
469// These values increment when an I/O request is merged with an
470// already-queued I/O request.
471//
472// read sectors, write sectors
473// ===========================
474//
475// These values count the number of sectors read from or written to this
476// block device. The "sectors" in question are the standard UNIX 512-byte
477// sectors, not any device- or filesystem-specific block size. The
478// counters are incremented when the I/O completes.
479#define SECTOR_SIZE 512
480//
481// read ticks, write ticks
482// =======================
483//
484// These values count the number of milliseconds that I/O requests have
485// waited on this block device. If there are multiple I/O requests waiting,
486// these values will increase at a rate greater than 1000/second; for
487// example, if 60 read requests wait for an average of 30 ms, the read_ticks
488// field will increase by 60*30 = 1800.
489//
490// in_flight
491// =========
492//
493// This value counts the number of I/O requests that have been issued to
494// the device driver but have not yet completed. It does not include I/O
495// requests that are in the queue but not yet issued to the device driver.
496//
497// io_ticks
498// ========
499//
500// This value counts the number of milliseconds during which the device has
501// had I/O requests queued.
502//
503// time_in_queue
504// =============
505//
506// This value counts the number of milliseconds that I/O requests have waited
507// on this block device. If there are multiple I/O requests waiting, this
508// value will increase as the product of the number of milliseconds times the
509// number of requests waiting (see "read ticks" above for an example).
510#define S_TO_MS 1000
511//
512
Mark Salyzyn326842f2015-04-30 09:49:41 -0700513static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800514 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700515 bool z;
516 char *cp, *buffer = NULL;
517 size_t i = 0;
518 FILE *fp = fdopen(fd, "rb");
519 getline(&buffer, &i, fp);
520 fclose(fp);
521 if (!buffer) {
522 return -errno;
523 }
524 i = strlen(buffer);
525 while ((i > 0) && (buffer[i - 1] == '\n')) {
526 buffer[--i] = '\0';
527 }
528 if (!*buffer) {
529 free(buffer);
530 return 0;
531 }
532 z = true;
533 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800534 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700535 if (fields[i] != 0) {
536 z = false;
537 }
538 }
539 if (z) { /* never accessed */
540 free(buffer);
541 return 0;
542 }
543
544 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
545 path += sizeof(mmcblk0) - 1;
546 }
547
548 printf("%s: %s\n", path, buffer);
549 free(buffer);
550
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800551 if (fields[__STAT_IO_TICKS]) {
552 unsigned long read_perf = 0;
553 unsigned long read_ios = 0;
554 if (fields[__STAT_READ_TICKS]) {
555 unsigned long long divisor = fields[__STAT_READ_TICKS]
556 * fields[__STAT_IO_TICKS];
557 read_perf = ((unsigned long long)SECTOR_SIZE
558 * fields[__STAT_READ_SECTORS]
559 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
560 / divisor;
561 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
562 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
563 / divisor;
564 }
565
566 unsigned long write_perf = 0;
567 unsigned long write_ios = 0;
568 if (fields[__STAT_WRITE_TICKS]) {
569 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
570 * fields[__STAT_IO_TICKS];
571 write_perf = ((unsigned long long)SECTOR_SIZE
572 * fields[__STAT_WRITE_SECTORS]
573 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
574 / divisor;
575 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
576 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
577 / divisor;
578 }
579
580 unsigned queue = (fields[__STAT_IN_QUEUE]
581 + (fields[__STAT_IO_TICKS] >> 1))
582 / fields[__STAT_IO_TICKS];
583
584 if (!write_perf && !write_ios) {
585 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
586 path, read_perf, read_ios, queue);
587 } else {
588 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
589 path, read_perf, read_ios, write_perf, write_ios, queue);
590 }
591
592 /* bugreport timeout factor adjustment */
593 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
594 worst_write_perf = write_perf;
595 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700596 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700597 return 0;
598}
599
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700600/* Copied policy from system/core/logd/LogBuffer.cpp */
601
602#define LOG_BUFFER_SIZE (256 * 1024)
603#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
604#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
605
606static bool valid_size(unsigned long value) {
607 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
608 return false;
609 }
610
611 long pages = sysconf(_SC_PHYS_PAGES);
612 if (pages < 1) {
613 return true;
614 }
615
616 long pagesize = sysconf(_SC_PAGESIZE);
617 if (pagesize <= 1) {
618 pagesize = PAGE_SIZE;
619 }
620
621 // maximum memory impact a somewhat arbitrary ~3%
622 pages = (pages + 31) / 32;
623 unsigned long maximum = pages * pagesize;
624
625 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
626 return true;
627 }
628
629 return value <= maximum;
630}
631
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700632// TODO: migrate to logd/LogBuffer.cpp or use android::base::GetProperty
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700633static unsigned long property_get_size(const char *key) {
634 unsigned long value;
635 char *cp, property[PROPERTY_VALUE_MAX];
636
637 property_get(key, property, "");
638 value = strtoul(property, &cp, 10);
639
640 switch(*cp) {
641 case 'm':
642 case 'M':
643 value *= 1024;
644 /* FALLTHRU */
645 case 'k':
646 case 'K':
647 value *= 1024;
648 /* FALLTHRU */
649 case '\0':
650 break;
651
652 default:
653 value = 0;
654 }
655
656 if (!valid_size(value)) {
657 value = 0;
658 }
659
660 return value;
661}
662
663/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800664static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700665 static const char global_tuneable[] = "persist.logd.size"; // Settings App
666 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
667 char key[PROP_NAME_MAX];
668 unsigned long property_size, default_size;
669
670 default_size = property_get_size(global_tuneable);
671 if (!default_size) {
672 default_size = property_get_size(global_default);
673 }
674
675 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
676 property_size = property_get_size(key);
677
678 if (!property_size) {
679 snprintf(key, sizeof(key), "%s.%s", global_default, name);
680 property_size = property_get_size(key);
681 }
682
683 if (!property_size) {
684 property_size = default_size;
685 }
686
687 if (!property_size) {
688 property_size = LOG_BUFFER_SIZE;
689 }
690
691 /* Engineering margin is ten-fold our guess */
692 return 10 * (property_size + worst_write_perf) / worst_write_perf;
693}
694
695/* End copy from system/core/logd/LogBuffer.cpp */
696
Colin Crossf45fa6b2012-03-26 12:38:26 -0700697/* dumps the current system state to stdout */
Felipe Lemee844a9d2016-09-21 15:01:39 -0700698void print_header(const std::string& version) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700699 std::string build, fingerprint, radio, bootloader, network;
700 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700701
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700702 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
703 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
704 buildType = android::base::GetProperty("ro.build.type", "(unknown)");
705 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
706 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
707 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700708 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
709
710 printf("========================================================\n");
711 printf("== dumpstate: %s\n", date);
712 printf("========================================================\n");
713
714 printf("\n");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700715 printf("Build: %s\n", build.c_str());
716 // NOTE: fingerprint entry format is important for other tools.
717 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
718 printf("Bootloader: %s\n", bootloader.c_str());
719 printf("Radio: %s\n", radio.c_str());
720 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700721
722 printf("Kernel: ");
Felipe Leme678727a2016-09-21 17:22:11 -0700723 DumpFile("", "/proc/version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700724 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800725 printf("Bugreport format version: %s\n", version.c_str());
Felipe Lemee844a9d2016-09-21 15:01:39 -0700726 printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
727 ds.dryRun_, args.c_str(), extraOptions.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700728 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800729}
730
Felipe Leme24b66ee2016-06-16 10:55:26 -0700731// List of file extensions that can cause a zip file attachment to be rejected by some email
732// service providers.
733static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
734 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
735 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
736 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
737};
738
Felipe Leme71ca15e2016-05-19 16:18:17 -0700739bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800740 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800741 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
742 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800743 return false;
744 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700745 std::string valid_name = entry_name;
746
747 // Rename extension if necessary.
748 size_t idx = entry_name.rfind(".");
749 if (idx != std::string::npos) {
750 std::string extension = entry_name.substr(idx);
751 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
752 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
753 valid_name = entry_name + ".renamed";
754 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
755 }
756 }
757
Felipe Leme6fe9db62016-02-12 09:04:16 -0800758 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
759 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700760 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800761 ZipWriter::kCompress, get_mtime(fd, now));
762 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700763 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800764 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800765 return false;
766 }
767
Felipe Leme770410d2016-01-26 17:07:14 -0800768 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800769 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400770 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800771 if (bytes_read == 0) {
772 break;
773 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800774 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800775 return false;
776 }
777 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
778 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800779 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800780 return false;
781 }
782 }
783
784 err = zip_writer->FinishEntry();
785 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800786 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800787 return false;
788 }
789
790 return true;
791}
792
Felipe Leme71ca15e2016-05-19 16:18:17 -0700793bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700794 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
795 | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700796 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800797 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800798 return false;
799 }
800
801 return add_zip_entry_from_fd(entry_name, fd.get());
802}
803
804/* adds a file to the existing zipped bugreport */
805static int _add_file_from_fd(const char *title, const char *path, int fd) {
806 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
807}
808
Felipe Leme24b66ee2016-06-16 10:55:26 -0700809// TODO: move to util.cpp
Felipe Leme678727a2016-09-21 17:22:11 -0700810void add_dir(const std::string& dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800811 if (!zip_writer) {
Felipe Leme678727a2016-09-21 17:22:11 -0700812 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800813 return;
814 }
Felipe Leme678727a2016-09-21 17:22:11 -0700815 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
816 DurationReporter durationReporter(dir, nullptr);
817 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800818}
819
Felipe Leme809d74e2016-02-02 12:57:00 -0800820/* adds a text entry entry to the existing zip file. */
821static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800822 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800823 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 -0800824 return false;
825 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800826 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800827 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
828 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800829 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800830 ZipWriter::ErrorCodeString(err));
831 return false;
832 }
833
834 err = zip_writer->WriteBytes(content.c_str(), content.length());
835 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800836 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800837 ZipWriter::ErrorCodeString(err));
838 return false;
839 }
840
841 err = zip_writer->FinishEntry();
842 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800843 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800844 return false;
845 }
846
847 return true;
848}
849
Felipe Lemec0808152016-06-17 17:37:13 -0700850static void dump_iptables() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700851 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
852 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
853 RunCommand("IPTABLE NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700854 /* no ip6 nat */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700855 RunCommand("IPTABLE MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
856 RunCommand("IP6TABLE MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
857 RunCommand("IPTABLE RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
858 RunCommand("IP6TABLE RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700859}
860
Srinath Sridharanfdf52d32016-02-01 15:50:22 -0800861static void dumpstate(const std::string& screenshot_path, const std::string& version) {
Felipe Leme678727a2016-09-21 17:22:11 -0700862 DurationReporter durationReporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800863 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700864
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700865 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700866 RunCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -0700867 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800868 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700869 DumpFile("MEMORY INFO", "/proc/meminfo");
870 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700871 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700872 RunCommand("PROCRANK", {"procrank"}, CommandOptions::AS_ROOT_20);
873 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
874 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
875 DumpFile("SLAB INFO", "/proc/slabinfo");
876 DumpFile("ZONEINFO", "/proc/zoneinfo");
877 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
878 DumpFile("BUDDYINFO", "/proc/buddyinfo");
879 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700880
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700881 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
882 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
883 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700884
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700885 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700886 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700887 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT_10);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700888
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700889 RunCommand("PRINTENV", {"printenv"});
890 RunCommand("NETSTAT", {"netstat", "-n"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700891 struct stat s;
892 if (stat("/proc/modules", &s) != 0) {
893 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
894 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700895 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700896 }
Michal Karpinski4db754f2015-12-11 18:04:32 +0000897
Colin Crossf45fa6b2012-03-26 12:38:26 -0700898 do_dmesg();
899
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700900 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT_10);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700901 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
902 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800903 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700904
Ajay Panickerd886ec42016-09-14 12:26:46 -0700905 /* Dump Bluetooth HCI logs */
906 add_dir("/data/misc/bluetooth/logs", true);
907
Felipe Leme6e01fa62015-11-11 19:35:14 -0800908 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800909 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800910 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800911 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700912 }
913
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700914 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700915 // calculate timeout
916 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
917 if (timeout < 20000) {
918 timeout = 20000;
919 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700920 RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700921 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800922 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700923 if (timeout < 20000) {
924 timeout = 20000;
925 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700926 RunCommand("EVENT LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700927 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
928 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700929 timeout = logcat_timeout("radio");
930 if (timeout < 20000) {
931 timeout = 20000;
932 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700933 RunCommand("RADIO LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700934 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
935 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700936
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700937 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
Mark Salyzynecc07632015-07-30 14:57:09 -0700938
Colin Crossf45fa6b2012-03-26 12:38:26 -0700939 /* show the traces we collected in main(), if that was done */
940 if (dump_traces_path != NULL) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700941 DumpFile("VM TRACES JUST NOW", dump_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700942 }
943
944 /* only show ANR traces if they're less than 15 minutes old */
945 struct stat st;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700946 std::string anrTracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
947 if (anrTracesPath.empty()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700948 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700949 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700950 int fd = TEMP_FAILURE_RETRY(
951 open(anrTracesPath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
952 if (fd < 0) {
953 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anrTracesPath.c_str(), strerror(errno));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700954 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700955 dump_file_from_fd("VM TRACES AT LAST ANR", anrTracesPath.c_str(), fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700956 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700957 }
958
959 /* slow traces for slow operations */
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700960 if (!anrTracesPath.empty()) {
961 int tail = anrTracesPath.size() - 1;
962 while (tail > 0 && anrTracesPath.at(tail) != '/') {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700963 tail--;
964 }
965 int i = 0;
966 while (1) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700967 anrTracesPath =
968 anrTracesPath.substr(0, tail + 1) + android::base::StringPrintf("slow%02d.txt", i);
969 if (stat(anrTracesPath.c_str(), &st)) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700970 // No traces file at this index, done with the files.
971 break;
972 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700973 DumpFile("VM TRACES WHEN SLOW", anrTracesPath.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700974 i++;
975 }
976 }
977
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700978 int dumped = 0;
979 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
980 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800981 const char *name = tombstone_data[i].name;
982 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700983 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800984 if (zip_writer) {
985 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800986 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800987 }
988 } else {
989 dump_file_from_fd("TOMBSTONE", name, fd);
990 }
991 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700992 tombstone_data[i].fd = -1;
993 }
994 }
995 if (!dumped) {
996 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
997 }
998
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700999 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1000 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1001 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1002 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1003 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001004
Todd Poynor2a83daa2013-11-22 15:44:22 -08001005 if (!stat(PSTORE_LAST_KMSG, &st)) {
1006 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001007 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -07001008 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001009 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -08001010 } else {
1011 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001012 DumpFile("LAST KMSG", "/proc/last_kmsg");
Todd Poynor2a83daa2013-11-22 15:44:22 -08001013 }
1014
Mark Salyzyn2262c162014-12-16 09:09:26 -08001015 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001016 RunCommand("LAST LOGCAT",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001017 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
Mark Salyzyn2262c162014-12-16 09:09:26 -08001018
Colin Crossf45fa6b2012-03-26 12:38:26 -07001019 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -08001020
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001021 RunCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001022
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001023 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1024 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001025
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001026 RunCommand("IP RULES", {"ip", "rule", "show"});
1027 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001028
1029 dump_route_tables();
1030
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001031 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1032 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1033 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1034 RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001035 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001036
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001037#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001038 RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001039
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001040 RunCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001041
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001042 RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001043
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001044#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001045 DumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001046
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001047 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001048 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001049
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001050#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001051 RunCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001052
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001053 RunCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001054
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001055 RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001056#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001057 DumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001058
1059 print_properties();
1060
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001061 RunCommand("VOLD DUMP", {"vdc", "dump"});
1062 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001063
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001064 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001065
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001066 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001067
1068 printf("------ BACKLIGHTS ------\n");
1069 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001070 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001071 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001072 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001073 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001074 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001075 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001076 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001077 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001078 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001079 printf("\n");
1080
1081 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001082 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1083 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1084 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1085 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1086 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001087
Colin Crossf45fa6b2012-03-26 12:38:26 -07001088 printf("========================================================\n");
1089 printf("== Board\n");
1090 printf("========================================================\n");
1091
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001092 {
1093 DurationReporter tmpDr("dumpstate_board()");
1094 dumpstate_board();
1095 printf("\n");
1096 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001097
1098 /* Migrate the ril_dumpstate to a dumpstate_board()? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001099 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1100 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001101 // su does not exist on user builds, so try running without it.
1102 // This way any implementations of vril-dump that do not require
1103 // root can run on user builds.
1104 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001105 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Leme30dbfa12016-09-02 12:43:26 -07001106 if (!is_user_build()) {
1107 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001108 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001109 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001110 }
1111
1112 printf("========================================================\n");
1113 printf("== Android Framework Services\n");
1114 printf("========================================================\n");
1115
Felipe Leme5bcce572016-09-27 09:21:08 -07001116 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1117 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001118
1119 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001120 printf("== Checkins\n");
1121 printf("========================================================\n");
1122
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001123 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1124 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1125 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1126 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1127 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1128 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001129
1130 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001131 printf("== Running Application Activities\n");
1132 printf("========================================================\n");
1133
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001134 RunDumpsys("APP ACTIVITIES", {"activity", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001135
1136 printf("========================================================\n");
1137 printf("== Running Application Services\n");
1138 printf("========================================================\n");
1139
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001140 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001141
1142 printf("========================================================\n");
1143 printf("== Running Application Providers\n");
1144 printf("========================================================\n");
1145
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001146 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001147
1148 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001149 printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_,
1150 ds.weightTotal_, WEIGHT_TOTAL);
Felipe Leme608385d2016-02-01 10:35:38 -08001151 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001152 printf("== dumpstate: done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001153 printf("========================================================\n");
1154}
1155
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001156static void ShowUsageAndExit(int exitCode = 1) {
1157 fprintf(stderr,
1158 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1159 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1160 " -h: display this help message\n"
1161 " -b: play sound file instead of vibrate, at beginning of job\n"
1162 " -e: play sound file instead of vibrate, at end of job\n"
1163 " -o: write to file (instead of stdout)\n"
1164 " -d: append date to filename (requires -o)\n"
1165 " -p: capture screenshot to filename.png (requires -o)\n"
1166 " -z: generate zipped file (requires -o)\n"
1167 " -s: write output to control socket (for init)\n"
1168 " -S: write file location to control socket (for init; requires -o and -z)"
1169 " -q: disable vibrate\n"
1170 " -B: send broadcast when finished (requires -o)\n"
1171 " -P: send broadcast when started and update system properties on "
1172 "progress (requires -o and -B)\n"
1173 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1174 "shouldn't be used with -P)\n"
1175 " -V: sets the bugreport format version (valid values: %s)\n",
1176 VERSION_DEFAULT.c_str());
1177 exit(exitCode);
1178}
1179
1180static void ExitOnInvalidArgs() {
1181 fprintf(stderr, "invalid combination of args\n");
1182 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001183}
1184
Wei Liuf87959e2016-08-26 14:51:42 -07001185static void wake_lock_releaser() {
1186 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1187 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1188 } else {
1189 MYLOGD("Wake lock released.\n");
1190 }
1191}
1192
1193static void sig_handler(int signo) {
1194 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001195 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001196}
1197
Wei Liuf87959e2016-08-26 14:51:42 -07001198static void register_sig_handler() {
1199 struct sigaction sa;
1200 sigemptyset(&sa.sa_mask);
1201 sa.sa_flags = 0;
1202 sa.sa_handler = sig_handler;
1203 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1204 sigaction(SIGSEGV, &sa, NULL); // segment fault
1205 sigaction(SIGINT, &sa, NULL); // ctrl-c
1206 sigaction(SIGTERM, &sa, NULL); // killed
1207 sigaction(SIGQUIT, &sa, NULL); // quit
1208}
1209
Felipe Leme1e9edc62015-12-21 16:02:13 -08001210/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1211 temporary file.
1212 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001213static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001214 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001215 // Final timestamp
1216 char date[80];
1217 time_t the_real_now_please_stand_up = time(nullptr);
1218 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001219 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
1220 the_real_now_please_stand_up - now);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001221
Felipe Lemee82a27d2016-01-05 13:35:44 -08001222 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001223 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001224 return false;
1225 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001226 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001227 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001228 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001229 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001230
Felipe Leme0f3fb202016-06-10 17:10:53 -07001231 // Add log file (which contains stderr output) to zip...
1232 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1233 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1234 MYLOGE("Failed to add dumpstate log to .zip file\n");
1235 return false;
1236 }
1237 // ... and re-opens it for further logging.
1238 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1239 fprintf(stderr, "\n");
1240
Felipe Lemee82a27d2016-01-05 13:35:44 -08001241 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001242 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001243 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001244 return false;
1245 }
1246
Felipe Lemec4eee562016-04-21 15:42:55 -07001247 if (is_user_build()) {
1248 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1249 if (remove(bugreport_path.c_str())) {
1250 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1251 }
1252 } else {
1253 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1254 }
1255
Felipe Leme1e9edc62015-12-21 16:02:13 -08001256 return true;
1257}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001258
Michal Karpinski4db754f2015-12-11 18:04:32 +00001259static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001260 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1261 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001262 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001263 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001264 return NULL;
1265 }
1266
1267 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001268 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001269
1270 std::vector<uint8_t> buffer(65536);
1271 while (1) {
1272 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1273 if (bytes_read == 0) {
1274 break;
1275 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001276 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001277 return NULL;
1278 }
1279
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001280 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001281 }
1282
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001283 uint8_t hash[SHA256_DIGEST_LENGTH];
1284 SHA256_Final(hash, &ctx);
1285
1286 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1287 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001288 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001289 }
1290 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1291 return std::string(hash_buffer);
1292}
1293
Colin Crossf45fa6b2012-03-26 12:38:26 -07001294int main(int argc, char *argv[]) {
1295 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001296 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001297 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001298 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001299 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001300 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001301 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001302 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001303 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001304 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001305 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001306
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001307 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001308
Felipe Lemecbce55d2016-02-08 09:53:18 -08001309 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001310
Wei Liuf87959e2016-08-26 14:51:42 -07001311 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1312 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1313 } else {
1314 MYLOGD("Wake lock acquired.\n");
1315 atexit(wake_lock_releaser);
1316 register_sig_handler();
1317 }
1318
Felipe Lemee844a9d2016-09-21 15:01:39 -07001319 ds.dryRun_ = android::base::GetBoolProperty("dumpstate.dry_run", false);
1320 if (ds.dryRun_) {
Felipe Leme8268ed22016-08-02 18:18:25 -07001321 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1322 }
1323
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001324 // TODO: use helper function to convert argv into a string
Felipe Leme30dbfa12016-09-02 12:43:26 -07001325 for (int i = 0; i < argc; i++) {
1326 args += argv[i];
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001327 if (i < argc - 1) {
1328 args += " ";
1329 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001330 }
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001331
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001332 extraOptions = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1333 MYLOGI("Dumpstate args: %s (extra options: %s)\n", args.c_str(), extraOptions.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -07001334
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001335 /* gets the sequential id */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001336 int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemee844a9d2016-09-21 15:01:39 -07001337 ds.id_ = ++lastId;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001338 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001339 MYLOGI("dumpstate id: %lu\n", ds.id_);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001340
Colin Crossf45fa6b2012-03-26 12:38:26 -07001341 /* set as high priority, and protect from OOM killer */
1342 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001343
1344 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001345 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001346 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001347 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001348 } else {
1349 /* fallback to kernels <= 2.6.35 */
1350 oom_adj = fopen("/proc/self/oom_adj", "we");
1351 if (oom_adj) {
1352 fputs("-17", oom_adj);
1353 fclose(oom_adj);
1354 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001355 }
1356
Jeff Brown1dc94e32014-09-11 14:15:27 -07001357 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001358 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001359 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001360 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001361 // clang-format off
Felipe Leme71bbfc52015-11-23 14:14:51 -08001362 case 'd': do_add_date = 1; break;
1363 case 'z': do_zip_file = 1; break;
1364 case 'o': use_outfile = optarg; break;
1365 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001366 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001367 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001368 case 'q': do_vibrate = 0; break;
1369 case 'p': do_fb = 1; break;
Felipe Lemee844a9d2016-09-21 15:01:39 -07001370 case 'P': ds.updateProgress_ = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001371 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001372 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001373 case 'V': version = optarg; break;
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001374 case 'h':
1375 ShowUsageAndExit(0);
1376 break;
1377 default:
1378 fprintf(stderr, "Invalid option: %c\n", c);
1379 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001380 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001381 }
1382 }
1383
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001384 if (!extraOptions.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001385 // Framework uses a system property to override some command-line args.
1386 // Currently, it contains the type of the requested bugreport.
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001387 if (extraOptions == "bugreportplus") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001388 MYLOGD("Running as bugreportplus: add -P, remove -p\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001389 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001390 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001391 } else if (extraOptions == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001392 MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
1393 do_vibrate = 0;
1394 is_remote_mode = 1;
1395 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001396 } else if (extraOptions == "bugreportwear") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001397 MYLOGD("Running as bugreportwear: add -P\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001398 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001399 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001400 MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001401 }
1402 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001403 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001404 }
1405
Felipe Lemee844a9d2016-09-21 15:01:39 -07001406 if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001407 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001408 }
1409
Felipe Leme2628e9e2016-04-12 16:36:51 -07001410 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001411 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001412 }
1413
Felipe Lemee844a9d2016-09-21 15:01:39 -07001414 if (ds.updateProgress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001415 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001416 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001417
Felipe Lemee844a9d2016-09-21 15:01:39 -07001418 if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001419 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001420 }
1421
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001422 if (version != VERSION_DEFAULT) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001423 ShowUsageAndExit();
Felipe Leme809d74e2016-02-02 12:57:00 -08001424 }
1425
Felipe Lemecbce55d2016-02-08 09:53:18 -08001426 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001427
Felipe Lemee844a9d2016-09-21 15:01:39 -07001428 do_early_screenshot = ds.updateProgress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001429
Christopher Ferrised9354f2014-10-01 17:35:01 -07001430 // If we are going to use a socket, do it as early as possible
1431 // to avoid timeouts from bugreport.
1432 if (use_socket) {
1433 redirect_to_socket(stdout, "dumpstate");
1434 }
1435
Felipe Leme2628e9e2016-04-12 16:36:51 -07001436 if (use_control_socket) {
1437 MYLOGD("Opening control socket\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001438 ds.controlSocketFd_ = open_socket("dumpstate");
1439 ds.updateProgress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001440 }
1441
Felipe Lemecbce55d2016-02-08 09:53:18 -08001442 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001443 std::string tmp_path;
1444
Felipe Leme0f3fb202016-06-10 17:10:53 -07001445 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001446 std::string log_path;
1447
Felipe Leme14e034a2016-03-30 18:51:03 -07001448 /* full path of the systrace file, when enabled */
1449 std::string systrace_path;
1450
Felipe Lemee338bf62015-12-07 14:03:50 -08001451 /* full path of the temporary file containing the screenshot (when requested) */
1452 std::string screenshot_path;
1453
Felipe Lemecbce55d2016-02-08 09:53:18 -08001454 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001455 std::string base_name;
1456
Felipe Leme71bbfc52015-11-23 14:14:51 -08001457 /* pointer to the actual path, be it zip or text */
1458 std::string path;
1459
Felipe Leme635ca312016-01-05 14:23:02 -08001460 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001461 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001462
Felipe Lemead5f6c42015-11-30 14:26:46 -08001463 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001464 bool is_redirecting = !use_socket && use_outfile;
1465
1466 if (is_redirecting) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001467 ds.bugreportDir_ = dirname(use_outfile);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001468 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001469 if (do_add_date) {
1470 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001471 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1472 suffix = date;
1473 } else {
1474 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001475 }
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001476 std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1477 base_name = base_name + "-" + buildId;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001478 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001479 // TODO: if dumpstate was an object, the paths could be internal variables and then
1480 // we could have a function to calculate the derived values, such as:
1481 // screenshot_path = GetPath(".png");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001482 screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001483 }
Felipe Lemee844a9d2016-09-21 15:01:39 -07001484 tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
1485 log_path =
1486 ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001487
Felipe Lemee844a9d2016-09-21 15:01:39 -07001488 MYLOGD(
1489 "Bugreport dir: %s\n"
1490 "Base name: %s\n"
1491 "Suffix: %s\n"
1492 "Log path: %s\n"
1493 "Temporary path: %s\n"
1494 "Screenshot path: %s\n",
1495 ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
1496 tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001497
Felipe Leme1e9edc62015-12-21 16:02:13 -08001498 if (do_zip_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001499 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001500 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001501 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001502 zip_file.reset(fopen(path.c_str(), "wb"));
1503 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001504 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001505 do_zip_file = 0;
1506 } else {
1507 zip_writer.reset(new ZipWriter(zip_file.get()));
1508 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001509 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001510 }
1511
Felipe Lemee844a9d2016-09-21 15:01:39 -07001512 if (ds.updateProgress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001513 if (do_broadcast) {
1514 // clang-format off
1515 std::vector<std::string> am_args = {
1516 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1517 "--es", "android.intent.extra.NAME", suffix,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001518 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001519 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1520 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1521 };
1522 // clang-format on
1523 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1524 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001525 if (use_control_socket) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001526 dprintf(ds.controlSocketFd_, "BEGIN:%s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001527 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001528 }
1529 }
1530
Nick Kralevichf3599b32016-01-25 15:05:16 -08001531 /* read /proc/cmdline before dropping root */
1532 FILE *cmdline = fopen("/proc/cmdline", "re");
1533 if (cmdline) {
1534 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1535 fclose(cmdline);
1536 }
1537
Jeff Brown1dc94e32014-09-11 14:15:27 -07001538 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001539 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001540 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001541 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001542 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001543 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001544 }
John Michelau1f794c42012-09-17 11:20:19 -05001545 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001546
Felipe Leme3634a1e2015-12-09 10:11:47 -08001547 if (do_fb && do_early_screenshot) {
1548 if (screenshot_path.empty()) {
1549 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001550 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001551 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001552 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001553 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001554 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001555 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001556 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001557 screenshot_path.c_str(), strerror(errno));
1558 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001559 }
1560 }
1561
Felipe Leme1e9edc62015-12-21 16:02:13 -08001562 if (do_zip_file) {
1563 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001564 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001565 }
1566 }
1567
Felipe Leme71bbfc52015-11-23 14:14:51 -08001568 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001569 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001570 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1571 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1572 log_path.c_str(), strerror(errno));
1573 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001574 /* TODO: rather than generating a text file now and zipping it later,
1575 it would be more efficient to redirect stdout to the zip entry
1576 directly, but the libziparchive doesn't support that option yet. */
1577 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001578 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1579 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1580 tmp_path.c_str(), strerror(errno));
1581 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001582 }
Felipe Leme608385d2016-02-01 10:35:38 -08001583 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1584 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001585 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001586 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001587
Felipe Leme71a74ac2016-03-17 15:43:25 -07001588 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001589 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1590 // the raw trace.
1591 if (!dump_anrd_trace()) {
1592 dump_systrace();
1593 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001594
Felipe Leme9c74aad2016-02-29 18:15:42 -08001595 // Invoking the following dumpsys calls before dump_traces() to try and
1596 // keep the system stats as close to its initial state as possible.
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001597 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001598 CommandOptions::WithTimeout(90).DropRoot().Build());
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001599 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001600 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001601
Felipe Lemee844a9d2016-09-21 15:01:39 -07001602 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1603 dump_raft();
1604
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001605 /* collect stack traces from Dalvik and native processes (needs root) */
1606 dump_traces_path = dump_traces();
1607
Felipe Lemec0808152016-06-17 17:37:13 -07001608 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001609 get_tombstone_fds(tombstone_data);
1610 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001611 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001612 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001613 if (!is_user_build()) {
1614 add_dir(PROFILE_DATA_DIR_CUR, true);
1615 add_dir(PROFILE_DATA_DIR_REF, true);
1616 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001617 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001618 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001619
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001620 // Run ss as root so we can see socket marks.
1621 run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1622
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001623 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001624 return -1;
1625 }
1626
1627 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001628
Felipe Leme55b42a62015-11-10 17:39:08 -08001629 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001630 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001631 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001632 }
1633
Felipe Leme6e01fa62015-11-11 19:35:14 -08001634 /* rename or zip the (now complete) .tmp file to its final location */
1635 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001636
1637 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001638 std::string name = android::base::GetProperty(
1639 android::base::StringPrintf("dumpstate.%d.name", getpid()), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001640 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001641 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001642 /* must whitelist which characters are allowed, otherwise it could cross directories */
1643 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001644 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001645 change_suffix = true;
1646 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001647 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001648 }
1649 }
1650 if (change_suffix) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001651 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), name.c_str());
1652 suffix = name;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001653 if (!screenshot_path.empty()) {
1654 std::string new_screenshot_path =
Felipe Lemee844a9d2016-09-21 15:01:39 -07001655 ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Lemead5f6c42015-11-30 14:26:46 -08001656 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001657 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001658 new_screenshot_path.c_str(), strerror(errno));
1659 } else {
1660 screenshot_path = new_screenshot_path;
1661 }
1662 }
1663 }
1664
Felipe Leme6e01fa62015-11-11 19:35:14 -08001665 bool do_text_file = true;
1666 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001667 std::string entry_name = base_name + "-" + suffix + ".txt";
1668 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Leme0f3fb202016-06-10 17:10:53 -07001669 if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001670 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001671 do_text_file = true;
1672 } else {
1673 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001674 // Since zip file is already created, it needs to be renamed.
Felipe Lemee844a9d2016-09-21 15:01:39 -07001675 std::string new_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme91274352016-02-26 15:03:52 -08001676 if (path != new_path) {
1677 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1678 if (rename(path.c_str(), new_path.c_str())) {
1679 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1680 new_path.c_str(), strerror(errno));
1681 } else {
1682 path = new_path;
1683 }
1684 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001685 }
1686 }
1687 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001688 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001689 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001690 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001691 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001692 path.clear();
1693 }
1694 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001695 if (use_control_socket) {
1696 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001697 dprintf(ds.controlSocketFd_,
1698 "FAIL:could not create zip file, check %s "
1699 "for more details\n",
1700 log_path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001701 } else {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001702 dprintf(ds.controlSocketFd_, "OK:%s\n", path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001703 }
1704 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001705 }
1706
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001707 /* vibrate a few but shortly times to let user know it's finished */
1708 if (vibrator) {
1709 for (int i = 0; i < 3; i++) {
1710 vibrate(vibrator.get(), 75);
1711 usleep((75 + 50) * 1000);
1712 }
1713 }
1714
Jeff Brown1dc94e32014-09-11 14:15:27 -07001715 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001716 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001717 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001718 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001719 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001720 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001721 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001722 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001723 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemee844a9d2016-09-21 15:01:39 -07001724 "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001725 "--es", "android.intent.extra.BUGREPORT", path,
1726 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001727 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001728 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001729 if (do_fb) {
1730 am_args.push_back("--es");
1731 am_args.push_back("android.intent.extra.SCREENSHOT");
1732 am_args.push_back(screenshot_path);
1733 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001734 if (is_remote_mode) {
1735 am_args.push_back("--es");
1736 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1737 am_args.push_back(SHA256_file_hash(path));
1738 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1739 } else {
1740 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1741 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001742 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001743 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001744 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001745 }
1746
Felipe Lemee844a9d2016-09-21 15:01:39 -07001747 MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL);
1748 MYLOGI("done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001749
Felipe Leme107a05f2016-03-08 15:11:15 -08001750 if (is_redirecting) {
1751 fclose(stderr);
1752 }
1753
Felipe Lemee844a9d2016-09-21 15:01:39 -07001754 if (use_control_socket && ds.controlSocketFd_ != -1) {
1755 MYLOGD("Closing control socket\n");
1756 close(ds.controlSocketFd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001757 }
1758
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759 return 0;
1760}