blob: 1ecbb03ff41d8a41eb50681613c43596ab101b56 [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 Kamathd087b8d2017-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 Kamathd087b8d2017-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},
Yifan Hong48e83a12017-10-03 14:10:07 -07001067 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001068
1069 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1070
1071 unlink(kLsHalDebugPath.c_str());
1072 } else {
1073 RunCommand(
Yifan Hong48e83a12017-10-03 14:10:07 -07001074 "HARDWARE HALS", {"lshal", "--debug"},
1075 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001076 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001077
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001078 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001079 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001080 struct stat s;
1081 if (stat("/proc/modules", &s) != 0) {
1082 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1083 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001084 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001085 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001086
Colin Crossf45fa6b2012-03-26 12:38:26 -07001087 do_dmesg();
1088
Felipe Lemef0292972016-11-22 13:57:05 -08001089 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001090 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1091 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001092 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001093
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001094 /* Dump Bluetooth HCI logs */
1095 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001096
Felipe Leme9a523ae2016-10-20 15:10:33 -07001097 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001098 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001099 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001100 }
1101
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001102 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001103
Felipe Lemee184f662016-10-27 10:04:47 -07001104 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001105
Narayan Kamath8f788292017-05-25 13:20:39 +01001106 // NOTE: tombstones are always added as separate entries in the zip archive
1107 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001108 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1109 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001110 if (!tombstones_dumped) {
1111 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001112 }
1113
Jayachandran Ca94c7172017-06-10 15:08:12 -07001114 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001115
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001116 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001117
Jayachandran Ca94c7172017-06-10 15:08:12 -07001118 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001119
1120 dump_route_tables();
1121
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001122 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1123 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1124 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001125
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001126 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001127 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001128
Elliott Hughes23ccc622017-02-28 10:14:22 -08001129 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001130
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001131 RunCommand("VOLD DUMP", {"vdc", "dump"});
1132 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001133
Jin Qian24354422017-01-24 12:07:14 -08001134 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001135
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001136 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001137
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001138 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001139
Felipe Lemed8b94e52016-12-08 10:21:44 -08001140 printf("------ BACKLIGHTS ------\n");
1141 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001142 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001143 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001144 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001145 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001146 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001147 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001148 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001149 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001150 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001151 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001152
1153 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001154 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1155 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1156 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1157 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1158 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001159
Felipe Leme6f674ae2016-11-18 17:10:33 -08001160 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001161
Steven Moreland7440ddb2016-12-15 16:13:39 -08001162 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001163 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1164 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001165 // su does not exist on user builds, so try running without it.
1166 // This way any implementations of vril-dump that do not require
1167 // root can run on user builds.
1168 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001169 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001170 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001171 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001172 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001173 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001174 }
1175
Felipe Lemed8b94e52016-12-08 10:21:44 -08001176 printf("========================================================\n");
1177 printf("== Android Framework Services\n");
1178 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001179
Felipe Leme5bcce572016-09-27 09:21:08 -07001180 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1181 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001182
Felipe Lemed8b94e52016-12-08 10:21:44 -08001183 printf("========================================================\n");
1184 printf("== Checkins\n");
1185 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001186
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001187 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1188 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1189 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1190 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1191 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1192 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001193
Felipe Lemed8b94e52016-12-08 10:21:44 -08001194 printf("========================================================\n");
1195 printf("== Running Application Activities\n");
1196 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001197
Winson Chung1434a5c2017-02-28 17:09:24 -08001198 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001199
Felipe Lemed8b94e52016-12-08 10:21:44 -08001200 printf("========================================================\n");
1201 printf("== Running Application Services\n");
1202 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001203
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001204 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001205
Felipe Lemed8b94e52016-12-08 10:21:44 -08001206 printf("========================================================\n");
1207 printf("== Running Application Providers\n");
1208 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001209
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001210 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001211
Adrian Roos8b397ab2017-04-04 16:35:44 -07001212 printf("========================================================\n");
1213 printf("== Dropbox crashes\n");
1214 printf("========================================================\n");
1215
1216 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1217 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1218
Felipe Lemed8b94e52016-12-08 10:21:44 -08001219 printf("========================================================\n");
1220 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1221 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1222 printf("========================================================\n");
1223 printf("== dumpstate: done (id %d)\n", ds.id_);
1224 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001225}
1226
Jayachandran Ca94c7172017-06-10 15:08:12 -07001227// This method collects dumpsys for telephony debugging only
1228static void DumpstateTelephonyOnly() {
1229 DurationReporter duration_reporter("DUMPSTATE");
1230
1231 DumpIpTablesAsRoot();
1232
1233 if (!DropRootUser()) {
1234 return;
1235 }
1236
1237 do_dmesg();
1238 DoLogcat();
1239 DumpPacketStats();
1240 DoKmsg();
1241 DumpIpAddrAndRules();
1242 dump_route_tables();
1243
1244 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1245 CommandOptions::WithTimeout(10).Build());
1246
1247 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1248
1249 printf("========================================================\n");
1250 printf("== Android Framework Services\n");
1251 printf("========================================================\n");
1252
1253 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1254 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1255
1256 printf("========================================================\n");
1257 printf("== Running Application Services\n");
1258 printf("========================================================\n");
1259
1260 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1261
1262 printf("========================================================\n");
1263 printf("== dumpstate: done (id %d)\n", ds.id_);
1264 printf("========================================================\n");
1265}
1266
Felipe Leme6f674ae2016-11-18 17:10:33 -08001267void Dumpstate::DumpstateBoard() {
1268 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001269 printf("========================================================\n");
1270 printf("== Board\n");
1271 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001272
Chris Phoenix69d92212017-01-24 23:01:13 -08001273 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001274 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001275 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001276 return;
1277 }
1278
1279 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001280 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001281 return;
1282 }
1283
Jie Song9fbfad02017-06-20 16:29:42 -07001284 std::string path[NUM_OF_DUMPS];
1285 android::base::unique_fd fd[NUM_OF_DUMPS];
1286 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001287
Jie Song9fbfad02017-06-20 16:29:42 -07001288 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1289 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1290 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1291
1292 fd[i] = android::base::unique_fd(
1293 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1294 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1295 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1296 if (fd[i] < 0) {
1297 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1298 return;
1299 } else {
1300 numFds++;
1301 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001302 }
1303
Jie Song9fbfad02017-06-20 16:29:42 -07001304 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001305 if (handle == nullptr) {
1306 MYLOGE("Could not create native_handle\n");
1307 return;
1308 }
Jie Song9fbfad02017-06-20 16:29:42 -07001309
1310 for (int i = 0; i < numFds; i++) {
1311 handle->data[i] = fd[i].release();
1312 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001313
Felipe Lemef0292972016-11-22 13:57:05 -08001314 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001315 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1316 if (!status.isOk()) {
1317 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1318 native_handle_close(handle);
1319 native_handle_delete(handle);
1320 return;
1321 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001322
Jie Song9fbfad02017-06-20 16:29:42 -07001323 for (int i = 0; i < numFds; i++) {
1324 struct stat s;
1325 if (fstat(handle->data[i], &s) == -1) {
1326 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1327 } else if (s.st_size > 0) {
1328 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1329 } else {
1330 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1331 }
1332 }
1333
Felipe Lemed8b94e52016-12-08 10:21:44 -08001334 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001335
1336 native_handle_close(handle);
1337 native_handle_delete(handle);
1338
Jie Song9fbfad02017-06-20 16:29:42 -07001339 for (int i = 0; i < numFds; i++) {
1340 if (remove(path[i].c_str()) != 0) {
1341 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1342 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001343 }
1344}
1345
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001346static void ShowUsageAndExit(int exitCode = 1) {
1347 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001348 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001349 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1350 " -h: display this help message\n"
1351 " -b: play sound file instead of vibrate, at beginning of job\n"
1352 " -e: play sound file instead of vibrate, at end of job\n"
1353 " -o: write to file (instead of stdout)\n"
1354 " -d: append date to filename (requires -o)\n"
1355 " -p: capture screenshot to filename.png (requires -o)\n"
1356 " -z: generate zipped file (requires -o)\n"
1357 " -s: write output to control socket (for init)\n"
1358 " -S: write file location to control socket (for init; requires -o and -z)"
1359 " -q: disable vibrate\n"
1360 " -B: send broadcast when finished (requires -o)\n"
1361 " -P: send broadcast when started and update system properties on "
1362 "progress (requires -o and -B)\n"
1363 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1364 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001365 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001366 exit(exitCode);
1367}
1368
1369static void ExitOnInvalidArgs() {
1370 fprintf(stderr, "invalid combination of args\n");
1371 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001372}
1373
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001374static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001375 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001376}
1377
Wei Liuf87959e2016-08-26 14:51:42 -07001378static void register_sig_handler() {
1379 struct sigaction sa;
1380 sigemptyset(&sa.sa_mask);
1381 sa.sa_flags = 0;
1382 sa.sa_handler = sig_handler;
1383 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1384 sigaction(SIGSEGV, &sa, NULL); // segment fault
1385 sigaction(SIGINT, &sa, NULL); // ctrl-c
1386 sigaction(SIGTERM, &sa, NULL); // killed
1387 sigaction(SIGQUIT, &sa, NULL); // quit
1388}
1389
Felipe Leme1d486fe2016-10-14 18:06:47 -07001390bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001391 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001392 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001393 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001394 // Final timestamp
1395 char date[80];
1396 time_t the_real_now_please_stand_up = time(nullptr);
1397 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001398 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001399 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001400
Felipe Leme9a523ae2016-10-20 15:10:33 -07001401 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001402 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001403 return false;
1404 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001405 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001406 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001407 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001408 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001409
Felipe Leme0f3fb202016-06-10 17:10:53 -07001410 // Add log file (which contains stderr output) to zip...
1411 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001412 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001413 MYLOGE("Failed to add dumpstate log to .zip file\n");
1414 return false;
1415 }
1416 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001417 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001418 fprintf(stderr, "\n");
1419
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001420 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001421 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001422 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001423 return false;
1424 }
1425
Felipe Leme1d486fe2016-10-14 18:06:47 -07001426 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1427 ds.zip_file.reset(nullptr);
1428
Felipe Lemee9d2c542016-11-15 11:48:26 -08001429 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1430 if (remove(tmp_path_.c_str()) != 0) {
1431 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001432 }
1433
Felipe Leme1e9edc62015-12-21 16:02:13 -08001434 return true;
1435}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001436
Michal Karpinski4db754f2015-12-11 18:04:32 +00001437static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001438 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1439 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001440 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001441 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001442 return NULL;
1443 }
1444
1445 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001446 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001447
1448 std::vector<uint8_t> buffer(65536);
1449 while (1) {
1450 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1451 if (bytes_read == 0) {
1452 break;
1453 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001454 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001455 return NULL;
1456 }
1457
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001458 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001459 }
1460
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001461 uint8_t hash[SHA256_DIGEST_LENGTH];
1462 SHA256_Final(hash, &ctx);
1463
1464 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1465 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001466 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001467 }
1468 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1469 return std::string(hash_buffer);
1470}
1471
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001472static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1473 // clang-format off
1474 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1475 "--receiver-foreground", "--receiver-include-background", "-a", action};
1476 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001477
1478 am.insert(am.end(), args.begin(), args.end());
1479
Felipe Leme8d2410e2017-02-08 09:46:08 -08001480 RunCommand("", am,
1481 CommandOptions::WithTimeout(20)
1482 .Log("Sending broadcast: '%s'\n")
1483 .Always()
1484 .DropRoot()
1485 .RedirectStderr()
1486 .Build());
1487}
1488
Felipe Leme35b8cf12017-02-10 15:47:29 -08001489static void Vibrate(int duration_ms) {
1490 // clang-format off
1491 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1492 CommandOptions::WithTimeout(10)
1493 .Log("Vibrate: '%s'\n")
1494 .Always()
1495 .Build());
1496 // clang-format on
1497}
1498
Colin Crossf45fa6b2012-03-26 12:38:26 -07001499int main(int argc, char *argv[]) {
1500 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001501 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001502 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001503 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001504 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001505 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001506 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001507 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001508 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001509 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001510 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001511 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001512
Colin Crossf45fa6b2012-03-26 12:38:26 -07001513 /* set as high priority, and protect from OOM killer */
1514 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001515
Felipe Lemed071c682016-10-20 16:48:00 -07001516 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001517 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001518 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001519 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001520 } else {
1521 /* fallback to kernels <= 2.6.35 */
1522 oom_adj = fopen("/proc/self/oom_adj", "we");
1523 if (oom_adj) {
1524 fputs("-17", oom_adj);
1525 fclose(oom_adj);
1526 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001527 }
1528
Jeff Brown1dc94e32014-09-11 14:15:27 -07001529 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001530 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001531 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001532 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001533 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001534 case 'd': do_add_date = 1; break;
1535 case 'z': do_zip_file = 1; break;
1536 case 'o': use_outfile = optarg; break;
1537 case 's': use_socket = 1; break;
1538 case 'S': use_control_socket = 1; break;
1539 case 'v': show_header_only = true; break;
1540 case 'q': do_vibrate = 0; break;
1541 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001542 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001543 case 'R': is_remote_mode = 1; break;
1544 case 'B': do_broadcast = 1; break;
1545 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001546 case 'h':
1547 ShowUsageAndExit(0);
1548 break;
1549 default:
1550 fprintf(stderr, "Invalid option: %c\n", c);
1551 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001552 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001553 }
1554 }
1555
Felipe Lemed071c682016-10-20 16:48:00 -07001556 // TODO: use helper function to convert argv into a string
1557 for (int i = 0; i < argc; i++) {
1558 ds.args_ += argv[i];
1559 if (i < argc - 1) {
1560 ds.args_ += " ";
1561 }
1562 }
1563
1564 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001565 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001566 // Framework uses a system property to override some command-line args.
1567 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001568 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001569 // Currently, the dumpstate binder is only used by Shell to update progress.
1570 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001571 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001572 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001573 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001574 do_vibrate = 0;
1575 is_remote_mode = 1;
1576 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001577 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001578 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001579 } else if (ds.extra_options_ == "bugreporttelephony") {
1580 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001581 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001582 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001583 }
1584 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001585 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001586 }
1587
Naveen Kallab53a1c92017-03-16 18:17:25 -07001588 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1589 if (!ds.notification_title.empty()) {
1590 // Reset the property
1591 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1592
1593 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1594 if (!ds.notification_description.empty()) {
1595 // Reset the property
1596 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1597 }
1598 MYLOGD("notification (title: %s, description: %s)\n",
1599 ds.notification_title.c_str(), ds.notification_description.c_str());
1600 }
1601
Felipe Leme9a523ae2016-10-20 15:10:33 -07001602 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001603 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001604 }
1605
Felipe Leme2628e9e2016-04-12 16:36:51 -07001606 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001607 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001608 }
1609
Felipe Leme9a523ae2016-10-20 15:10:33 -07001610 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001611 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001612 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001613
Felipe Leme9a523ae2016-10-20 15:10:33 -07001614 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001615 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001616 }
1617
Felipe Lemed071c682016-10-20 16:48:00 -07001618 if (ds.version_ == VERSION_DEFAULT) {
1619 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001620 }
1621
Felipe Lemee184f662016-10-27 10:04:47 -07001622 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1623 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1624 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1625 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001626 exit(1);
1627 }
1628
1629 if (show_header_only) {
1630 ds.PrintHeader();
1631 exit(0);
1632 }
1633
Felipe Leme7447d7c2016-11-03 18:12:22 -07001634 /* redirect output if needed */
1635 bool is_redirecting = !use_socket && use_outfile;
1636
1637 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1638 std::string stats_path =
1639 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1640 : "";
1641 ds.progress_.reset(new Progress(stats_path));
1642
Felipe Lemed071c682016-10-20 16:48:00 -07001643 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001644 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001645 ds.id_ = ++last_id;
1646 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1647
1648 MYLOGI("begin\n");
1649
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001650 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001651
Felipe Leme75876a22016-10-27 16:31:27 -07001652 if (do_start_service) {
1653 MYLOGI("Starting 'dumpstate' service\n");
1654 android::status_t ret;
1655 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1656 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1657 }
1658 }
1659
Felipe Lemef0292972016-11-22 13:57:05 -08001660 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001661 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1662 }
1663
Felipe Leme7447d7c2016-11-03 18:12:22 -07001664 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001665 ds.extra_options_.c_str());
1666
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001667 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001668
Felipe Leme9a523ae2016-10-20 15:10:33 -07001669 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001670
Christopher Ferrised9354f2014-10-01 17:35:01 -07001671 // If we are going to use a socket, do it as early as possible
1672 // to avoid timeouts from bugreport.
1673 if (use_socket) {
1674 redirect_to_socket(stdout, "dumpstate");
1675 }
1676
Felipe Leme2628e9e2016-04-12 16:36:51 -07001677 if (use_control_socket) {
1678 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001679 ds.control_socket_fd_ = open_socket("dumpstate");
1680 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001681 }
1682
Felipe Leme71bbfc52015-11-23 14:14:51 -08001683 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001684 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001685 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001686 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001687 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1688 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001689 if (do_add_date) {
1690 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001691 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001692 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001693 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001694 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001695 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001696
1697 if (telephony_only) {
1698 ds.base_name_ += "-telephony";
1699 }
1700
Felipe Leme71bbfc52015-11-23 14:14:51 -08001701 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001702 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001703 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001704 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001705 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001706
Felipe Lemee844a9d2016-09-21 15:01:39 -07001707 MYLOGD(
1708 "Bugreport dir: %s\n"
1709 "Base name: %s\n"
1710 "Suffix: %s\n"
1711 "Log path: %s\n"
1712 "Temporary path: %s\n"
1713 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001714 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1715 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001716
Felipe Leme1e9edc62015-12-21 16:02:13 -08001717 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001718 ds.path_ = ds.GetPath(".zip");
1719 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1720 create_parent_dirs(ds.path_.c_str());
1721 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001722 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001723 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001724 do_zip_file = 0;
1725 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001726 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001727 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001728 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001729 }
1730
Felipe Leme9a523ae2016-10-20 15:10:33 -07001731 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001732 if (do_broadcast) {
1733 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001734
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001735 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001736 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001737 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001738 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001739 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001740 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001741 };
1742 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001743 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001744 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001745 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001746 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001747 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001748 }
1749 }
1750
Nick Kralevichf3599b32016-01-25 15:05:16 -08001751 /* read /proc/cmdline before dropping root */
1752 FILE *cmdline = fopen("/proc/cmdline", "re");
1753 if (cmdline) {
1754 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1755 fclose(cmdline);
1756 }
1757
John Michelau1f794c42012-09-17 11:20:19 -05001758 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001759 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001760 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001761
Felipe Leme9a523ae2016-10-20 15:10:33 -07001762 if (do_fb && ds.do_early_screenshot_) {
1763 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001764 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001765 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001766 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001767 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001768 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001769 }
1770 }
1771
Felipe Leme1e9edc62015-12-21 16:02:13 -08001772 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001773 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1774 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001775 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001776 }
1777 }
1778
Felipe Leme71bbfc52015-11-23 14:14:51 -08001779 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001780 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1781 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1782 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1783 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001784 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001785 /* TODO: rather than generating a text file now and zipping it later,
1786 it would be more efficient to redirect stdout to the zip entry
1787 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001788 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1789 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001790 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001791 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001792 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001793 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001794
1795 // Don't buffer stdout
1796 setvbuf(stdout, nullptr, _IONBF, 0);
1797
Felipe Leme608385d2016-02-01 10:35:38 -08001798 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1799 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001800 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001801 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001802
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001803 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001804 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001805 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001806 } else {
1807 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1808 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1809 // the raw trace.
1810 if (!dump_anrd_trace()) {
1811 dump_systrace();
1812 }
1813
1814 // Invoking the following dumpsys calls before dump_traces() to try and
1815 // keep the system stats as close to its initial state as possible.
1816 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1817 CommandOptions::WithTimeout(90).DropRoot().Build());
1818 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1819 CommandOptions::WithTimeout(10).DropRoot().Build());
1820
1821 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1822 dump_raft();
1823
1824 /* collect stack traces from Dalvik and native processes (needs root) */
1825 dump_traces_path = dump_traces();
1826
1827 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001828 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1829 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001830
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001831 ds.AddDir(RECOVERY_DIR, true);
1832 ds.AddDir(RECOVERY_DATA_DIR, true);
1833 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1834 if (!PropertiesHelper::IsUserBuild()) {
1835 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1836 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1837 }
1838 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001839 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001840
1841 // Capture any IPSec policies in play. No keys are exposed here.
1842 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1843 CommandOptions::WithTimeout(10).Build());
1844
1845 // Run ss as root so we can see socket marks.
1846 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1847 CommandOptions::WithTimeout(10).Build());
1848
1849 if (!DropRootUser()) {
1850 return -1;
1851 }
1852
1853 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001854 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001855
Felipe Leme55b42a62015-11-10 17:39:08 -08001856 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001857 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001858 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001859 }
1860
Felipe Leme6e01fa62015-11-11 19:35:14 -08001861 /* rename or zip the (now complete) .tmp file to its final location */
1862 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001863
1864 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001865 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001866 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001867 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001868 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001869 /* must whitelist which characters are allowed, otherwise it could cross directories */
1870 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001871 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001872 change_suffix = true;
1873 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001874 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001875 }
1876 }
1877 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001878 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1879 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001880 if (!ds.screenshot_path_.empty()) {
1881 std::string new_screenshot_path = ds.GetPath(".png");
1882 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1883 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1884 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001885 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001886 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001887 }
1888 }
1889 }
1890
Felipe Leme6e01fa62015-11-11 19:35:14 -08001891 bool do_text_file = true;
1892 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001893 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001894 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001895 do_text_file = true;
1896 } else {
1897 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001898 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001899 std::string new_path = ds.GetPath(".zip");
1900 if (ds.path_ != new_path) {
1901 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1902 if (rename(ds.path_.c_str(), new_path.c_str())) {
1903 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001904 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001905 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001906 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001907 }
1908 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001909 }
1910 }
1911 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001912 ds.path_ = ds.GetPath(".txt");
1913 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1914 ds.tmp_path_.c_str());
1915 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1916 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001917 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001918 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001919 }
1920 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001921 if (use_control_socket) {
1922 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001923 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001924 "FAIL:could not create zip file, check %s "
1925 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001926 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001927 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001928 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001929 }
1930 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001931 }
1932
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001933 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001934 for (int i = 0; i < 3; i++) {
1935 Vibrate(75);
1936 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001937 }
1938
Jeff Brown1dc94e32014-09-11 14:15:27 -07001939 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001940 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001941 if (!ds.path_.empty()) {
1942 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001943 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001944
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001945 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001946 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001947 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001948 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001949 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001950 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1951 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001952 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001953 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001954 if (do_fb) {
1955 am_args.push_back("--es");
1956 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001957 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001958 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001959 if (!ds.notification_title.empty()) {
1960 am_args.push_back("--es");
1961 am_args.push_back("android.intent.extra.TITLE");
1962 am_args.push_back(ds.notification_title);
1963 if (!ds.notification_description.empty()) {
1964 am_args.push_back("--es");
1965 am_args.push_back("android.intent.extra.DESCRIPTION");
1966 am_args.push_back(ds.notification_description);
1967 }
1968 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001969 if (is_remote_mode) {
1970 am_args.push_back("--es");
1971 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001972 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001973 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1974 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001975 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001976 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001977 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001978 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001979 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001980 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001981 }
1982
Felipe Leme7447d7c2016-11-03 18:12:22 -07001983 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1984 ds.progress_->GetInitialMax());
1985 ds.progress_->Save();
1986 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001987
Felipe Leme107a05f2016-03-08 15:11:15 -08001988 if (is_redirecting) {
1989 fclose(stderr);
1990 }
1991
Felipe Leme9a523ae2016-10-20 15:10:33 -07001992 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001993 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001994 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001995 }
1996
Colin Crossf45fa6b2012-03-26 12:38:26 -07001997 return 0;
1998}