blob: 1627ba8d3196311cac5592e3020db1c54edfd7ca [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
1156static void usage() {
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001157 fprintf(stderr,
Felipe Leme2628e9e2016-04-12 16:36:51 -07001158 "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"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001161 " -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"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001166 " -z: generate zipped file (requires -o)\n"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001167 " -s: write output to control socket (for init)\n"
Felipe Leme2628e9e2016-04-12 16:36:51 -07001168 " -S: write file location to control socket (for init; requires -o and -z)"
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001169 " -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());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001177}
1178
Wei Liuf87959e2016-08-26 14:51:42 -07001179static void wake_lock_releaser() {
1180 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1181 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1182 } else {
1183 MYLOGD("Wake lock released.\n");
1184 }
1185}
1186
1187static void sig_handler(int signo) {
1188 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001189 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001190}
1191
Wei Liuf87959e2016-08-26 14:51:42 -07001192static void register_sig_handler() {
1193 struct sigaction sa;
1194 sigemptyset(&sa.sa_mask);
1195 sa.sa_flags = 0;
1196 sa.sa_handler = sig_handler;
1197 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1198 sigaction(SIGSEGV, &sa, NULL); // segment fault
1199 sigaction(SIGINT, &sa, NULL); // ctrl-c
1200 sigaction(SIGTERM, &sa, NULL); // killed
1201 sigaction(SIGQUIT, &sa, NULL); // quit
1202}
1203
Felipe Leme1e9edc62015-12-21 16:02:13 -08001204/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1205 temporary file.
1206 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001207static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001208 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001209 // Final timestamp
1210 char date[80];
1211 time_t the_real_now_please_stand_up = time(nullptr);
1212 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001213 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
1214 the_real_now_please_stand_up - now);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001215
Felipe Lemee82a27d2016-01-05 13:35:44 -08001216 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001217 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001218 return false;
1219 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001220 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001221 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001222 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001223 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001224
Felipe Leme0f3fb202016-06-10 17:10:53 -07001225 // Add log file (which contains stderr output) to zip...
1226 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1227 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1228 MYLOGE("Failed to add dumpstate log to .zip file\n");
1229 return false;
1230 }
1231 // ... and re-opens it for further logging.
1232 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1233 fprintf(stderr, "\n");
1234
Felipe Lemee82a27d2016-01-05 13:35:44 -08001235 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001236 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001237 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001238 return false;
1239 }
1240
Felipe Lemec4eee562016-04-21 15:42:55 -07001241 if (is_user_build()) {
1242 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1243 if (remove(bugreport_path.c_str())) {
1244 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1245 }
1246 } else {
1247 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1248 }
1249
Felipe Leme1e9edc62015-12-21 16:02:13 -08001250 return true;
1251}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001252
Michal Karpinski4db754f2015-12-11 18:04:32 +00001253static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001254 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1255 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001256 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001257 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001258 return NULL;
1259 }
1260
1261 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001262 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001263
1264 std::vector<uint8_t> buffer(65536);
1265 while (1) {
1266 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1267 if (bytes_read == 0) {
1268 break;
1269 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001270 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001271 return NULL;
1272 }
1273
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001274 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001275 }
1276
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001277 uint8_t hash[SHA256_DIGEST_LENGTH];
1278 SHA256_Final(hash, &ctx);
1279
1280 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1281 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001282 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001283 }
1284 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1285 return std::string(hash_buffer);
1286}
1287
Colin Crossf45fa6b2012-03-26 12:38:26 -07001288int main(int argc, char *argv[]) {
1289 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001290 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001291 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001292 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001294 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001295 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001296 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001297 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001298 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001299 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001300
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001301 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001302
Felipe Lemecbce55d2016-02-08 09:53:18 -08001303 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001304
Wei Liuf87959e2016-08-26 14:51:42 -07001305 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1306 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1307 } else {
1308 MYLOGD("Wake lock acquired.\n");
1309 atexit(wake_lock_releaser);
1310 register_sig_handler();
1311 }
1312
Felipe Lemee844a9d2016-09-21 15:01:39 -07001313 ds.dryRun_ = android::base::GetBoolProperty("dumpstate.dry_run", false);
1314 if (ds.dryRun_) {
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;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001368 case '?': printf("\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001369 case 'h': usage(); exit(1);
1370 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001371 }
1372 }
1373
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001374 if (!extraOptions.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001375 // Framework uses a system property to override some command-line args.
1376 // Currently, it contains the type of the requested bugreport.
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001377 if (extraOptions == "bugreportplus") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001378 MYLOGD("Running as bugreportplus: add -P, remove -p\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001379 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001380 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001381 } else if (extraOptions == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001382 MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
1383 do_vibrate = 0;
1384 is_remote_mode = 1;
1385 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001386 } else if (extraOptions == "bugreportwear") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001387 MYLOGD("Running as bugreportwear: add -P\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001388 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001389 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001390 MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001391 }
1392 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001393 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001394 }
1395
Felipe Lemee844a9d2016-09-21 15:01:39 -07001396 if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001397 usage();
1398 exit(1);
1399 }
1400
Felipe Leme2628e9e2016-04-12 16:36:51 -07001401 if (use_control_socket && !do_zip_file) {
1402 usage();
1403 exit(1);
1404 }
1405
Felipe Lemee844a9d2016-09-21 15:01:39 -07001406 if (ds.updateProgress_ && !do_broadcast) {
Felipe Leme71bbfc52015-11-23 14:14:51 -08001407 usage();
1408 exit(1);
1409 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001410
Felipe Lemee844a9d2016-09-21 15:01:39 -07001411 if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Michal Karpinski4db754f2015-12-11 18:04:32 +00001412 usage();
1413 exit(1);
1414 }
1415
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001416 if (version != VERSION_DEFAULT) {
1417 usage();
1418 exit(1);
Felipe Leme809d74e2016-02-02 12:57:00 -08001419 }
1420
Felipe Lemecbce55d2016-02-08 09:53:18 -08001421 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001422
Felipe Lemee844a9d2016-09-21 15:01:39 -07001423 do_early_screenshot = ds.updateProgress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001424
Christopher Ferrised9354f2014-10-01 17:35:01 -07001425 // If we are going to use a socket, do it as early as possible
1426 // to avoid timeouts from bugreport.
1427 if (use_socket) {
1428 redirect_to_socket(stdout, "dumpstate");
1429 }
1430
Felipe Leme2628e9e2016-04-12 16:36:51 -07001431 if (use_control_socket) {
1432 MYLOGD("Opening control socket\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001433 ds.controlSocketFd_ = open_socket("dumpstate");
1434 ds.updateProgress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001435 }
1436
Felipe Lemecbce55d2016-02-08 09:53:18 -08001437 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001438 std::string tmp_path;
1439
Felipe Leme0f3fb202016-06-10 17:10:53 -07001440 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001441 std::string log_path;
1442
Felipe Leme14e034a2016-03-30 18:51:03 -07001443 /* full path of the systrace file, when enabled */
1444 std::string systrace_path;
1445
Felipe Lemee338bf62015-12-07 14:03:50 -08001446 /* full path of the temporary file containing the screenshot (when requested) */
1447 std::string screenshot_path;
1448
Felipe Lemecbce55d2016-02-08 09:53:18 -08001449 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001450 std::string base_name;
1451
Felipe Leme71bbfc52015-11-23 14:14:51 -08001452 /* pointer to the actual path, be it zip or text */
1453 std::string path;
1454
Felipe Leme635ca312016-01-05 14:23:02 -08001455 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001456 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001457
Felipe Lemead5f6c42015-11-30 14:26:46 -08001458 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001459 bool is_redirecting = !use_socket && use_outfile;
1460
1461 if (is_redirecting) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001462 ds.bugreportDir_ = dirname(use_outfile);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001463 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001464 if (do_add_date) {
1465 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001466 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1467 suffix = date;
1468 } else {
1469 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001470 }
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001471 std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1472 base_name = base_name + "-" + buildId;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001473 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001474 // TODO: if dumpstate was an object, the paths could be internal variables and then
1475 // we could have a function to calculate the derived values, such as:
1476 // screenshot_path = GetPath(".png");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001477 screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001478 }
Felipe Lemee844a9d2016-09-21 15:01:39 -07001479 tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
1480 log_path =
1481 ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001482
Felipe Lemee844a9d2016-09-21 15:01:39 -07001483 MYLOGD(
1484 "Bugreport dir: %s\n"
1485 "Base name: %s\n"
1486 "Suffix: %s\n"
1487 "Log path: %s\n"
1488 "Temporary path: %s\n"
1489 "Screenshot path: %s\n",
1490 ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
1491 tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001492
Felipe Leme1e9edc62015-12-21 16:02:13 -08001493 if (do_zip_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001494 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001495 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001496 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001497 zip_file.reset(fopen(path.c_str(), "wb"));
1498 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001499 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001500 do_zip_file = 0;
1501 } else {
1502 zip_writer.reset(new ZipWriter(zip_file.get()));
1503 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001504 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001505 }
1506
Felipe Lemee844a9d2016-09-21 15:01:39 -07001507 if (ds.updateProgress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001508 if (do_broadcast) {
1509 // clang-format off
1510 std::vector<std::string> am_args = {
1511 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1512 "--es", "android.intent.extra.NAME", suffix,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001513 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001514 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1515 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1516 };
1517 // clang-format on
1518 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1519 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001520 if (use_control_socket) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001521 dprintf(ds.controlSocketFd_, "BEGIN:%s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001522 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001523 }
1524 }
1525
Nick Kralevichf3599b32016-01-25 15:05:16 -08001526 /* read /proc/cmdline before dropping root */
1527 FILE *cmdline = fopen("/proc/cmdline", "re");
1528 if (cmdline) {
1529 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1530 fclose(cmdline);
1531 }
1532
Jeff Brown1dc94e32014-09-11 14:15:27 -07001533 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001534 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001535 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001536 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001537 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001538 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001539 }
John Michelau1f794c42012-09-17 11:20:19 -05001540 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001541
Felipe Leme3634a1e2015-12-09 10:11:47 -08001542 if (do_fb && do_early_screenshot) {
1543 if (screenshot_path.empty()) {
1544 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001545 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001546 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001547 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001548 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001549 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001550 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001551 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001552 screenshot_path.c_str(), strerror(errno));
1553 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001554 }
1555 }
1556
Felipe Leme1e9edc62015-12-21 16:02:13 -08001557 if (do_zip_file) {
1558 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001559 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001560 }
1561 }
1562
Felipe Leme71bbfc52015-11-23 14:14:51 -08001563 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001564 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001565 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1566 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1567 log_path.c_str(), strerror(errno));
1568 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001569 /* TODO: rather than generating a text file now and zipping it later,
1570 it would be more efficient to redirect stdout to the zip entry
1571 directly, but the libziparchive doesn't support that option yet. */
1572 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001573 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1574 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1575 tmp_path.c_str(), strerror(errno));
1576 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001577 }
Felipe Leme608385d2016-02-01 10:35:38 -08001578 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1579 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001580 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001581 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001582
Felipe Leme71a74ac2016-03-17 15:43:25 -07001583 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001584 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1585 // the raw trace.
1586 if (!dump_anrd_trace()) {
1587 dump_systrace();
1588 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001589
Felipe Leme9c74aad2016-02-29 18:15:42 -08001590 // Invoking the following dumpsys calls before dump_traces() to try and
1591 // keep the system stats as close to its initial state as possible.
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001592 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001593 CommandOptions::WithTimeout(90).DropRoot().Build());
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001594 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001595 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001596
Felipe Lemee844a9d2016-09-21 15:01:39 -07001597 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1598 dump_raft();
1599
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001600 /* collect stack traces from Dalvik and native processes (needs root) */
1601 dump_traces_path = dump_traces();
1602
Felipe Lemec0808152016-06-17 17:37:13 -07001603 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001604 get_tombstone_fds(tombstone_data);
1605 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001606 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001607 add_dir(LOGPERSIST_DATA_DIR, false);
David Brazdild2991962016-06-03 14:40:44 +01001608 if (!is_user_build()) {
1609 add_dir(PROFILE_DATA_DIR_CUR, true);
1610 add_dir(PROFILE_DATA_DIR_REF, true);
1611 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001612 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001613 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001614
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001615 // Run ss as root so we can see socket marks.
1616 run_command("DETAILED SOCKET STATE", 10, "ss", "-eionptu", NULL);
1617
Felipe Lemecf6a8b42016-03-11 10:38:19 -08001618 if (!drop_root_user()) {
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001619 return -1;
1620 }
1621
1622 dumpstate(do_early_screenshot ? "": screenshot_path, version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001623
Felipe Leme55b42a62015-11-10 17:39:08 -08001624 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001625 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001626 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001627 }
1628
Felipe Leme6e01fa62015-11-11 19:35:14 -08001629 /* rename or zip the (now complete) .tmp file to its final location */
1630 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001631
1632 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001633 std::string name = android::base::GetProperty(
1634 android::base::StringPrintf("dumpstate.%d.name", getpid()), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001635 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001636 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001637 /* must whitelist which characters are allowed, otherwise it could cross directories */
1638 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001639 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001640 change_suffix = true;
1641 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001642 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001643 }
1644 }
1645 if (change_suffix) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001646 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), name.c_str());
1647 suffix = name;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001648 if (!screenshot_path.empty()) {
1649 std::string new_screenshot_path =
Felipe Lemee844a9d2016-09-21 15:01:39 -07001650 ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Lemead5f6c42015-11-30 14:26:46 -08001651 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001652 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
Felipe Lemead5f6c42015-11-30 14:26:46 -08001653 new_screenshot_path.c_str(), strerror(errno));
1654 } else {
1655 screenshot_path = new_screenshot_path;
1656 }
1657 }
1658 }
1659
Felipe Leme6e01fa62015-11-11 19:35:14 -08001660 bool do_text_file = true;
1661 if (do_zip_file) {
Felipe Leme88c79332016-02-22 11:06:49 -08001662 std::string entry_name = base_name + "-" + suffix + ".txt";
1663 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
Felipe Leme0f3fb202016-06-10 17:10:53 -07001664 if (!finish_zip_file(entry_name, tmp_path, log_path, now)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001665 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001666 do_text_file = true;
1667 } else {
1668 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001669 // Since zip file is already created, it needs to be renamed.
Felipe Lemee844a9d2016-09-21 15:01:39 -07001670 std::string new_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme91274352016-02-26 15:03:52 -08001671 if (path != new_path) {
1672 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
1673 if (rename(path.c_str(), new_path.c_str())) {
1674 MYLOGE("rename(%s, %s): %s\n", path.c_str(),
1675 new_path.c_str(), strerror(errno));
1676 } else {
1677 path = new_path;
1678 }
1679 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001680 }
1681 }
1682 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001683 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".txt";
Felipe Leme88c79332016-02-22 11:06:49 -08001684 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001685 if (rename(tmp_path.c_str(), path.c_str())) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001686 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
Felipe Leme6e01fa62015-11-11 19:35:14 -08001687 path.clear();
1688 }
1689 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001690 if (use_control_socket) {
1691 if (do_text_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001692 dprintf(ds.controlSocketFd_,
1693 "FAIL:could not create zip file, check %s "
1694 "for more details\n",
1695 log_path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001696 } else {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001697 dprintf(ds.controlSocketFd_, "OK:%s\n", path.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001698 }
1699 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001700 }
1701
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001702 /* vibrate a few but shortly times to let user know it's finished */
1703 if (vibrator) {
1704 for (int i = 0; i < 3; i++) {
1705 vibrate(vibrator.get(), 75);
1706 usleep((75 + 50) * 1000);
1707 }
1708 }
1709
Jeff Brown1dc94e32014-09-11 14:15:27 -07001710 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001711 if (do_broadcast) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001712 if (!path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001713 MYLOGI("Final bugreport path: %s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001714 // clang-format off
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001715 std::vector<std::string> am_args = {
Felipe Leme43fd1bb2016-01-29 09:07:57 -08001716 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001717 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme71bbfc52015-11-23 14:14:51 -08001718 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
Felipe Lemee844a9d2016-09-21 15:01:39 -07001719 "--ei", "android.intent.extra.MAX", std::to_string(ds.weightTotal_),
Felipe Lemecbce55d2016-02-08 09:53:18 -08001720 "--es", "android.intent.extra.BUGREPORT", path,
1721 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001722 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001723 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001724 if (do_fb) {
1725 am_args.push_back("--es");
1726 am_args.push_back("android.intent.extra.SCREENSHOT");
1727 am_args.push_back(screenshot_path);
1728 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001729 if (is_remote_mode) {
1730 am_args.push_back("--es");
1731 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
1732 am_args.push_back(SHA256_file_hash(path));
1733 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
1734 } else {
1735 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
1736 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001737 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001738 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001739 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001740 }
1741
Felipe Lemee844a9d2016-09-21 15:01:39 -07001742 MYLOGD("Final progress: %d/%d (originally %d)\n", ds.progress_, ds.weightTotal_, WEIGHT_TOTAL);
1743 MYLOGI("done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001744
Felipe Leme107a05f2016-03-08 15:11:15 -08001745 if (is_redirecting) {
1746 fclose(stderr);
1747 }
1748
Felipe Lemee844a9d2016-09-21 15:01:39 -07001749 if (use_control_socket && ds.controlSocketFd_ != -1) {
1750 MYLOGD("Closing control socket\n");
1751 close(ds.controlSocketFd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001752 }
1753
Colin Crossf45fa6b2012-03-26 12:38:26 -07001754 return 0;
1755}