blob: 1e0943f6197bdcb5f976fb8f7833330a1b2f6e84 [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 */
Felipe Lemef0292972016-11-22 13:57:05 -080016
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070017#define LOG_TAG "dumpstate"
Colin Crossf45fa6b2012-03-26 12:38:26 -070018
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -070019#include <dirent.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070020#include <errno.h>
21#include <fcntl.h>
Felipe Lemead5f6c42015-11-30 14:26:46 -080022#include <libgen.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070023#include <limits.h>
Mark Salyzyn8f37aa52015-06-12 12:28:24 -070024#include <stdbool.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070025#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
Christopher Ferris7dc7f322014-07-22 16:08:19 -070028#include <sys/prctl.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070029#include <sys/resource.h>
30#include <sys/stat.h>
31#include <sys/time.h>
32#include <sys/wait.h>
33#include <unistd.h>
Narayan Kamath8f788292017-05-25 13:20:39 +010034#include <memory>
35#include <regex>
36#include <set>
37#include <string>
38#include <vector>
Colin Crossf45fa6b2012-03-26 12:38:26 -070039
Felipe Leme96c2bbb2016-09-26 09:21:21 -070040#include <android-base/file.h>
41#include <android-base/properties.h>
Elliott Hughes9dc117c2015-12-07 14:21:50 -080042#include <android-base/stringprintf.h>
Naveen Kalla058e1e82016-10-19 21:38:44 -070043#include <android-base/strings.h>
Andreas Gampeaff68432016-07-18 18:01:27 -070044#include <android-base/unique_fd.h>
Felipe Leme6f674ae2016-11-18 17:10:33 -080045#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
46#include <cutils/native_handle.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070047#include <cutils/properties.h>
Felipe Leme75876a22016-10-27 16:31:27 -070048#include <openssl/sha.h>
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -070049#include <private/android_filesystem_config.h>
50#include <private/android_logger.h>
Colin Crossf45fa6b2012-03-26 12:38:26 -070051
Felipe Lemef0292972016-11-22 13:57:05 -080052#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070053#include "DumpstateService.h"
Colin Crossf45fa6b2012-03-26 12:38:26 -070054#include "dumpstate.h"
Felipe Leme6e01fa62015-11-11 19:35:14 -080055
Steven Morelandcb7ef822016-11-29 13:20:37 -080056using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
Steven Morelandcb7ef822016-11-29 13:20:37 -080057
Felipe Leme47e9be22016-12-21 15:37:07 -080058// TODO: remove once moved to namespace
59using android::os::dumpstate::CommandOptions;
60using android::os::dumpstate::DumpFileToFd;
61using android::os::dumpstate::PropertiesHelper;
62using android::os::dumpstate::GetPidByName;
63
Colin Crossf45fa6b2012-03-26 12:38:26 -070064/* read before root is shed */
65static char cmdline_buf[16384] = "(unknown)";
66static const char *dump_traces_path = NULL;
67
Felipe Leme1d486fe2016-10-14 18:06:47 -070068// TODO: variables and functions below should be part of dumpstate object
69
Felipe Leme635ca312016-01-05 14:23:02 -080070static std::set<std::string> mount_points;
71void add_mountinfo();
Felipe Leme78f2c862015-12-21 09:55:22 -080072
Todd Poynor2a83daa2013-11-22 15:44:22 -080073#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
Mark Salyzyn7d0a7622016-06-24 14:06:15 -070074#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0"
Wei Wang509bb5d2017-06-09 14:42:12 -070075#define BLK_DEV_SYS_DIR "/sys/block"
Todd Poynor2a83daa2013-11-22 15:44:22 -080076
Wei Liu341938b2016-04-27 16:18:17 -070077#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080078#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070079#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070080#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010081#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
82#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +090083#define WLUTIL "/vendor/xbin/wlutil"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070084
Narayan Kamath8f788292017-05-25 13:20:39 +010085// TODO(narayan): Since this information has to be kept in sync
86// with tombstoned, we should just put it in a common header.
87//
88// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +010089static const std::string TOMBSTONE_DIR = "/data/tombstones/";
90static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
91static const std::string ANR_DIR = "/data/anr/";
92static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -070093
Narayan Kamath8f788292017-05-25 13:20:39 +010094struct DumpData {
95 std::string name;
96 int fd;
97 time_t mtime;
98};
99
100static bool operator<(const DumpData& d1, const DumpData& d2) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100101 return d1.mtime > d2.mtime;
Narayan Kamath8f788292017-05-25 13:20:39 +0100102}
103
104static std::unique_ptr<std::vector<DumpData>> tombstone_data;
105static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700106
Felipe Lemee844a9d2016-09-21 15:01:39 -0700107// TODO: temporary variables and functions used during C++ refactoring
108static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700109static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
110 const CommandOptions& options = CommandOptions::DEFAULT) {
111 return ds.RunCommand(title, fullCommand, options);
112}
113static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800114 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Felipe Leme678727a2016-09-21 17:22:11 -0700115 long dumpsysTimeout = 0) {
116 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
117}
118static int DumpFile(const std::string& title, const std::string& path) {
119 return ds.DumpFile(title, path);
120}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800121
Felipe Lemee844a9d2016-09-21 15:01:39 -0700122// Relative directory (inside the zip) for all files copied as-is into the bugreport.
123static const std::string ZIP_ROOT_DIR = "FS";
124
Steven Moreland7440ddb2016-12-15 16:13:39 -0800125// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700126static const std::string kDumpstateBoardPath = "/bugreports/";
127static const std::string kDumpstateBoardFiles[] = {
128 "dumpstate_board.txt",
Jie Songdf4e3bc2017-06-21 13:26:00 -0700129 // TODO: rename to dumpstate_board.bin once vendors can handle it
130 "modem_log_all.tar"
Jie Song9fbfad02017-06-20 16:29:42 -0700131};
132static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
133
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700134static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800135
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700136static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700137static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700138static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700139static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
140static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700141
Felipe Lemef0292972016-11-22 13:57:05 -0800142static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
143
Narayan Kamath8f788292017-05-25 13:20:39 +0100144/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100145 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
146 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
147 * is set, the vector only contains files that were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100148 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100149static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
150 const std::string& file_prefix,
151 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100152 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
153
Narayan Kamath8f788292017-05-25 13:20:39 +0100154 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100155 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100156
Narayan Kamathbd863722017-06-01 18:50:12 +0100157 struct dirent* entry = nullptr;
158 while ((entry = readdir(dump_dir.get()))) {
159 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100160 continue;
161 }
162
Narayan Kamathbd863722017-06-01 18:50:12 +0100163 const std::string base_name(entry->d_name);
164 if (base_name.find(file_prefix) != 0) {
165 continue;
166 }
167
168 const std::string abs_path = dir_path + base_name;
169 android::base::unique_fd fd(
170 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
171 if (fd == -1) {
172 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
173 break;
174 }
175
176 struct stat st = {};
177 if (fstat(fd, &st) == -1) {
178 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100179 continue;
180 }
181
182 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100183 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100184 continue;
185 }
186
Narayan Kamathbd863722017-06-01 18:50:12 +0100187 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100188
189 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700190 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100191
192 std::sort(dump_data->begin(), dump_data->end());
193
194 return dump_data.release();
195}
196
Narayan Kamathbd863722017-06-01 18:50:12 +0100197static bool AddDumps(const std::vector<DumpData>::const_iterator start,
198 const std::vector<DumpData>::const_iterator end,
199 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100200 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100201 for (auto it = start; it != end; ++it) {
202 const std::string& name = it->name;
203 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100204 dumped = true;
205 if (ds.IsZipping() && add_to_zip) {
206 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
207 MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
208 }
209 } else {
210 dump_file_from_fd(type_name, name.c_str(), fd);
211 }
212
213 close(fd);
214 }
215
216 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700217}
218
Felipe Leme635ca312016-01-05 14:23:02 -0800219// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700220void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800221 char path[PATH_MAX];
222
223 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
224 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700225 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800226 char linkname[PATH_MAX];
227 ssize_t r = readlink(path, linkname, PATH_MAX);
228 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800229 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800230 return;
231 }
232 linkname[r] = '\0';
233
234 if (mount_points.find(linkname) == mount_points.end()) {
235 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700236 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700237 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800238 mount_points.insert(linkname);
239 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800240 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800241 }
242 }
243}
244
245void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700246 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700247 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800248 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800249 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700250 for_each_pid(do_mountinfo, nullptr);
251 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800252}
253
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700254static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
255{
256 DIR *d;
257 struct dirent *de;
258 char path[PATH_MAX];
259
260 d = opendir(driverpath);
261 if (d == NULL) {
262 return;
263 }
264
265 while ((de = readdir(d))) {
266 if (de->d_type != DT_LNK) {
267 continue;
268 }
269 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700270 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700271 }
272
273 closedir(d);
274}
275
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700276
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700277
278// dump anrd's trace and add to the zip file.
279// 1. check if anrd is running on this device.
280// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
281// 3. wait until the trace generation completes and add to the zip file.
282static bool dump_anrd_trace() {
283 unsigned int pid;
284 char buf[50], path[PATH_MAX];
285 struct dirent *trace;
286 struct stat st;
287 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700288 int retry = 5;
289 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700290 long long cur_size = 0;
291 const char *trace_path = "/data/misc/anrd/";
292
Felipe Leme1d486fe2016-10-14 18:06:47 -0700293 if (!ds.IsZipping()) {
294 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700295 return false;
296 }
297
298 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700299 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700300
301 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700302 if (stat(trace_path, &st) == 0) {
303 old_mtime = st.st_mtime;
304 } else {
305 MYLOGE("Failed to find: %s\n", trace_path);
306 return false;
307 }
308
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700309 // send SIGUSR1 to the anrd to generate a trace.
310 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700311 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700312 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700313 MYLOGE("anrd signal timed out. Please manually collect trace\n");
314 return false;
315 }
316
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700317 while (retry-- > 0 && old_mtime == st.st_mtime) {
318 sleep(1);
319 stat(trace_path, &st);
320 }
321
322 if (retry < 0 && old_mtime == st.st_mtime) {
323 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
324 return false;
325 }
326
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700327 // identify the trace file by its creation time.
328 if (!(trace_dir = opendir(trace_path))) {
329 MYLOGE("Can't open trace file under %s\n", trace_path);
330 }
331 while ((trace = readdir(trace_dir))) {
332 if (strcmp(trace->d_name, ".") == 0
333 || strcmp(trace->d_name, "..") == 0) {
334 continue;
335 }
336 sprintf(path, "%s%s", trace_path, trace->d_name);
337 if (stat(path, &st) == 0) {
338 if (st.st_ctime > max_ctime) {
339 max_ctime = st.st_ctime;
340 sprintf(buf, "%s", trace->d_name);
341 }
342 }
343 }
344 closedir(trace_dir);
345
346 // Wait until the dump completes by checking the size of the trace.
347 if (max_ctime > 0) {
348 sprintf(path, "%s%s", trace_path, buf);
349 while(true) {
350 sleep(1);
351 if (stat(path, &st) == 0) {
352 if (st.st_size == cur_size) {
353 break;
354 } else if (st.st_size > cur_size) {
355 cur_size = st.st_size;
356 } else {
357 return false;
358 }
359 } else {
360 MYLOGE("Cant stat() %s anymore\n", path);
361 return false;
362 }
363 }
364 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700365 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700366 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
367 } else {
368 if (remove(path)) {
369 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
370 }
371 return true;
372 }
373 } else {
374 MYLOGE("Can't stats any trace file under %s\n", trace_path);
375 }
376 }
377 return false;
378}
379
Felipe Lemeefd7e272016-05-18 09:27:16 -0700380static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700381 if (!ds.IsZipping()) {
382 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700383 return;
384 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700385 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700386 if (systrace_path.empty()) {
387 MYLOGE("Not dumping systrace because path is empty\n");
388 return;
389 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700390 const char* path = "/sys/kernel/debug/tracing/tracing_on";
391 long int is_tracing;
392 if (read_file_as_long(path, &is_tracing)) {
393 return; // error already logged
394 }
395 if (is_tracing <= 0) {
396 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
397 return;
398 }
399
Felipe Leme14e034a2016-03-30 18:51:03 -0700400 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
401 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700402 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700403 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700404 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700405 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700406 // peacefully; ideally, we should call strace to stop itself, but there is no such option
407 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700408 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700409 // MYLOGE("could not stop systrace ");
410 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700411 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700412 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700413 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700414 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700415 if (remove(systrace_path.c_str())) {
416 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
417 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700418 }
419}
420
Felipe Lemeefd7e272016-05-18 09:27:16 -0700421static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800422 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700423 return;
424 }
425
Felipe Leme1d486fe2016-10-14 18:06:47 -0700426 std::string raft_path = ds.GetPath("-raft_log.txt");
427 if (raft_path.empty()) {
428 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700429 return;
430 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700431
432 struct stat s;
433 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
434 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
435 return;
436 }
437
Felipe Leme30dbfa12016-09-02 12:43:26 -0700438 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700439 if (!ds.IsZipping()) {
440 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700441 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700442 return;
443 }
444
Felipe Leme1d486fe2016-10-14 18:06:47 -0700445 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
446 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
447 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700448 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700449 if (remove(raft_path.c_str())) {
450 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700451 }
452 }
453}
454
Mark Salyzyn326842f2015-04-30 09:49:41 -0700455static bool skip_not_stat(const char *path) {
456 static const char stat[] = "/stat";
457 size_t len = strlen(path);
458 if (path[len - 1] == '/') { /* Directory? */
459 return false;
460 }
461 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
462}
463
Felipe Leme4c2d6632016-09-28 14:32:00 -0700464static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800465 return false;
466}
467
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700468unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700469
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800470//
471// stat offsets
472// Name units description
473// ---- ----- -----------
474// read I/Os requests number of read I/Os processed
475#define __STAT_READ_IOS 0
476// read merges requests number of read I/Os merged with in-queue I/O
477#define __STAT_READ_MERGES 1
478// read sectors sectors number of sectors read
479#define __STAT_READ_SECTORS 2
480// read ticks milliseconds total wait time for read requests
481#define __STAT_READ_TICKS 3
482// write I/Os requests number of write I/Os processed
483#define __STAT_WRITE_IOS 4
484// write merges requests number of write I/Os merged with in-queue I/O
485#define __STAT_WRITE_MERGES 5
486// write sectors sectors number of sectors written
487#define __STAT_WRITE_SECTORS 6
488// write ticks milliseconds total wait time for write requests
489#define __STAT_WRITE_TICKS 7
490// in_flight requests number of I/Os currently in flight
491#define __STAT_IN_FLIGHT 8
492// io_ticks milliseconds total time this block device has been active
493#define __STAT_IO_TICKS 9
494// time_in_queue milliseconds total wait time for all requests
495#define __STAT_IN_QUEUE 10
496#define __STAT_NUMBER_FIELD 11
497//
498// read I/Os, write I/Os
499// =====================
500//
501// These values increment when an I/O request completes.
502//
503// read merges, write merges
504// =========================
505//
506// These values increment when an I/O request is merged with an
507// already-queued I/O request.
508//
509// read sectors, write sectors
510// ===========================
511//
512// These values count the number of sectors read from or written to this
513// block device. The "sectors" in question are the standard UNIX 512-byte
514// sectors, not any device- or filesystem-specific block size. The
515// counters are incremented when the I/O completes.
516#define SECTOR_SIZE 512
517//
518// read ticks, write ticks
519// =======================
520//
521// These values count the number of milliseconds that I/O requests have
522// waited on this block device. If there are multiple I/O requests waiting,
523// these values will increase at a rate greater than 1000/second; for
524// example, if 60 read requests wait for an average of 30 ms, the read_ticks
525// field will increase by 60*30 = 1800.
526//
527// in_flight
528// =========
529//
530// This value counts the number of I/O requests that have been issued to
531// the device driver but have not yet completed. It does not include I/O
532// requests that are in the queue but not yet issued to the device driver.
533//
534// io_ticks
535// ========
536//
537// This value counts the number of milliseconds during which the device has
538// had I/O requests queued.
539//
540// time_in_queue
541// =============
542//
543// This value counts the number of milliseconds that I/O requests have waited
544// on this block device. If there are multiple I/O requests waiting, this
545// value will increase as the product of the number of milliseconds times the
546// number of requests waiting (see "read ticks" above for an example).
547#define S_TO_MS 1000
548//
549
Mark Salyzyn326842f2015-04-30 09:49:41 -0700550static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800551 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700552 bool z;
553 char *cp, *buffer = NULL;
554 size_t i = 0;
555 FILE *fp = fdopen(fd, "rb");
556 getline(&buffer, &i, fp);
557 fclose(fp);
558 if (!buffer) {
559 return -errno;
560 }
561 i = strlen(buffer);
562 while ((i > 0) && (buffer[i - 1] == '\n')) {
563 buffer[--i] = '\0';
564 }
565 if (!*buffer) {
566 free(buffer);
567 return 0;
568 }
569 z = true;
570 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800571 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700572 if (fields[i] != 0) {
573 z = false;
574 }
575 }
576 if (z) { /* never accessed */
577 free(buffer);
578 return 0;
579 }
580
Wei Wang509bb5d2017-06-09 14:42:12 -0700581 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
582 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700583 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700584
585 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
586 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
587 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700588 free(buffer);
589
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800590 if (fields[__STAT_IO_TICKS]) {
591 unsigned long read_perf = 0;
592 unsigned long read_ios = 0;
593 if (fields[__STAT_READ_TICKS]) {
594 unsigned long long divisor = fields[__STAT_READ_TICKS]
595 * fields[__STAT_IO_TICKS];
596 read_perf = ((unsigned long long)SECTOR_SIZE
597 * fields[__STAT_READ_SECTORS]
598 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
599 / divisor;
600 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
601 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
602 / divisor;
603 }
604
605 unsigned long write_perf = 0;
606 unsigned long write_ios = 0;
607 if (fields[__STAT_WRITE_TICKS]) {
608 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
609 * fields[__STAT_IO_TICKS];
610 write_perf = ((unsigned long long)SECTOR_SIZE
611 * fields[__STAT_WRITE_SECTORS]
612 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
613 / divisor;
614 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
615 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
616 / divisor;
617 }
618
619 unsigned queue = (fields[__STAT_IN_QUEUE]
620 + (fields[__STAT_IO_TICKS] >> 1))
621 / fields[__STAT_IO_TICKS];
622
623 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700624 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800625 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700626 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
Felipe Lemed8b94e52016-12-08 10:21:44 -0800627 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800628 }
629
630 /* bugreport timeout factor adjustment */
631 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
632 worst_write_perf = write_perf;
633 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700634 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700635 return 0;
636}
637
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700638/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800639static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700640 log_id_t id = android_name_to_log_id(name);
641 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700642 /* Engineering margin is ten-fold our guess */
643 return 10 * (property_size + worst_write_perf) / worst_write_perf;
644}
645
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700646void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700647 std::string build, fingerprint, radio, bootloader, network;
648 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700649
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700650 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
651 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700652 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
653 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
654 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700655 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700656
Felipe Lemed8b94e52016-12-08 10:21:44 -0800657 printf("========================================================\n");
658 printf("== dumpstate: %s\n", date);
659 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700660
Felipe Lemed8b94e52016-12-08 10:21:44 -0800661 printf("\n");
662 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700663 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800664 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
665 printf("Bootloader: %s\n", bootloader.c_str());
666 printf("Radio: %s\n", radio.c_str());
667 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700668
Felipe Lemed8b94e52016-12-08 10:21:44 -0800669 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800670 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800671 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
672 printf("Bugreport format version: %s\n", version_.c_str());
673 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
674 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
675 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800676}
677
Felipe Leme24b66ee2016-06-16 10:55:26 -0700678// List of file extensions that can cause a zip file attachment to be rejected by some email
679// service providers.
680static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
681 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
682 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
683 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
684};
685
Felipe Leme1d486fe2016-10-14 18:06:47 -0700686bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
687 if (!IsZipping()) {
688 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
689 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800690 return false;
691 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700692 std::string valid_name = entry_name;
693
694 // Rename extension if necessary.
695 size_t idx = entry_name.rfind(".");
696 if (idx != std::string::npos) {
697 std::string extension = entry_name.substr(idx);
698 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
699 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
700 valid_name = entry_name + ".renamed";
701 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
702 }
703 }
704
Felipe Leme6fe9db62016-02-12 09:04:16 -0800705 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
706 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700707 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
708 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700709 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700710 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700711 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800712 return false;
713 }
714
Felipe Leme770410d2016-01-26 17:07:14 -0800715 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800716 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400717 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800718 if (bytes_read == 0) {
719 break;
720 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800721 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800722 return false;
723 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700724 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800725 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700726 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800727 return false;
728 }
729 }
730
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700731 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700732 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700733 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800734 return false;
735 }
736
737 return true;
738}
739
Felipe Leme1d486fe2016-10-14 18:06:47 -0700740bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
741 android::base::unique_fd fd(
742 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700743 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800744 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800745 return false;
746 }
747
Felipe Leme1d486fe2016-10-14 18:06:47 -0700748 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800749}
750
751/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700752static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700753 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800754}
755
Felipe Leme1d486fe2016-10-14 18:06:47 -0700756void Dumpstate::AddDir(const std::string& dir, bool recursive) {
757 if (!IsZipping()) {
758 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800759 return;
760 }
Felipe Leme678727a2016-09-21 17:22:11 -0700761 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800762 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700763 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800764}
765
Felipe Leme1d486fe2016-10-14 18:06:47 -0700766bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
767 if (!IsZipping()) {
768 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
769 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800770 return false;
771 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800772 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700773 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700774 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700775 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800777 return false;
778 }
779
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700780 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700781 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700782 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700783 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800784 return false;
785 }
786
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700787 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700788 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700789 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800790 return false;
791 }
792
793 return true;
794}
795
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800796static void DoKmsg() {
797 struct stat st;
798 if (!stat(PSTORE_LAST_KMSG, &st)) {
799 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
800 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
801 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
802 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
803 } else {
804 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
805 DumpFile("LAST KMSG", "/proc/last_kmsg");
806 }
807}
808
809static void DoLogcat() {
810 unsigned long timeout;
811 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
812 // calculate timeout
813 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
814 if (timeout < 20000) {
815 timeout = 20000;
816 }
Tony Makae737652017-03-30 17:47:09 +0100817 RunCommand("SYSTEM LOG",
818 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
819 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800820 CommandOptions::WithTimeout(timeout / 1000).Build());
821 timeout = logcat_timeout("events");
822 if (timeout < 20000) {
823 timeout = 20000;
824 }
825 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100826 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
827 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800828 CommandOptions::WithTimeout(timeout / 1000).Build());
829 timeout = logcat_timeout("radio");
830 if (timeout < 20000) {
831 timeout = 20000;
832 }
833 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100834 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
835 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800836 CommandOptions::WithTimeout(timeout / 1000).Build());
837
838 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
839
840 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
841 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100842 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
843 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800844}
845
Jayachandran Ca94c7172017-06-10 15:08:12 -0700846static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700847 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
848 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900849 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700850 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900851 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
852 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
853 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
854 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700855}
856
Narayan Kamath8f788292017-05-25 13:20:39 +0100857static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
858 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700859 std::string dump_traces_dir;
860
Felipe Lemee184f662016-10-27 10:04:47 -0700861 if (dump_traces_path != nullptr) {
862 if (add_to_zip) {
863 dump_traces_dir = dirname(dump_traces_path);
864 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
865 ds.AddDir(dump_traces_dir, true);
866 } else {
867 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
868 dump_traces_path);
869 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
870 }
871 }
872
Felipe Lemee184f662016-10-27 10:04:47 -0700873
874 // Make sure directory is not added twice.
875 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
876 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
877 // property - but in reality they're the same path (although the former could be nullptr).
878 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
879 // be revisited.
880 bool already_dumped = anr_traces_dir == dump_traces_dir;
881
Narayan Kamath8f788292017-05-25 13:20:39 +0100882 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700883 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
884
Narayan Kamath8f788292017-05-25 13:20:39 +0100885 int fd = TEMP_FAILURE_RETRY(
886 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
887 if (fd < 0) {
888 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700889 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100890 if (add_to_zip) {
891 if (!already_dumped) {
892 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
893 anr_traces_dir.c_str());
894 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700895 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100896 } else {
897 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
898 anr_traces_file.c_str());
899 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
900 }
901 }
902}
903
904static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
905 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
906 anr_traces_dir.c_str());
907
908 // If we're here, dump_traces_path will always be a temporary file
909 // (created with mkostemp or similar) that contains dumps taken earlier
910 // on in the process.
911 if (dump_traces_path != nullptr) {
912 if (add_to_zip) {
913 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
914 } else {
915 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
916 dump_traces_path);
917 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
918 }
919
920 const int ret = unlink(dump_traces_path);
921 if (ret == -1) {
922 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
923 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700924 }
925 }
926
Narayan Kamathbd863722017-06-01 18:50:12 +0100927 // Add a specific message for the first ANR Dump.
928 if (anr_data->size() > 0) {
929 AddDumps(anr_data->begin(), anr_data->begin() + 1,
930 "VM TRACES AT LAST ANR", add_to_zip);
931
932 if (anr_data->size() > 1) {
Narayan Kamath8cbab7c2017-07-27 11:21:07 +0100933 // NOTE: Historical ANRs are always added as separate entries in the
934 // bugreport zip file.
Narayan Kamathbd863722017-06-01 18:50:12 +0100935 AddDumps(anr_data->begin() + 1, anr_data->end(),
Narayan Kamath8cbab7c2017-07-27 11:21:07 +0100936 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100937 }
938 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100939 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
940 }
941}
942
943static void AddAnrTraceFiles() {
944 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
945
946 std::string anr_traces_file;
947 std::string anr_traces_dir;
948 bool is_global_trace_file = true;
949
950 // First check whether the stack-trace-dir property is set. When it's set,
951 // each ANR trace will be written to a separate file and not to a global
952 // stack trace file.
953 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
954 if (anr_traces_dir.empty()) {
955 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
956 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100957 anr_traces_dir = dirname(anr_traces_file.c_str());
958 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100959 } else {
960 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100961 }
962
963 // We have neither configured a global trace file nor a trace directory,
964 // there will be nothing to dump.
965 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
966 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700967 return;
968 }
969
Narayan Kamath8f788292017-05-25 13:20:39 +0100970 if (is_global_trace_file) {
971 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
972 } else {
973 AddAnrTraceDir(add_to_zip, anr_traces_dir);
974 }
975
Felipe Lemee184f662016-10-27 10:04:47 -0700976 /* slow traces for slow operations */
977 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +0100978 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -0700979 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +0100980 while (true) {
981 const std::string slow_trace_path =
982 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
983 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -0700984 // No traces file at this index, done with the files.
985 break;
986 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100987 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -0700988 i++;
989 }
990 }
991}
992
Wei Wang509bb5d2017-06-09 14:42:12 -0700993static void DumpBlockStatFiles() {
994 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700995
Wei Wang1dc1ef52017-06-12 11:28:37 -0700996 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
997
998 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700999 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1000 return;
1001 }
1002
1003 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001004 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001005 if ((d->d_name[0] == '.')
1006 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1007 || (d->d_name[1] == '\0'))) {
1008 continue;
1009 }
1010 const std::string new_path =
1011 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1012 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1013 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1014 printf("\n");
1015 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001016 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001017}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001018
1019static void DumpPacketStats() {
1020 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1021 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1022 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1023 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1024 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1025}
1026
1027static void DumpIpAddrAndRules() {
1028 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1029 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1030 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1031 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1032 RunCommand("IP RULES", {"ip", "rule", "show"});
1033 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1034}
1035
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001036static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001037 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001038
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001039 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001040 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001041 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001042 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001043 DumpFile("MEMORY INFO", "/proc/meminfo");
1044 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001045 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001046 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001047 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1048 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1049 DumpFile("SLAB INFO", "/proc/slabinfo");
1050 DumpFile("ZONEINFO", "/proc/zoneinfo");
1051 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1052 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1053 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001054
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001055 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1056 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1057 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001058
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001059 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001060 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemef0292972016-11-22 13:57:05 -08001061 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001062
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001063 if (ds.IsZipping()) {
1064 RunCommand(
1065 "HARDWARE HALS",
1066 {"lshal", std::string("--debug=") + kLsHalDebugPath},
1067 CommandOptions::AS_ROOT);
1068
1069 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1070
1071 unlink(kLsHalDebugPath.c_str());
1072 } else {
1073 RunCommand(
1074 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
1075 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001076
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001077 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001078 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001079 struct stat s;
1080 if (stat("/proc/modules", &s) != 0) {
1081 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1082 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001083 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001084 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001085
Colin Crossf45fa6b2012-03-26 12:38:26 -07001086 do_dmesg();
1087
Felipe Lemef0292972016-11-22 13:57:05 -08001088 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001089 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1090 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001091 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001092
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001093 /* Dump Bluetooth HCI logs */
1094 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001095
Felipe Leme9a523ae2016-10-20 15:10:33 -07001096 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001097 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001098 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001099 }
1100
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001101 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001102
Felipe Lemee184f662016-10-27 10:04:47 -07001103 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001104
Narayan Kamath8f788292017-05-25 13:20:39 +01001105 // NOTE: tombstones are always added as separate entries in the zip archive
1106 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001107 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1108 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001109 if (!tombstones_dumped) {
1110 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001111 }
1112
Jayachandran Ca94c7172017-06-10 15:08:12 -07001113 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001114
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001115 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001116
Jayachandran Ca94c7172017-06-10 15:08:12 -07001117 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001118
1119 dump_route_tables();
1120
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001121 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1122 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1123 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001124
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001125 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001126 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001127
Elliott Hughes23ccc622017-02-28 10:14:22 -08001128 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001129
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001130 RunCommand("VOLD DUMP", {"vdc", "dump"});
1131 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001132
Jin Qian24354422017-01-24 12:07:14 -08001133 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001136
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001137 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001138
Felipe Lemed8b94e52016-12-08 10:21:44 -08001139 printf("------ BACKLIGHTS ------\n");
1140 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001141 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001142 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001143 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001144 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001145 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001146 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001147 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001148 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001149 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001150 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001151
1152 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001153 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1154 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1155 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1156 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1157 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001158
Felipe Leme6f674ae2016-11-18 17:10:33 -08001159 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001160
Steven Moreland7440ddb2016-12-15 16:13:39 -08001161 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001162 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1163 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001164 // su does not exist on user builds, so try running without it.
1165 // This way any implementations of vril-dump that do not require
1166 // root can run on user builds.
1167 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001168 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001169 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001170 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001171 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001172 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001173 }
1174
Felipe Lemed8b94e52016-12-08 10:21:44 -08001175 printf("========================================================\n");
1176 printf("== Android Framework Services\n");
1177 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001178
Felipe Leme5bcce572016-09-27 09:21:08 -07001179 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1180 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001181
Felipe Lemed8b94e52016-12-08 10:21:44 -08001182 printf("========================================================\n");
1183 printf("== Checkins\n");
1184 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001185
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001186 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1187 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1188 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1189 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1190 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1191 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001192
Felipe Lemed8b94e52016-12-08 10:21:44 -08001193 printf("========================================================\n");
1194 printf("== Running Application Activities\n");
1195 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001196
Winson Chung1434a5c2017-02-28 17:09:24 -08001197 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001198
Felipe Lemed8b94e52016-12-08 10:21:44 -08001199 printf("========================================================\n");
1200 printf("== Running Application Services\n");
1201 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001202
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001203 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001204
Felipe Lemed8b94e52016-12-08 10:21:44 -08001205 printf("========================================================\n");
1206 printf("== Running Application Providers\n");
1207 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001208
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001209 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001210
Adrian Roos8b397ab2017-04-04 16:35:44 -07001211 printf("========================================================\n");
1212 printf("== Dropbox crashes\n");
1213 printf("========================================================\n");
1214
1215 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1216 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1217
Felipe Lemed8b94e52016-12-08 10:21:44 -08001218 printf("========================================================\n");
1219 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1220 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1221 printf("========================================================\n");
1222 printf("== dumpstate: done (id %d)\n", ds.id_);
1223 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001224}
1225
Jayachandran Ca94c7172017-06-10 15:08:12 -07001226// This method collects dumpsys for telephony debugging only
1227static void DumpstateTelephonyOnly() {
1228 DurationReporter duration_reporter("DUMPSTATE");
1229
1230 DumpIpTablesAsRoot();
1231
1232 if (!DropRootUser()) {
1233 return;
1234 }
1235
1236 do_dmesg();
1237 DoLogcat();
1238 DumpPacketStats();
1239 DoKmsg();
1240 DumpIpAddrAndRules();
1241 dump_route_tables();
1242
1243 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1244 CommandOptions::WithTimeout(10).Build());
1245
1246 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1247
1248 printf("========================================================\n");
1249 printf("== Android Framework Services\n");
1250 printf("========================================================\n");
1251
1252 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1253 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1254
1255 printf("========================================================\n");
1256 printf("== Running Application Services\n");
1257 printf("========================================================\n");
1258
1259 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1260
1261 printf("========================================================\n");
1262 printf("== dumpstate: done (id %d)\n", ds.id_);
1263 printf("========================================================\n");
1264}
1265
Felipe Leme6f674ae2016-11-18 17:10:33 -08001266void Dumpstate::DumpstateBoard() {
1267 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001268 printf("========================================================\n");
1269 printf("== Board\n");
1270 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001271
Chris Phoenix69d92212017-01-24 23:01:13 -08001272 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001273 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001274 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001275 return;
1276 }
1277
1278 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001279 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001280 return;
1281 }
1282
Jie Song9fbfad02017-06-20 16:29:42 -07001283 std::string path[NUM_OF_DUMPS];
1284 android::base::unique_fd fd[NUM_OF_DUMPS];
1285 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001286
Jie Song9fbfad02017-06-20 16:29:42 -07001287 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1288 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1289 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1290
1291 fd[i] = android::base::unique_fd(
1292 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1293 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1294 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1295 if (fd[i] < 0) {
1296 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1297 return;
1298 } else {
1299 numFds++;
1300 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001301 }
1302
Jie Song9fbfad02017-06-20 16:29:42 -07001303 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001304 if (handle == nullptr) {
1305 MYLOGE("Could not create native_handle\n");
1306 return;
1307 }
Jie Song9fbfad02017-06-20 16:29:42 -07001308
1309 for (int i = 0; i < numFds; i++) {
1310 handle->data[i] = fd[i].release();
1311 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001312
Felipe Lemef0292972016-11-22 13:57:05 -08001313 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001314 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1315 if (!status.isOk()) {
1316 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1317 native_handle_close(handle);
1318 native_handle_delete(handle);
1319 return;
1320 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001321
Jie Song9fbfad02017-06-20 16:29:42 -07001322 for (int i = 0; i < numFds; i++) {
1323 struct stat s;
1324 if (fstat(handle->data[i], &s) == -1) {
1325 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1326 } else if (s.st_size > 0) {
1327 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1328 } else {
1329 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1330 }
1331 }
1332
Felipe Lemed8b94e52016-12-08 10:21:44 -08001333 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001334
1335 native_handle_close(handle);
1336 native_handle_delete(handle);
1337
Jie Song9fbfad02017-06-20 16:29:42 -07001338 for (int i = 0; i < numFds; i++) {
1339 if (remove(path[i].c_str()) != 0) {
1340 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1341 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001342 }
1343}
1344
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001345static void ShowUsageAndExit(int exitCode = 1) {
1346 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001347 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001348 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1349 " -h: display this help message\n"
1350 " -b: play sound file instead of vibrate, at beginning of job\n"
1351 " -e: play sound file instead of vibrate, at end of job\n"
1352 " -o: write to file (instead of stdout)\n"
1353 " -d: append date to filename (requires -o)\n"
1354 " -p: capture screenshot to filename.png (requires -o)\n"
1355 " -z: generate zipped file (requires -o)\n"
1356 " -s: write output to control socket (for init)\n"
1357 " -S: write file location to control socket (for init; requires -o and -z)"
1358 " -q: disable vibrate\n"
1359 " -B: send broadcast when finished (requires -o)\n"
1360 " -P: send broadcast when started and update system properties on "
1361 "progress (requires -o and -B)\n"
1362 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1363 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001364 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001365 exit(exitCode);
1366}
1367
1368static void ExitOnInvalidArgs() {
1369 fprintf(stderr, "invalid combination of args\n");
1370 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001371}
1372
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001373static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001374 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001375}
1376
Wei Liuf87959e2016-08-26 14:51:42 -07001377static void register_sig_handler() {
1378 struct sigaction sa;
1379 sigemptyset(&sa.sa_mask);
1380 sa.sa_flags = 0;
1381 sa.sa_handler = sig_handler;
1382 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1383 sigaction(SIGSEGV, &sa, NULL); // segment fault
1384 sigaction(SIGINT, &sa, NULL); // ctrl-c
1385 sigaction(SIGTERM, &sa, NULL); // killed
1386 sigaction(SIGQUIT, &sa, NULL); // quit
1387}
1388
Felipe Leme1d486fe2016-10-14 18:06:47 -07001389bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001390 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001391 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001392 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001393 // Final timestamp
1394 char date[80];
1395 time_t the_real_now_please_stand_up = time(nullptr);
1396 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001397 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001398 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001399
Felipe Leme9a523ae2016-10-20 15:10:33 -07001400 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001401 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001402 return false;
1403 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001404 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001405 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001406 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001407 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001408
Felipe Leme0f3fb202016-06-10 17:10:53 -07001409 // Add log file (which contains stderr output) to zip...
1410 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001411 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001412 MYLOGE("Failed to add dumpstate log to .zip file\n");
1413 return false;
1414 }
1415 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001416 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001417 fprintf(stderr, "\n");
1418
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001419 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001420 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001421 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001422 return false;
1423 }
1424
Felipe Leme1d486fe2016-10-14 18:06:47 -07001425 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1426 ds.zip_file.reset(nullptr);
1427
Felipe Lemee9d2c542016-11-15 11:48:26 -08001428 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1429 if (remove(tmp_path_.c_str()) != 0) {
1430 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001431 }
1432
Felipe Leme1e9edc62015-12-21 16:02:13 -08001433 return true;
1434}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001435
Michal Karpinski4db754f2015-12-11 18:04:32 +00001436static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001437 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1438 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001439 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001440 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001441 return NULL;
1442 }
1443
1444 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001445 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001446
1447 std::vector<uint8_t> buffer(65536);
1448 while (1) {
1449 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1450 if (bytes_read == 0) {
1451 break;
1452 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001453 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001454 return NULL;
1455 }
1456
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001457 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001458 }
1459
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001460 uint8_t hash[SHA256_DIGEST_LENGTH];
1461 SHA256_Final(hash, &ctx);
1462
1463 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1464 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001465 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001466 }
1467 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1468 return std::string(hash_buffer);
1469}
1470
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001471static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1472 // clang-format off
1473 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1474 "--receiver-foreground", "--receiver-include-background", "-a", action};
1475 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001476
1477 am.insert(am.end(), args.begin(), args.end());
1478
Felipe Leme8d2410e2017-02-08 09:46:08 -08001479 RunCommand("", am,
1480 CommandOptions::WithTimeout(20)
1481 .Log("Sending broadcast: '%s'\n")
1482 .Always()
1483 .DropRoot()
1484 .RedirectStderr()
1485 .Build());
1486}
1487
Felipe Leme35b8cf12017-02-10 15:47:29 -08001488static void Vibrate(int duration_ms) {
1489 // clang-format off
1490 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1491 CommandOptions::WithTimeout(10)
1492 .Log("Vibrate: '%s'\n")
1493 .Always()
1494 .Build());
1495 // clang-format on
1496}
1497
Colin Crossf45fa6b2012-03-26 12:38:26 -07001498int main(int argc, char *argv[]) {
1499 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001500 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001501 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001502 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001503 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001504 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001505 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001506 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001507 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001508 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001509 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001510 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001511
Colin Crossf45fa6b2012-03-26 12:38:26 -07001512 /* set as high priority, and protect from OOM killer */
1513 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001514
Felipe Lemed071c682016-10-20 16:48:00 -07001515 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001516 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001517 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001518 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001519 } else {
1520 /* fallback to kernels <= 2.6.35 */
1521 oom_adj = fopen("/proc/self/oom_adj", "we");
1522 if (oom_adj) {
1523 fputs("-17", oom_adj);
1524 fclose(oom_adj);
1525 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001526 }
1527
Jeff Brown1dc94e32014-09-11 14:15:27 -07001528 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001529 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001530 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001531 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001532 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001533 case 'd': do_add_date = 1; break;
1534 case 'z': do_zip_file = 1; break;
1535 case 'o': use_outfile = optarg; break;
1536 case 's': use_socket = 1; break;
1537 case 'S': use_control_socket = 1; break;
1538 case 'v': show_header_only = true; break;
1539 case 'q': do_vibrate = 0; break;
1540 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001541 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001542 case 'R': is_remote_mode = 1; break;
1543 case 'B': do_broadcast = 1; break;
1544 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001545 case 'h':
1546 ShowUsageAndExit(0);
1547 break;
1548 default:
1549 fprintf(stderr, "Invalid option: %c\n", c);
1550 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001551 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001552 }
1553 }
1554
Felipe Lemed071c682016-10-20 16:48:00 -07001555 // TODO: use helper function to convert argv into a string
1556 for (int i = 0; i < argc; i++) {
1557 ds.args_ += argv[i];
1558 if (i < argc - 1) {
1559 ds.args_ += " ";
1560 }
1561 }
1562
1563 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001564 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001565 // Framework uses a system property to override some command-line args.
1566 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001567 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001568 // Currently, the dumpstate binder is only used by Shell to update progress.
1569 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001570 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001571 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001572 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001573 do_vibrate = 0;
1574 is_remote_mode = 1;
1575 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001576 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001577 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001578 } else if (ds.extra_options_ == "bugreporttelephony") {
1579 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001580 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001581 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001582 }
1583 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001584 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001585 }
1586
Naveen Kallab53a1c92017-03-16 18:17:25 -07001587 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1588 if (!ds.notification_title.empty()) {
1589 // Reset the property
1590 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1591
1592 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1593 if (!ds.notification_description.empty()) {
1594 // Reset the property
1595 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1596 }
1597 MYLOGD("notification (title: %s, description: %s)\n",
1598 ds.notification_title.c_str(), ds.notification_description.c_str());
1599 }
1600
Felipe Leme9a523ae2016-10-20 15:10:33 -07001601 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001602 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001603 }
1604
Felipe Leme2628e9e2016-04-12 16:36:51 -07001605 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001606 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001607 }
1608
Felipe Leme9a523ae2016-10-20 15:10:33 -07001609 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001610 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001611 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001612
Felipe Leme9a523ae2016-10-20 15:10:33 -07001613 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001614 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001615 }
1616
Felipe Lemed071c682016-10-20 16:48:00 -07001617 if (ds.version_ == VERSION_DEFAULT) {
1618 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001619 }
1620
Felipe Lemee184f662016-10-27 10:04:47 -07001621 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1622 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1623 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1624 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001625 exit(1);
1626 }
1627
1628 if (show_header_only) {
1629 ds.PrintHeader();
1630 exit(0);
1631 }
1632
Felipe Leme7447d7c2016-11-03 18:12:22 -07001633 /* redirect output if needed */
1634 bool is_redirecting = !use_socket && use_outfile;
1635
1636 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1637 std::string stats_path =
1638 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1639 : "";
1640 ds.progress_.reset(new Progress(stats_path));
1641
Felipe Lemed071c682016-10-20 16:48:00 -07001642 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001643 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001644 ds.id_ = ++last_id;
1645 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1646
1647 MYLOGI("begin\n");
1648
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001649 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001650
Felipe Leme75876a22016-10-27 16:31:27 -07001651 if (do_start_service) {
1652 MYLOGI("Starting 'dumpstate' service\n");
1653 android::status_t ret;
1654 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1655 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1656 }
1657 }
1658
Felipe Lemef0292972016-11-22 13:57:05 -08001659 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001660 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1661 }
1662
Felipe Leme7447d7c2016-11-03 18:12:22 -07001663 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001664 ds.extra_options_.c_str());
1665
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001666 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001667
Felipe Leme9a523ae2016-10-20 15:10:33 -07001668 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001669
Christopher Ferrised9354f2014-10-01 17:35:01 -07001670 // If we are going to use a socket, do it as early as possible
1671 // to avoid timeouts from bugreport.
1672 if (use_socket) {
1673 redirect_to_socket(stdout, "dumpstate");
1674 }
1675
Felipe Leme2628e9e2016-04-12 16:36:51 -07001676 if (use_control_socket) {
1677 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001678 ds.control_socket_fd_ = open_socket("dumpstate");
1679 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001680 }
1681
Felipe Leme71bbfc52015-11-23 14:14:51 -08001682 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001683 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001684 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001685 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001686 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1687 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001688 if (do_add_date) {
1689 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001690 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001691 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001692 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001693 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001694 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001695
1696 if (telephony_only) {
1697 ds.base_name_ += "-telephony";
1698 }
1699
Felipe Leme71bbfc52015-11-23 14:14:51 -08001700 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001701 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001702 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001703 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001704 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001705
Felipe Lemee844a9d2016-09-21 15:01:39 -07001706 MYLOGD(
1707 "Bugreport dir: %s\n"
1708 "Base name: %s\n"
1709 "Suffix: %s\n"
1710 "Log path: %s\n"
1711 "Temporary path: %s\n"
1712 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001713 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1714 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001715
Felipe Leme1e9edc62015-12-21 16:02:13 -08001716 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001717 ds.path_ = ds.GetPath(".zip");
1718 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1719 create_parent_dirs(ds.path_.c_str());
1720 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001721 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001722 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001723 do_zip_file = 0;
1724 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001725 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001726 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001727 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001728 }
1729
Felipe Leme9a523ae2016-10-20 15:10:33 -07001730 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001731 if (do_broadcast) {
1732 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001733
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001734 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001735 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001736 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001737 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001738 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001739 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001740 };
1741 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001742 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001743 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001744 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001745 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001746 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001747 }
1748 }
1749
Nick Kralevichf3599b32016-01-25 15:05:16 -08001750 /* read /proc/cmdline before dropping root */
1751 FILE *cmdline = fopen("/proc/cmdline", "re");
1752 if (cmdline) {
1753 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1754 fclose(cmdline);
1755 }
1756
John Michelau1f794c42012-09-17 11:20:19 -05001757 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001758 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001759 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001760
Felipe Leme9a523ae2016-10-20 15:10:33 -07001761 if (do_fb && ds.do_early_screenshot_) {
1762 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001763 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001764 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001765 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001766 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001767 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001768 }
1769 }
1770
Felipe Leme1e9edc62015-12-21 16:02:13 -08001771 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001772 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1773 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001774 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001775 }
1776 }
1777
Felipe Leme71bbfc52015-11-23 14:14:51 -08001778 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001779 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1780 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1781 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1782 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001783 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001784 /* TODO: rather than generating a text file now and zipping it later,
1785 it would be more efficient to redirect stdout to the zip entry
1786 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001787 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1788 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001789 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001790 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001791 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001792 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001793
1794 // Don't buffer stdout
1795 setvbuf(stdout, nullptr, _IONBF, 0);
1796
Felipe Leme608385d2016-02-01 10:35:38 -08001797 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1798 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001799 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001800 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001801
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001802 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001803 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001804 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001805 } else {
1806 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1807 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1808 // the raw trace.
1809 if (!dump_anrd_trace()) {
1810 dump_systrace();
1811 }
1812
1813 // Invoking the following dumpsys calls before dump_traces() to try and
1814 // keep the system stats as close to its initial state as possible.
1815 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1816 CommandOptions::WithTimeout(90).DropRoot().Build());
1817 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1818 CommandOptions::WithTimeout(10).DropRoot().Build());
1819
1820 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1821 dump_raft();
1822
1823 /* collect stack traces from Dalvik and native processes (needs root) */
1824 dump_traces_path = dump_traces();
1825
1826 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001827 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1828 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001829
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001830 ds.AddDir(RECOVERY_DIR, true);
1831 ds.AddDir(RECOVERY_DATA_DIR, true);
1832 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1833 if (!PropertiesHelper::IsUserBuild()) {
1834 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1835 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1836 }
1837 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001838 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001839
1840 // Capture any IPSec policies in play. No keys are exposed here.
1841 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1842 CommandOptions::WithTimeout(10).Build());
1843
1844 // Run ss as root so we can see socket marks.
1845 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1846 CommandOptions::WithTimeout(10).Build());
1847
1848 if (!DropRootUser()) {
1849 return -1;
1850 }
1851
1852 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001853 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001854
Felipe Leme55b42a62015-11-10 17:39:08 -08001855 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001856 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001857 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001858 }
1859
Felipe Leme6e01fa62015-11-11 19:35:14 -08001860 /* rename or zip the (now complete) .tmp file to its final location */
1861 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001862
1863 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001864 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001865 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001866 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001867 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001868 /* must whitelist which characters are allowed, otherwise it could cross directories */
1869 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001870 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001871 change_suffix = true;
1872 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001873 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001874 }
1875 }
1876 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001877 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1878 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001879 if (!ds.screenshot_path_.empty()) {
1880 std::string new_screenshot_path = ds.GetPath(".png");
1881 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1882 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1883 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001884 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001885 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001886 }
1887 }
1888 }
1889
Felipe Leme6e01fa62015-11-11 19:35:14 -08001890 bool do_text_file = true;
1891 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001892 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001893 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001894 do_text_file = true;
1895 } else {
1896 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001897 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001898 std::string new_path = ds.GetPath(".zip");
1899 if (ds.path_ != new_path) {
1900 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1901 if (rename(ds.path_.c_str(), new_path.c_str())) {
1902 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001903 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001904 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001905 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001906 }
1907 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001908 }
1909 }
1910 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001911 ds.path_ = ds.GetPath(".txt");
1912 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1913 ds.tmp_path_.c_str());
1914 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1915 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001916 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001917 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001918 }
1919 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001920 if (use_control_socket) {
1921 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001922 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001923 "FAIL:could not create zip file, check %s "
1924 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001925 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001926 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001927 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001928 }
1929 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001930 }
1931
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001932 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001933 for (int i = 0; i < 3; i++) {
1934 Vibrate(75);
1935 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001936 }
1937
Jeff Brown1dc94e32014-09-11 14:15:27 -07001938 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001939 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001940 if (!ds.path_.empty()) {
1941 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001942 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001943
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001944 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001945 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001946 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001947 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001948 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001949 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1950 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001951 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001952 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001953 if (do_fb) {
1954 am_args.push_back("--es");
1955 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001956 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001957 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001958 if (!ds.notification_title.empty()) {
1959 am_args.push_back("--es");
1960 am_args.push_back("android.intent.extra.TITLE");
1961 am_args.push_back(ds.notification_title);
1962 if (!ds.notification_description.empty()) {
1963 am_args.push_back("--es");
1964 am_args.push_back("android.intent.extra.DESCRIPTION");
1965 am_args.push_back(ds.notification_description);
1966 }
1967 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001968 if (is_remote_mode) {
1969 am_args.push_back("--es");
1970 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001971 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001972 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1973 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001974 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001975 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001976 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001977 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001978 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001979 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001980 }
1981
Felipe Leme7447d7c2016-11-03 18:12:22 -07001982 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1983 ds.progress_->GetInitialMax());
1984 ds.progress_->Save();
1985 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001986
Felipe Leme107a05f2016-03-08 15:11:15 -08001987 if (is_redirecting) {
1988 fclose(stderr);
1989 }
1990
Felipe Leme9a523ae2016-10-20 15:10:33 -07001991 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001992 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001993 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001994 }
1995
Colin Crossf45fa6b2012-03-26 12:38:26 -07001996 return 0;
1997}