blob: 32dbf8d617fd690831258ae4901a8a1ce157d153 [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
Colin Crossf45fa6b2012-03-26 12:38:26 -070055/* read before root is shed */
56static char cmdline_buf[16384] = "(unknown)";
57static const char *dump_traces_path = NULL;
58
Felipe Leme9ce6aa42016-09-21 10:02:25 -070059// Command-line arguments as string
60static std::string args;
61
Felipe Lemeefd7e272016-05-18 09:27:16 -070062// TODO: variables below should be part of dumpstate object
Felipe Lemee82a27d2016-01-05 13:35:44 -080063static time_t now;
64static std::unique_ptr<ZipWriter> zip_writer;
Felipe Leme635ca312016-01-05 14:23:02 -080065static std::set<std::string> mount_points;
66void add_mountinfo();
Felipe Lemeefd7e272016-05-18 09:27:16 -070067/* suffix of the bugreport files - it's typically the date (when invoked with -d),
68 * although it could be changed by the user using a system property */
69static std::string suffix;
Felipe Leme96c2bbb2016-09-26 09:21:21 -070070static std::string extraOptions;
Felipe Leme78f2c862015-12-21 09:55:22 -080071
Todd Poynor2a83daa2013-11-22 15:44:22 -080072#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070073#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Todd Poynor2a83daa2013-11-22 15:44:22 -080074
Wei Liu341938b2016-04-27 16:18:17 -070075#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080076#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070077#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070078#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010079#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
80#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070081#define TOMBSTONE_DIR "/data/tombstones"
82#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
83/* Can accomodate a tombstone number up to 9999. */
84#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
85#define NUM_TOMBSTONES 10
Erik Kline08165202016-05-30 11:55:44 +090086#define WLUTIL "/vendor/xbin/wlutil"
Wei Liuf87959e2016-08-26 14:51:42 -070087#define WAKE_LOCK_NAME "dumpstate_wakelock"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070088
89typedef struct {
90 char name[TOMBSTONE_MAX_LEN];
91 int fd;
92} tombstone_data_t;
93
94static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
95
Felipe Lemee844a9d2016-09-21 15:01:39 -070096// TODO: temporary variables and functions used during C++ refactoring
97static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -070098static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
99 const CommandOptions& options = CommandOptions::DEFAULT) {
100 return ds.RunCommand(title, fullCommand, options);
101}
102static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
103 const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
104 long dumpsysTimeout = 0) {
105 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
106}
107static int DumpFile(const std::string& title, const std::string& path) {
108 return ds.DumpFile(title, path);
109}
Felipe Leme6ad9c062016-09-28 11:58:36 -0700110bool IsUserBuild() {
111 return ds.IsUserBuild();
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
Felipe Leme3d305a12016-05-20 11:24:37 -0700127/* gets the tombstone data, according to the bugreport type: if zipped, gets all tombstones;
128 * otherwise, gets just those modified in the last half an hour. */
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700129static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800130 time_t thirty_minutes_ago = now - 60*30;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700131 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
132 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
Christopher Ferris54bcc5f2015-02-10 12:15:01 -0800133 int fd = TEMP_FAILURE_RETRY(open(data[i].name,
134 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700135 struct stat st;
Felipe Leme3d305a12016-05-20 11:24:37 -0700136 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && st.st_size > 0 &&
Felipe Lemee82a27d2016-01-05 13:35:44 -0800137 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
Felipe Leme3d305a12016-05-20 11:24:37 -0700138 data[i].fd = fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700139 } else {
Felipe Leme3d305a12016-05-20 11:24:37 -0700140 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700141 data[i].fd = -1;
142 }
143 }
144}
145
Felipe Leme635ca312016-01-05 14:23:02 -0800146// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700147void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800148 char path[PATH_MAX];
149
150 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
151 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700152 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800153 char linkname[PATH_MAX];
154 ssize_t r = readlink(path, linkname, PATH_MAX);
155 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800156 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800157 return;
158 }
159 linkname[r] = '\0';
160
161 if (mount_points.find(linkname) == mount_points.end()) {
162 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700163 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800164 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
165 mount_points.insert(linkname);
166 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800167 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800168 }
169 }
170}
171
172void add_mountinfo() {
173 if (!zip_writer) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700174 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800175 mount_points.clear();
Felipe Leme678727a2016-09-21 17:22:11 -0700176 DurationReporter durationReporter(title, nullptr);
177 for_each_pid(do_mountinfo, nullptr);
178 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800179}
180
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700181static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
182{
183 DIR *d;
184 struct dirent *de;
185 char path[PATH_MAX];
186
187 d = opendir(driverpath);
188 if (d == NULL) {
189 return;
190 }
191
192 while ((de = readdir(d))) {
193 if (de->d_type != DT_LNK) {
194 continue;
195 }
196 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700197 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700198 }
199
200 closedir(d);
201}
202
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700203// return pid of a userspace process. If not found or error, return 0.
204static unsigned int pid_of_process(const char* ps_name) {
205 DIR *proc_dir;
206 struct dirent *ps;
207 unsigned int pid;
208 std::string cmdline;
209
210 if (!(proc_dir = opendir("/proc"))) {
211 MYLOGE("Can't open /proc\n");
212 return 0;
213 }
214
215 while ((ps = readdir(proc_dir))) {
216 if (!(pid = atoi(ps->d_name))) {
217 continue;
218 }
219 android::base::ReadFileToString("/proc/"
220 + std::string(ps->d_name) + "/cmdline", &cmdline);
221 if (cmdline.find(ps_name) == std::string::npos) {
222 continue;
223 } else {
224 closedir(proc_dir);
225 return pid;
226 }
227 }
228 closedir(proc_dir);
229 return 0;
230}
231
232// dump anrd's trace and add to the zip file.
233// 1. check if anrd is running on this device.
234// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
235// 3. wait until the trace generation completes and add to the zip file.
236static bool dump_anrd_trace() {
237 unsigned int pid;
238 char buf[50], path[PATH_MAX];
239 struct dirent *trace;
240 struct stat st;
241 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700242 int retry = 5;
243 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700244 long long cur_size = 0;
245 const char *trace_path = "/data/misc/anrd/";
246
247 if (!zip_writer) {
248 MYLOGE("Not dumping anrd trace because zip_writer is not set\n");
249 return false;
250 }
251
252 // find anrd's pid if it is running.
253 pid = pid_of_process("/system/xbin/anrd");
254
255 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700256 if (stat(trace_path, &st) == 0) {
257 old_mtime = st.st_mtime;
258 } else {
259 MYLOGE("Failed to find: %s\n", trace_path);
260 return false;
261 }
262
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700263 // send SIGUSR1 to the anrd to generate a trace.
264 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700265 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700266 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700267 MYLOGE("anrd signal timed out. Please manually collect trace\n");
268 return false;
269 }
270
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700271 while (retry-- > 0 && old_mtime == st.st_mtime) {
272 sleep(1);
273 stat(trace_path, &st);
274 }
275
276 if (retry < 0 && old_mtime == st.st_mtime) {
277 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
278 return false;
279 }
280
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700281 // identify the trace file by its creation time.
282 if (!(trace_dir = opendir(trace_path))) {
283 MYLOGE("Can't open trace file under %s\n", trace_path);
284 }
285 while ((trace = readdir(trace_dir))) {
286 if (strcmp(trace->d_name, ".") == 0
287 || strcmp(trace->d_name, "..") == 0) {
288 continue;
289 }
290 sprintf(path, "%s%s", trace_path, trace->d_name);
291 if (stat(path, &st) == 0) {
292 if (st.st_ctime > max_ctime) {
293 max_ctime = st.st_ctime;
294 sprintf(buf, "%s", trace->d_name);
295 }
296 }
297 }
298 closedir(trace_dir);
299
300 // Wait until the dump completes by checking the size of the trace.
301 if (max_ctime > 0) {
302 sprintf(path, "%s%s", trace_path, buf);
303 while(true) {
304 sleep(1);
305 if (stat(path, &st) == 0) {
306 if (st.st_size == cur_size) {
307 break;
308 } else if (st.st_size > cur_size) {
309 cur_size = st.st_size;
310 } else {
311 return false;
312 }
313 } else {
314 MYLOGE("Cant stat() %s anymore\n", path);
315 return false;
316 }
317 }
318 // Add to the zip file.
319 if (!add_zip_entry("anrd_trace.txt", path)) {
320 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
321 } else {
322 if (remove(path)) {
323 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
324 }
325 return true;
326 }
327 } else {
328 MYLOGE("Can't stats any trace file under %s\n", trace_path);
329 }
330 }
331 return false;
332}
333
Felipe Lemeefd7e272016-05-18 09:27:16 -0700334static void dump_systrace() {
Felipe Leme71a74ac2016-03-17 15:43:25 -0700335 if (!zip_writer) {
336 MYLOGD("Not dumping systrace because zip_writer is not set\n");
337 return;
338 }
Felipe Lemee844a9d2016-09-21 15:01:39 -0700339 std::string systrace_path = ds.bugreportDir_ + "/systrace-" + suffix + ".txt";
Felipe Leme14e034a2016-03-30 18:51:03 -0700340 if (systrace_path.empty()) {
341 MYLOGE("Not dumping systrace because path is empty\n");
342 return;
343 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700344 const char* path = "/sys/kernel/debug/tracing/tracing_on";
345 long int is_tracing;
346 if (read_file_as_long(path, &is_tracing)) {
347 return; // error already logged
348 }
349 if (is_tracing <= 0) {
350 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
351 return;
352 }
353
Felipe Leme14e034a2016-03-30 18:51:03 -0700354 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
355 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700356 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700357 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700358 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700359 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700360 // peacefully; ideally, we should call strace to stop itself, but there is no such option
361 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700362 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700363 // MYLOGE("could not stop systrace ");
364 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700365 }
366 if (!add_zip_entry("systrace.txt", systrace_path)) {
367 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700368 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700369 if (remove(systrace_path.c_str())) {
370 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
371 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700372 }
373}
374
Felipe Lemeefd7e272016-05-18 09:27:16 -0700375static void dump_raft() {
Felipe Leme6ad9c062016-09-28 11:58:36 -0700376 if (IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700377 return;
378 }
379
Felipe Lemee844a9d2016-09-21 15:01:39 -0700380 std::string raft_log_path = ds.bugreportDir_ + "/raft_log.txt";
Wei Liu341938b2016-04-27 16:18:17 -0700381 if (raft_log_path.empty()) {
382 MYLOGD("raft_log_path is empty\n");
383 return;
384 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700385
386 struct stat s;
387 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
388 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
389 return;
390 }
391
Felipe Leme30dbfa12016-09-02 12:43:26 -0700392 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Wei Liu341938b2016-04-27 16:18:17 -0700393 if (!zip_writer) {
Wei Liu310525a2016-05-25 11:28:57 -0700394 // Write compressed and encoded raft logs to stdout if not zip_writer.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700395 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700396 return;
397 }
398
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700399 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_log_path}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700400 if (!add_zip_entry("raft_log.txt", raft_log_path)) {
401 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str());
402 } else {
403 if (remove(raft_log_path.c_str())) {
Felipe Lemeefd7e272016-05-18 09:27:16 -0700404 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700405 }
406 }
407}
408
Mark Salyzyn326842f2015-04-30 09:49:41 -0700409static bool skip_not_stat(const char *path) {
410 static const char stat[] = "/stat";
411 size_t len = strlen(path);
412 if (path[len - 1] == '/') { /* Directory? */
413 return false;
414 }
415 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
416}
417
Felipe Leme4c2d6632016-09-28 14:32:00 -0700418static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800419 return false;
420}
421
Mark Salyzyn326842f2015-04-30 09:49:41 -0700422static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700423unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700424
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800425//
426// stat offsets
427// Name units description
428// ---- ----- -----------
429// read I/Os requests number of read I/Os processed
430#define __STAT_READ_IOS 0
431// read merges requests number of read I/Os merged with in-queue I/O
432#define __STAT_READ_MERGES 1
433// read sectors sectors number of sectors read
434#define __STAT_READ_SECTORS 2
435// read ticks milliseconds total wait time for read requests
436#define __STAT_READ_TICKS 3
437// write I/Os requests number of write I/Os processed
438#define __STAT_WRITE_IOS 4
439// write merges requests number of write I/Os merged with in-queue I/O
440#define __STAT_WRITE_MERGES 5
441// write sectors sectors number of sectors written
442#define __STAT_WRITE_SECTORS 6
443// write ticks milliseconds total wait time for write requests
444#define __STAT_WRITE_TICKS 7
445// in_flight requests number of I/Os currently in flight
446#define __STAT_IN_FLIGHT 8
447// io_ticks milliseconds total time this block device has been active
448#define __STAT_IO_TICKS 9
449// time_in_queue milliseconds total wait time for all requests
450#define __STAT_IN_QUEUE 10
451#define __STAT_NUMBER_FIELD 11
452//
453// read I/Os, write I/Os
454// =====================
455//
456// These values increment when an I/O request completes.
457//
458// read merges, write merges
459// =========================
460//
461// These values increment when an I/O request is merged with an
462// already-queued I/O request.
463//
464// read sectors, write sectors
465// ===========================
466//
467// These values count the number of sectors read from or written to this
468// block device. The "sectors" in question are the standard UNIX 512-byte
469// sectors, not any device- or filesystem-specific block size. The
470// counters are incremented when the I/O completes.
471#define SECTOR_SIZE 512
472//
473// read ticks, write ticks
474// =======================
475//
476// These values count the number of milliseconds that I/O requests have
477// waited on this block device. If there are multiple I/O requests waiting,
478// these values will increase at a rate greater than 1000/second; for
479// example, if 60 read requests wait for an average of 30 ms, the read_ticks
480// field will increase by 60*30 = 1800.
481//
482// in_flight
483// =========
484//
485// This value counts the number of I/O requests that have been issued to
486// the device driver but have not yet completed. It does not include I/O
487// requests that are in the queue but not yet issued to the device driver.
488//
489// io_ticks
490// ========
491//
492// This value counts the number of milliseconds during which the device has
493// had I/O requests queued.
494//
495// time_in_queue
496// =============
497//
498// This value counts the number of milliseconds that I/O requests have waited
499// on this block device. If there are multiple I/O requests waiting, this
500// value will increase as the product of the number of milliseconds times the
501// number of requests waiting (see "read ticks" above for an example).
502#define S_TO_MS 1000
503//
504
Mark Salyzyn326842f2015-04-30 09:49:41 -0700505static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800506 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700507 bool z;
508 char *cp, *buffer = NULL;
509 size_t i = 0;
510 FILE *fp = fdopen(fd, "rb");
511 getline(&buffer, &i, fp);
512 fclose(fp);
513 if (!buffer) {
514 return -errno;
515 }
516 i = strlen(buffer);
517 while ((i > 0) && (buffer[i - 1] == '\n')) {
518 buffer[--i] = '\0';
519 }
520 if (!*buffer) {
521 free(buffer);
522 return 0;
523 }
524 z = true;
525 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800526 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700527 if (fields[i] != 0) {
528 z = false;
529 }
530 }
531 if (z) { /* never accessed */
532 free(buffer);
533 return 0;
534 }
535
536 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
537 path += sizeof(mmcblk0) - 1;
538 }
539
540 printf("%s: %s\n", path, buffer);
541 free(buffer);
542
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800543 if (fields[__STAT_IO_TICKS]) {
544 unsigned long read_perf = 0;
545 unsigned long read_ios = 0;
546 if (fields[__STAT_READ_TICKS]) {
547 unsigned long long divisor = fields[__STAT_READ_TICKS]
548 * fields[__STAT_IO_TICKS];
549 read_perf = ((unsigned long long)SECTOR_SIZE
550 * fields[__STAT_READ_SECTORS]
551 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
552 / divisor;
553 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
554 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
555 / divisor;
556 }
557
558 unsigned long write_perf = 0;
559 unsigned long write_ios = 0;
560 if (fields[__STAT_WRITE_TICKS]) {
561 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
562 * fields[__STAT_IO_TICKS];
563 write_perf = ((unsigned long long)SECTOR_SIZE
564 * fields[__STAT_WRITE_SECTORS]
565 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
566 / divisor;
567 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
568 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
569 / divisor;
570 }
571
572 unsigned queue = (fields[__STAT_IN_QUEUE]
573 + (fields[__STAT_IO_TICKS] >> 1))
574 / fields[__STAT_IO_TICKS];
575
576 if (!write_perf && !write_ios) {
577 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
578 path, read_perf, read_ios, queue);
579 } else {
580 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
581 path, read_perf, read_ios, write_perf, write_ios, queue);
582 }
583
584 /* bugreport timeout factor adjustment */
585 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
586 worst_write_perf = write_perf;
587 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700588 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700589 return 0;
590}
591
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700592/* Copied policy from system/core/logd/LogBuffer.cpp */
593
594#define LOG_BUFFER_SIZE (256 * 1024)
595#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
596#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
597
598static bool valid_size(unsigned long value) {
599 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
600 return false;
601 }
602
603 long pages = sysconf(_SC_PHYS_PAGES);
604 if (pages < 1) {
605 return true;
606 }
607
608 long pagesize = sysconf(_SC_PAGESIZE);
609 if (pagesize <= 1) {
610 pagesize = PAGE_SIZE;
611 }
612
613 // maximum memory impact a somewhat arbitrary ~3%
614 pages = (pages + 31) / 32;
615 unsigned long maximum = pages * pagesize;
616
617 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
618 return true;
619 }
620
621 return value <= maximum;
622}
623
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700624// TODO: migrate to logd/LogBuffer.cpp or use android::base::GetProperty
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700625static unsigned long property_get_size(const char *key) {
626 unsigned long value;
627 char *cp, property[PROPERTY_VALUE_MAX];
628
629 property_get(key, property, "");
630 value = strtoul(property, &cp, 10);
631
632 switch(*cp) {
633 case 'm':
634 case 'M':
635 value *= 1024;
636 /* FALLTHRU */
637 case 'k':
638 case 'K':
639 value *= 1024;
640 /* FALLTHRU */
641 case '\0':
642 break;
643
644 default:
645 value = 0;
646 }
647
648 if (!valid_size(value)) {
649 value = 0;
650 }
651
652 return value;
653}
654
655/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800656static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700657 static const char global_tuneable[] = "persist.logd.size"; // Settings App
658 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk
659 char key[PROP_NAME_MAX];
660 unsigned long property_size, default_size;
661
662 default_size = property_get_size(global_tuneable);
663 if (!default_size) {
664 default_size = property_get_size(global_default);
665 }
666
667 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
668 property_size = property_get_size(key);
669
670 if (!property_size) {
671 snprintf(key, sizeof(key), "%s.%s", global_default, name);
672 property_size = property_get_size(key);
673 }
674
675 if (!property_size) {
676 property_size = default_size;
677 }
678
679 if (!property_size) {
680 property_size = LOG_BUFFER_SIZE;
681 }
682
683 /* Engineering margin is ten-fold our guess */
684 return 10 * (property_size + worst_write_perf) / worst_write_perf;
685}
686
687/* End copy from system/core/logd/LogBuffer.cpp */
688
Colin Crossf45fa6b2012-03-26 12:38:26 -0700689/* dumps the current system state to stdout */
Felipe Lemee844a9d2016-09-21 15:01:39 -0700690void print_header(const std::string& version) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700691 std::string build, fingerprint, radio, bootloader, network;
692 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700693
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700694 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
695 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700696 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
697 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
698 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700699 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
700
701 printf("========================================================\n");
702 printf("== dumpstate: %s\n", date);
703 printf("========================================================\n");
704
705 printf("\n");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700706 printf("Build: %s\n", build.c_str());
707 // NOTE: fingerprint entry format is important for other tools.
708 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
709 printf("Bootloader: %s\n", bootloader.c_str());
710 printf("Radio: %s\n", radio.c_str());
711 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700712
713 printf("Kernel: ");
Felipe Leme678727a2016-09-21 17:22:11 -0700714 DumpFile("", "/proc/version");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700715 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
Felipe Leme809d74e2016-02-02 12:57:00 -0800716 printf("Bugreport format version: %s\n", version.c_str());
Felipe Lemee844a9d2016-09-21 15:01:39 -0700717 printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
Felipe Leme4c2d6632016-09-28 14:32:00 -0700718 ds.IsDryRun(), args.c_str(), extraOptions.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700719 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800720}
721
Felipe Leme24b66ee2016-06-16 10:55:26 -0700722// List of file extensions that can cause a zip file attachment to be rejected by some email
723// service providers.
724static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
725 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
726 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
727 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
728};
729
Felipe Leme71ca15e2016-05-19 16:18:17 -0700730bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800731 if (!zip_writer) {
Felipe Leme88c79332016-02-22 11:06:49 -0800732 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
733 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800734 return false;
735 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700736 std::string valid_name = entry_name;
737
738 // Rename extension if necessary.
739 size_t idx = entry_name.rfind(".");
740 if (idx != std::string::npos) {
741 std::string extension = entry_name.substr(idx);
742 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
743 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
744 valid_name = entry_name + ".renamed";
745 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
746 }
747 }
748
Felipe Leme6fe9db62016-02-12 09:04:16 -0800749 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
750 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Leme24b66ee2016-06-16 10:55:26 -0700751 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(),
Felipe Lemee82a27d2016-01-05 13:35:44 -0800752 ZipWriter::kCompress, get_mtime(fd, now));
753 if (err) {
Felipe Leme24b66ee2016-06-16 10:55:26 -0700754 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800755 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800756 return false;
757 }
758
Felipe Leme770410d2016-01-26 17:07:14 -0800759 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800760 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400761 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800762 if (bytes_read == 0) {
763 break;
764 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800765 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800766 return false;
767 }
768 err = zip_writer->WriteBytes(buffer.data(), bytes_read);
769 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800770 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800771 return false;
772 }
773 }
774
775 err = zip_writer->FinishEntry();
776 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800777 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800778 return false;
779 }
780
781 return true;
782}
783
Felipe Leme71ca15e2016-05-19 16:18:17 -0700784bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -0700785 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
786 | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700787 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800788 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800789 return false;
790 }
791
792 return add_zip_entry_from_fd(entry_name, fd.get());
793}
794
795/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700796static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800797 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
798}
799
Felipe Leme24b66ee2016-06-16 10:55:26 -0700800// TODO: move to util.cpp
Felipe Leme678727a2016-09-21 17:22:11 -0700801void add_dir(const std::string& dir, bool recursive) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800802 if (!zip_writer) {
Felipe Leme678727a2016-09-21 17:22:11 -0700803 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800804 return;
805 }
Felipe Leme678727a2016-09-21 17:22:11 -0700806 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
807 DurationReporter durationReporter(dir, nullptr);
808 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800809}
810
Felipe Leme809d74e2016-02-02 12:57:00 -0800811/* adds a text entry entry to the existing zip file. */
812static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
Felipe Leme111b9d02016-02-03 09:28:24 -0800813 if (!zip_writer) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800814 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 -0800815 return false;
816 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800817 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -0800818 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
819 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800820 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800821 ZipWriter::ErrorCodeString(err));
822 return false;
823 }
824
825 err = zip_writer->WriteBytes(content.c_str(), content.length());
826 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800827 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme809d74e2016-02-02 12:57:00 -0800828 ZipWriter::ErrorCodeString(err));
829 return false;
830 }
831
832 err = zip_writer->FinishEntry();
833 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800834 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800835 return false;
836 }
837
838 return true;
839}
840
Felipe Lemec0808152016-06-17 17:37:13 -0700841static void dump_iptables() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700842 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
843 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900844 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700845 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900846 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
847 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
848 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
849 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700850}
851
Felipe Leme4c2d6632016-09-28 14:32:00 -0700852static void dumpstate(const std::string& screenshot_path,
853 const std::string& version __attribute__((unused))) {
Felipe Leme678727a2016-09-21 17:22:11 -0700854 DurationReporter durationReporter("DUMPSTATE");
Felipe Leme78f2c862015-12-21 09:55:22 -0800855 unsigned long timeout;
Colin Crossf45fa6b2012-03-26 12:38:26 -0700856
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700857 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700858 RunCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -0700859 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -0800860 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700861 DumpFile("MEMORY INFO", "/proc/meminfo");
862 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700863 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700864 RunCommand("PROCRANK", {"procrank"}, CommandOptions::AS_ROOT_20);
865 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
866 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
867 DumpFile("SLAB INFO", "/proc/slabinfo");
868 DumpFile("ZONEINFO", "/proc/zoneinfo");
869 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
870 DumpFile("BUDDYINFO", "/proc/buddyinfo");
871 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700872
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700873 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
874 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
875 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700876
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700877 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700878 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700879 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT_10);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700880
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700881 RunCommand("PRINTENV", {"printenv"});
882 RunCommand("NETSTAT", {"netstat", "-n"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700883 struct stat s;
884 if (stat("/proc/modules", &s) != 0) {
885 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
886 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700887 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -0700888 }
Michal Karpinski4db754f2015-12-11 18:04:32 +0000889
Colin Crossf45fa6b2012-03-26 12:38:26 -0700890 do_dmesg();
891
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700892 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT_10);
Jeff Brown1dc94e32014-09-11 14:15:27 -0700893 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
894 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -0800895 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700896
Ajay Panickerd886ec42016-09-14 12:26:46 -0700897 /* Dump Bluetooth HCI logs */
898 add_dir("/data/misc/bluetooth/logs", true);
899
Felipe Leme6e01fa62015-11-11 19:35:14 -0800900 if (!screenshot_path.empty()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800901 MYLOGI("taking late screenshot\n");
Felipe Lemee338bf62015-12-07 14:03:50 -0800902 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -0800903 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Jeff Sharkey5a930032013-03-19 15:05:19 -0700904 }
905
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700906 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700907 // calculate timeout
908 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
909 if (timeout < 20000) {
910 timeout = 20000;
911 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700912 RunCommand("SYSTEM LOG", {"logcat", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700913 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn43afe5d2016-01-26 07:24:08 -0800914 timeout = logcat_timeout("events");
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700915 if (timeout < 20000) {
916 timeout = 20000;
917 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700918 RunCommand("EVENT LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700919 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
920 CommandOptions::WithTimeout(timeout / 1000).Build());
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700921 timeout = logcat_timeout("radio");
922 if (timeout < 20000) {
923 timeout = 20000;
924 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700925 RunCommand("RADIO LOG",
Felipe Leme30dbfa12016-09-02 12:43:26 -0700926 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-d", "*:v"},
927 CommandOptions::WithTimeout(timeout / 1000).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700928
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700929 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
Mark Salyzynecc07632015-07-30 14:57:09 -0700930
Colin Crossf45fa6b2012-03-26 12:38:26 -0700931 /* show the traces we collected in main(), if that was done */
932 if (dump_traces_path != NULL) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700933 DumpFile("VM TRACES JUST NOW", dump_traces_path);
Colin Crossf45fa6b2012-03-26 12:38:26 -0700934 }
935
936 /* only show ANR traces if they're less than 15 minutes old */
937 struct stat st;
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700938 std::string anrTracesPath = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
939 if (anrTracesPath.empty()) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700940 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700941 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700942 int fd = TEMP_FAILURE_RETRY(
943 open(anrTracesPath.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
944 if (fd < 0) {
945 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anrTracesPath.c_str(), strerror(errno));
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700946 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700947 dump_file_from_fd("VM TRACES AT LAST ANR", anrTracesPath.c_str(), fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700948 }
Colin Crossf45fa6b2012-03-26 12:38:26 -0700949 }
950
951 /* slow traces for slow operations */
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700952 if (!anrTracesPath.empty()) {
953 int tail = anrTracesPath.size() - 1;
954 while (tail > 0 && anrTracesPath.at(tail) != '/') {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700955 tail--;
956 }
957 int i = 0;
958 while (1) {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700959 anrTracesPath =
960 anrTracesPath.substr(0, tail + 1) + android::base::StringPrintf("slow%02d.txt", i);
961 if (stat(anrTracesPath.c_str(), &st)) {
Colin Crossf45fa6b2012-03-26 12:38:26 -0700962 // No traces file at this index, done with the files.
963 break;
964 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700965 DumpFile("VM TRACES WHEN SLOW", anrTracesPath.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700966 i++;
967 }
968 }
969
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700970 int dumped = 0;
971 for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
972 if (tombstone_data[i].fd != -1) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800973 const char *name = tombstone_data[i].name;
974 int fd = tombstone_data[i].fd;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700975 dumped = 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800976 if (zip_writer) {
977 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800978 MYLOGE("Unable to add tombstone %s to zip file\n", name);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800979 }
980 } else {
981 dump_file_from_fd("TOMBSTONE", name, fd);
982 }
983 close(fd);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700984 tombstone_data[i].fd = -1;
985 }
986 }
987 if (!dumped) {
988 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
989 }
990
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700991 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
992 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
993 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
994 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
995 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700996
Todd Poynor2a83daa2013-11-22 15:44:22 -0800997 if (!stat(PSTORE_LAST_KMSG, &st)) {
998 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700999 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
Mark Salyzyn7d0a7622016-06-24 14:06:15 -07001000 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001001 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
Todd Poynor2a83daa2013-11-22 15:44:22 -08001002 } else {
1003 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001004 DumpFile("LAST KMSG", "/proc/last_kmsg");
Todd Poynor2a83daa2013-11-22 15:44:22 -08001005 }
1006
Mark Salyzyn2262c162014-12-16 09:09:26 -08001007 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001008 RunCommand("LAST LOGCAT",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001009 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-d", "*:v"});
Mark Salyzyn2262c162014-12-16 09:09:26 -08001010
Colin Crossf45fa6b2012-03-26 12:38:26 -07001011 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -08001012
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001013 RunCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001014
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001015 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1016 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001017
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001018 RunCommand("IP RULES", {"ip", "rule", "show"});
1019 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001020
1021 dump_route_tables();
1022
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001023 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1024 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1025 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1026 RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001027 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001028
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001029#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001030 RunCommand("ND OFFLOAD TABLE", {WLUTIL, "nd_hostip"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001031
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001032 RunCommand("DUMP WIFI INTERNAL COUNTERS (1)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001033
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001034 RunCommand("ND OFFLOAD STATUS (1)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001035
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001036#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001037 DumpFile("INTERRUPTS (1)", "/proc/interrupts");
Dmitry Shmidt0b2c9262012-11-07 11:09:46 -08001038
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001039 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001040 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001041
Dmitry Shmidtc11f56e2012-11-07 10:42:05 -08001042#ifdef FWDUMP_bcmdhd
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001043 RunCommand("DUMP WIFI STATUS", {"dhdutil", "-i", "wlan0", "dump"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001044
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001045 RunCommand("DUMP WIFI INTERNAL COUNTERS (2)", {WLUTIL, "counters"}, CommandOptions::AS_ROOT_20);
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001046
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001047 RunCommand("ND OFFLOAD STATUS (2)", {WLUTIL, "nd_status"}, CommandOptions::AS_ROOT_5);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001048#endif
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001049 DumpFile("INTERRUPTS (2)", "/proc/interrupts");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001050
1051 print_properties();
1052
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001053 RunCommand("VOLD DUMP", {"vdc", "dump"});
1054 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001055
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001056 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001057
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001058 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001059
1060 printf("------ BACKLIGHTS ------\n");
1061 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001062 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001063 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001064 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001065 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001066 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001067 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001068 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001069 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001070 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001071 printf("\n");
1072
1073 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001074 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1075 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1076 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1077 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1078 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001079
Colin Crossf45fa6b2012-03-26 12:38:26 -07001080 printf("========================================================\n");
1081 printf("== Board\n");
1082 printf("========================================================\n");
1083
Felipe Leme0bcc7ca2016-09-13 16:45:56 -07001084 {
1085 DurationReporter tmpDr("dumpstate_board()");
1086 dumpstate_board();
1087 printf("\n");
1088 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001089
1090 /* Migrate the ril_dumpstate to a dumpstate_board()? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001091 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1092 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001093 // su does not exist on user builds, so try running without it.
1094 // This way any implementations of vril-dump that do not require
1095 // root can run on user builds.
1096 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001097 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001098 if (!IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001099 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001100 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001101 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001102 }
1103
1104 printf("========================================================\n");
1105 printf("== Android Framework Services\n");
1106 printf("========================================================\n");
1107
Felipe Leme5bcce572016-09-27 09:21:08 -07001108 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1109 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001110
1111 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001112 printf("== Checkins\n");
1113 printf("========================================================\n");
1114
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001115 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1116 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1117 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1118 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1119 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1120 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001121
1122 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001123 printf("== Running Application Activities\n");
1124 printf("========================================================\n");
1125
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001126 RunDumpsys("APP ACTIVITIES", {"activity", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001127
1128 printf("========================================================\n");
1129 printf("== Running Application Services\n");
1130 printf("========================================================\n");
1131
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001132 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001133
1134 printf("========================================================\n");
1135 printf("== Running Application Providers\n");
1136 printf("========================================================\n");
1137
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001138 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001139
1140 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001141 printf("== Final progress (pid %d): %d/%d (originally %d)\n", getpid(), ds.progress_,
1142 ds.weightTotal_, WEIGHT_TOTAL);
Felipe Leme608385d2016-02-01 10:35:38 -08001143 printf("========================================================\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001144 printf("== dumpstate: done (id %lu)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001145 printf("========================================================\n");
1146}
1147
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001148static void ShowUsageAndExit(int exitCode = 1) {
1149 fprintf(stderr,
1150 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
1151 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1152 " -h: display this help message\n"
1153 " -b: play sound file instead of vibrate, at beginning of job\n"
1154 " -e: play sound file instead of vibrate, at end of job\n"
1155 " -o: write to file (instead of stdout)\n"
1156 " -d: append date to filename (requires -o)\n"
1157 " -p: capture screenshot to filename.png (requires -o)\n"
1158 " -z: generate zipped file (requires -o)\n"
1159 " -s: write output to control socket (for init)\n"
1160 " -S: write file location to control socket (for init; requires -o and -z)"
1161 " -q: disable vibrate\n"
1162 " -B: send broadcast when finished (requires -o)\n"
1163 " -P: send broadcast when started and update system properties on "
1164 "progress (requires -o and -B)\n"
1165 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1166 "shouldn't be used with -P)\n"
1167 " -V: sets the bugreport format version (valid values: %s)\n",
1168 VERSION_DEFAULT.c_str());
1169 exit(exitCode);
1170}
1171
1172static void ExitOnInvalidArgs() {
1173 fprintf(stderr, "invalid combination of args\n");
1174 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001175}
1176
Wei Liuf87959e2016-08-26 14:51:42 -07001177static void wake_lock_releaser() {
1178 if (release_wake_lock(WAKE_LOCK_NAME) < 0) {
1179 MYLOGE("Failed to release wake lock: %s \n", strerror(errno));
1180 } else {
1181 MYLOGD("Wake lock released.\n");
1182 }
1183}
1184
Felipe Leme4c2d6632016-09-28 14:32:00 -07001185static void sig_handler(int signo __attribute__((unused))) {
Wei Liuf87959e2016-08-26 14:51:42 -07001186 wake_lock_releaser();
Andres Morales2e671bb2014-08-21 12:38:22 -07001187 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001188}
1189
Wei Liuf87959e2016-08-26 14:51:42 -07001190static void register_sig_handler() {
1191 struct sigaction sa;
1192 sigemptyset(&sa.sa_mask);
1193 sa.sa_flags = 0;
1194 sa.sa_handler = sig_handler;
1195 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1196 sigaction(SIGSEGV, &sa, NULL); // segment fault
1197 sigaction(SIGINT, &sa, NULL); // ctrl-c
1198 sigaction(SIGTERM, &sa, NULL); // killed
1199 sigaction(SIGQUIT, &sa, NULL); // quit
1200}
1201
Felipe Leme1e9edc62015-12-21 16:02:13 -08001202/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
1203 temporary file.
1204 */
Felipe Lemee82a27d2016-01-05 13:35:44 -08001205static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001206 const std::string& log_path, time_t now) {
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001207 // Final timestamp
1208 char date[80];
1209 time_t the_real_now_please_stand_up = time(nullptr);
1210 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001211 MYLOGD("dumpstate id %lu finished around %s (%ld s)\n", ds.id_, date,
1212 the_real_now_please_stand_up - now);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001213
Felipe Lemee82a27d2016-01-05 13:35:44 -08001214 if (!add_zip_entry(bugreport_name, bugreport_path)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001215 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001216 return false;
1217 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001218 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001219 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001220 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001221 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001222
Felipe Leme0f3fb202016-06-10 17:10:53 -07001223 // Add log file (which contains stderr output) to zip...
1224 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
1225 if (!add_zip_entry("dumpstate_log.txt", log_path.c_str())) {
1226 MYLOGE("Failed to add dumpstate log to .zip file\n");
1227 return false;
1228 }
1229 // ... and re-opens it for further logging.
1230 redirect_to_existing_file(stderr, const_cast<char*>(log_path.c_str()));
1231 fprintf(stderr, "\n");
1232
Felipe Lemee82a27d2016-01-05 13:35:44 -08001233 int32_t err = zip_writer->Finish();
Felipe Leme1e9edc62015-12-21 16:02:13 -08001234 if (err) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001235 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001236 return false;
1237 }
1238
Felipe Leme6ad9c062016-09-28 11:58:36 -07001239 if (IsUserBuild()) {
Felipe Lemec4eee562016-04-21 15:42:55 -07001240 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
1241 if (remove(bugreport_path.c_str())) {
1242 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
1243 }
1244 } else {
1245 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
1246 }
1247
Felipe Leme1e9edc62015-12-21 16:02:13 -08001248 return true;
1249}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001250
Michal Karpinski4db754f2015-12-11 18:04:32 +00001251static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001252 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1253 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001254 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001255 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001256 return NULL;
1257 }
1258
1259 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001260 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001261
1262 std::vector<uint8_t> buffer(65536);
1263 while (1) {
1264 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1265 if (bytes_read == 0) {
1266 break;
1267 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001268 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001269 return NULL;
1270 }
1271
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001272 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001273 }
1274
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001275 uint8_t hash[SHA256_DIGEST_LENGTH];
1276 SHA256_Final(hash, &ctx);
1277
1278 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1279 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001280 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001281 }
1282 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1283 return std::string(hash_buffer);
1284}
1285
Colin Crossf45fa6b2012-03-26 12:38:26 -07001286int main(int argc, char *argv[]) {
1287 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001288 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001289 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001290 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001291 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001292 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001293 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001294 int do_broadcast = 0;
Felipe Lemee338bf62015-12-07 14:03:50 -08001295 int do_early_screenshot = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001296 int is_remote_mode = 0;
Felipe Leme809d74e2016-02-02 12:57:00 -08001297 std::string version = VERSION_DEFAULT;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001298
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001299 now = time(nullptr);
Felipe Lemee82a27d2016-01-05 13:35:44 -08001300
Felipe Lemecbce55d2016-02-08 09:53:18 -08001301 MYLOGI("begin\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001302
Wei Liuf87959e2016-08-26 14:51:42 -07001303 if (acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME) < 0) {
1304 MYLOGE("Failed to acquire wake lock: %s \n", strerror(errno));
1305 } else {
1306 MYLOGD("Wake lock acquired.\n");
1307 atexit(wake_lock_releaser);
1308 register_sig_handler();
1309 }
1310
Felipe Leme4c2d6632016-09-28 14:32:00 -07001311 if (ds.IsDryRun()) {
Felipe Leme8268ed22016-08-02 18:18:25 -07001312 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1313 }
1314
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001315 // TODO: use helper function to convert argv into a string
Felipe Leme30dbfa12016-09-02 12:43:26 -07001316 for (int i = 0; i < argc; i++) {
1317 args += argv[i];
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001318 if (i < argc - 1) {
1319 args += " ";
1320 }
Felipe Leme30dbfa12016-09-02 12:43:26 -07001321 }
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001322
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001323 extraOptions = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
1324 MYLOGI("Dumpstate args: %s (extra options: %s)\n", args.c_str(), extraOptions.c_str());
Felipe Leme30dbfa12016-09-02 12:43:26 -07001325
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001326 /* gets the sequential id */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001327 int lastId = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemee844a9d2016-09-21 15:01:39 -07001328 ds.id_ = ++lastId;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001329 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(lastId));
Felipe Lemee844a9d2016-09-21 15:01:39 -07001330 MYLOGI("dumpstate id: %lu\n", ds.id_);
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001331
Colin Crossf45fa6b2012-03-26 12:38:26 -07001332 /* set as high priority, and protect from OOM killer */
1333 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001334
1335 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001336 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001337 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001338 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001339 } else {
1340 /* fallback to kernels <= 2.6.35 */
1341 oom_adj = fopen("/proc/self/oom_adj", "we");
1342 if (oom_adj) {
1343 fputs("-17", oom_adj);
1344 fclose(oom_adj);
1345 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001346 }
1347
Jeff Brown1dc94e32014-09-11 14:15:27 -07001348 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001349 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001350 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001351 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001352 // clang-format off
Felipe Leme71bbfc52015-11-23 14:14:51 -08001353 case 'd': do_add_date = 1; break;
1354 case 'z': do_zip_file = 1; break;
1355 case 'o': use_outfile = optarg; break;
1356 case 's': use_socket = 1; break;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001357 case 'S': use_control_socket = 1; break;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001358 case 'v': break; // compatibility no-op
Felipe Leme71bbfc52015-11-23 14:14:51 -08001359 case 'q': do_vibrate = 0; break;
1360 case 'p': do_fb = 1; break;
Felipe Lemee844a9d2016-09-21 15:01:39 -07001361 case 'P': ds.updateProgress_ = 1; break;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001362 case 'R': is_remote_mode = 1; break;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001363 case 'B': do_broadcast = 1; break;
Felipe Leme809d74e2016-02-02 12:57:00 -08001364 case 'V': version = optarg; break;
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001365 case 'h':
1366 ShowUsageAndExit(0);
1367 break;
1368 default:
1369 fprintf(stderr, "Invalid option: %c\n", c);
1370 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001371 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001372 }
1373 }
1374
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001375 if (!extraOptions.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001376 // Framework uses a system property to override some command-line args.
1377 // Currently, it contains the type of the requested bugreport.
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001378 if (extraOptions == "bugreportplus") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001379 MYLOGD("Running as bugreportplus: add -P, remove -p\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001380 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001381 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001382 } else if (extraOptions == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001383 MYLOGD("Running as bugreportremote: add -q -R, remove -p\n");
1384 do_vibrate = 0;
1385 is_remote_mode = 1;
1386 do_fb = 0;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001387 } else if (extraOptions == "bugreportwear") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001388 MYLOGD("Running as bugreportwear: add -P\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001389 ds.updateProgress_ = 1;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001390 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001391 MYLOGE("Unknown extra option: %s\n", extraOptions.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001392 }
1393 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001394 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001395 }
1396
Felipe Lemee844a9d2016-09-21 15:01:39 -07001397 if ((do_zip_file || do_add_date || ds.updateProgress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001398 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001399 }
1400
Felipe Leme2628e9e2016-04-12 16:36:51 -07001401 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001402 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001403 }
1404
Felipe Lemee844a9d2016-09-21 15:01:39 -07001405 if (ds.updateProgress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001406 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001407 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001408
Felipe Lemee844a9d2016-09-21 15:01:39 -07001409 if (is_remote_mode && (ds.updateProgress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001410 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001411 }
1412
Felipe Lemecc37b8e2016-04-11 13:45:18 -07001413 if (version != VERSION_DEFAULT) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001414 ShowUsageAndExit();
Felipe Leme809d74e2016-02-02 12:57:00 -08001415 }
1416
Felipe Lemecbce55d2016-02-08 09:53:18 -08001417 MYLOGI("bugreport format version: %s\n", version.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001418
Felipe Lemee844a9d2016-09-21 15:01:39 -07001419 do_early_screenshot = ds.updateProgress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001420
Christopher Ferrised9354f2014-10-01 17:35:01 -07001421 // If we are going to use a socket, do it as early as possible
1422 // to avoid timeouts from bugreport.
1423 if (use_socket) {
1424 redirect_to_socket(stdout, "dumpstate");
1425 }
1426
Felipe Leme2628e9e2016-04-12 16:36:51 -07001427 if (use_control_socket) {
1428 MYLOGD("Opening control socket\n");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001429 ds.controlSocketFd_ = open_socket("dumpstate");
1430 ds.updateProgress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001431 }
1432
Felipe Lemecbce55d2016-02-08 09:53:18 -08001433 /* full path of the temporary file containing the bugreport */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001434 std::string tmp_path;
1435
Felipe Leme0f3fb202016-06-10 17:10:53 -07001436 /* full path of the file containing the dumpstate logs */
Felipe Lemecbce55d2016-02-08 09:53:18 -08001437 std::string log_path;
1438
Felipe Leme14e034a2016-03-30 18:51:03 -07001439 /* full path of the systrace file, when enabled */
1440 std::string systrace_path;
1441
Felipe Lemee338bf62015-12-07 14:03:50 -08001442 /* full path of the temporary file containing the screenshot (when requested) */
1443 std::string screenshot_path;
1444
Felipe Lemecbce55d2016-02-08 09:53:18 -08001445 /* base name (without suffix or extensions) of the bugreport files */
Felipe Lemead5f6c42015-11-30 14:26:46 -08001446 std::string base_name;
1447
Felipe Leme71bbfc52015-11-23 14:14:51 -08001448 /* pointer to the actual path, be it zip or text */
1449 std::string path;
1450
Felipe Leme635ca312016-01-05 14:23:02 -08001451 /* pointer to the zipped file */
Felipe Leme1e9edc62015-12-21 16:02:13 -08001452 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001453
Felipe Lemead5f6c42015-11-30 14:26:46 -08001454 /* redirect output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001455 bool is_redirecting = !use_socket && use_outfile;
1456
1457 if (is_redirecting) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001458 ds.bugreportDir_ = dirname(use_outfile);
Felipe Lemead5f6c42015-11-30 14:26:46 -08001459 base_name = basename(use_outfile);
Felipe Leme71bbfc52015-11-23 14:14:51 -08001460 if (do_add_date) {
1461 char date[80];
Felipe Lemead5f6c42015-11-30 14:26:46 -08001462 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
1463 suffix = date;
1464 } else {
1465 suffix = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001466 }
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001467 std::string buildId = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
1468 base_name = base_name + "-" + buildId;
Felipe Leme71bbfc52015-11-23 14:14:51 -08001469 if (do_fb) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001470 // TODO: if dumpstate was an object, the paths could be internal variables and then
1471 // we could have a function to calculate the derived values, such as:
1472 // screenshot_path = GetPath(".png");
Felipe Lemee844a9d2016-09-21 15:01:39 -07001473 screenshot_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".png";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001474 }
Felipe Lemee844a9d2016-09-21 15:01:39 -07001475 tmp_path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".tmp";
1476 log_path =
1477 ds.bugreportDir_ + "/dumpstate_log-" + suffix + "-" + std::to_string(getpid()) + ".txt";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001478
Felipe Lemee844a9d2016-09-21 15:01:39 -07001479 MYLOGD(
1480 "Bugreport dir: %s\n"
1481 "Base name: %s\n"
1482 "Suffix: %s\n"
1483 "Log path: %s\n"
1484 "Temporary path: %s\n"
1485 "Screenshot path: %s\n",
1486 ds.bugreportDir_.c_str(), base_name.c_str(), suffix.c_str(), log_path.c_str(),
1487 tmp_path.c_str(), screenshot_path.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001488
Felipe Leme1e9edc62015-12-21 16:02:13 -08001489 if (do_zip_file) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001490 path = ds.bugreportDir_ + "/" + base_name + "-" + suffix + ".zip";
Felipe Leme26bd34c2016-03-15 13:40:33 -07001491 MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -08001492 create_parent_dirs(path.c_str());
Felipe Leme1e9edc62015-12-21 16:02:13 -08001493 zip_file.reset(fopen(path.c_str(), "wb"));
1494 if (!zip_file) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001495 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001496 do_zip_file = 0;
1497 } else {
1498 zip_writer.reset(new ZipWriter(zip_file.get()));
1499 }
Felipe Leme809d74e2016-02-02 12:57:00 -08001500 add_text_zip_entry("version.txt", version);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001501 }
1502
Felipe Lemee844a9d2016-09-21 15:01:39 -07001503 if (ds.updateProgress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001504 if (do_broadcast) {
1505 // clang-format off
1506 std::vector<std::string> am_args = {
1507 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
1508 "--es", "android.intent.extra.NAME", suffix,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001509 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001510 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
1511 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
1512 };
1513 // clang-format on
1514 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
1515 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001516 if (use_control_socket) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001517 dprintf(ds.controlSocketFd_, "BEGIN:%s\n", path.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001518 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001519 }
1520 }
1521
Nick Kralevichf3599b32016-01-25 15:05:16 -08001522 /* read /proc/cmdline before dropping root */
1523 FILE *cmdline = fopen("/proc/cmdline", "re");
1524 if (cmdline) {
1525 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1526 fclose(cmdline);
1527 }
1528
Jeff Brown1dc94e32014-09-11 14:15:27 -07001529 /* open the vibrator before dropping root */
Felipe Leme6e01fa62015-11-11 19:35:14 -08001530 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
John Michelau1f794c42012-09-17 11:20:19 -05001531 if (do_vibrate) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001532 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
Jeff Brown1dc94e32014-09-11 14:15:27 -07001533 if (vibrator) {
Felipe Leme6e01fa62015-11-11 19:35:14 -08001534 vibrate(vibrator.get(), 150);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001535 }
John Michelau1f794c42012-09-17 11:20:19 -05001536 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001537
Felipe Leme3634a1e2015-12-09 10:11:47 -08001538 if (do_fb && do_early_screenshot) {
1539 if (screenshot_path.empty()) {
1540 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001541 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001542 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001543 MYLOGI("taking early screenshot\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001544 take_screenshot(screenshot_path);
Felipe Lemecbce55d2016-02-08 09:53:18 -08001545 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
Felipe Leme3634a1e2015-12-09 10:11:47 -08001546 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001547 MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
Felipe Leme3634a1e2015-12-09 10:11:47 -08001548 screenshot_path.c_str(), strerror(errno));
1549 }
Felipe Lemee338bf62015-12-07 14:03:50 -08001550 }
1551 }
1552
Felipe Leme1e9edc62015-12-21 16:02:13 -08001553 if (do_zip_file) {
1554 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001555 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001556 }
1557 }
1558
Felipe Leme71bbfc52015-11-23 14:14:51 -08001559 if (is_redirecting) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001560 redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001561 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
1562 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1563 log_path.c_str(), strerror(errno));
1564 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001565 /* TODO: rather than generating a text file now and zipping it later,
1566 it would be more efficient to redirect stdout to the zip entry
1567 directly, but the libziparchive doesn't support that option yet. */
1568 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001569 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
1570 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
1571 tmp_path.c_str(), strerror(errno));
1572 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001573 }
Felipe Leme608385d2016-02-01 10:35:38 -08001574 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1575 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001576 // duration is logged into MYLOG instead.
Felipe Leme809d74e2016-02-02 12:57:00 -08001577 print_header(version);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001578
Felipe Leme71a74ac2016-03-17 15:43:25 -07001579 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001580 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1581 // the raw trace.
1582 if (!dump_anrd_trace()) {
1583 dump_systrace();
1584 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001585
Felipe Leme9c74aad2016-02-29 18:15:42 -08001586 // Invoking the following dumpsys calls before dump_traces() to try and
1587 // keep the system stats as close to its initial state as possible.
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001588 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001589 CommandOptions::WithTimeout(90).DropRoot().Build());
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001590 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001591 CommandOptions::WithTimeout(10).DropRoot().Build());
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001592
Felipe Lemee844a9d2016-09-21 15:01:39 -07001593 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1594 dump_raft();
1595
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001596 /* collect stack traces from Dalvik and native processes (needs root) */
1597 dump_traces_path = dump_traces();
1598
Felipe Lemec0808152016-06-17 17:37:13 -07001599 /* Run some operations that require root. */
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001600 get_tombstone_fds(tombstone_data);
1601 add_dir(RECOVERY_DIR, true);
Mark Salyzynd6ab0112016-03-25 12:56:39 -07001602 add_dir(RECOVERY_DATA_DIR, true);
Mark Salyzyn4d42dea2016-04-01 10:03:14 -07001603 add_dir(LOGPERSIST_DATA_DIR, false);
Felipe Leme6ad9c062016-09-28 11:58:36 -07001604 if (!IsUserBuild()) {
David Brazdild2991962016-06-03 14:40:44 +01001605 add_dir(PROFILE_DATA_DIR_CUR, true);
1606 add_dir(PROFILE_DATA_DIR_REF, true);
1607 }
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001608 add_mountinfo();
Felipe Lemec0808152016-06-17 17:37:13 -07001609 dump_iptables();
Srinath Sridharanfdf52d32016-02-01 15:50:22 -08001610
Erik Kline32af8c22016-09-28 17:26:26 +09001611 // Capture any IPSec policies in play. No keys are exposed here.
1612 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1613 CommandOptions::WithTimeout(10).Build());
1614
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001615 // Run ss as root so we can see socket marks.
Felipe Lemec7fe8fe2016-09-21 18:13:20 -07001616 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, CommandOptions::WithTimeout(10).Build());
Lorenzo Colittid3b809b2016-09-26 13:37:45 +09001617
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}