blob: 4161bd79d9e44f59fa7a4b70b0bed4a159444042 [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) {
933 AddDumps(anr_data->begin() + 1, anr_data->end(),
934 "HISTORICAL ANR", add_to_zip);
935 }
936 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100937 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
938 }
939}
940
941static void AddAnrTraceFiles() {
942 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
943
944 std::string anr_traces_file;
945 std::string anr_traces_dir;
946 bool is_global_trace_file = true;
947
948 // First check whether the stack-trace-dir property is set. When it's set,
949 // each ANR trace will be written to a separate file and not to a global
950 // stack trace file.
951 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
952 if (anr_traces_dir.empty()) {
953 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
954 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100955 anr_traces_dir = dirname(anr_traces_file.c_str());
956 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100957 } else {
958 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100959 }
960
961 // We have neither configured a global trace file nor a trace directory,
962 // there will be nothing to dump.
963 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
964 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700965 return;
966 }
967
Narayan Kamath8f788292017-05-25 13:20:39 +0100968 if (is_global_trace_file) {
969 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
970 } else {
971 AddAnrTraceDir(add_to_zip, anr_traces_dir);
972 }
973
Felipe Lemee184f662016-10-27 10:04:47 -0700974 /* slow traces for slow operations */
975 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +0100976 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -0700977 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +0100978 while (true) {
979 const std::string slow_trace_path =
980 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
981 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -0700982 // No traces file at this index, done with the files.
983 break;
984 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100985 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -0700986 i++;
987 }
988 }
989}
990
Wei Wang509bb5d2017-06-09 14:42:12 -0700991static void DumpBlockStatFiles() {
992 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700993
Wei Wang1dc1ef52017-06-12 11:28:37 -0700994 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
995
996 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700997 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
998 return;
999 }
1000
1001 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001002 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001003 if ((d->d_name[0] == '.')
1004 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1005 || (d->d_name[1] == '\0'))) {
1006 continue;
1007 }
1008 const std::string new_path =
1009 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1010 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1011 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1012 printf("\n");
1013 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001014 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001015}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001016
1017static void DumpPacketStats() {
1018 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1019 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1020 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1021 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1022 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1023}
1024
1025static void DumpIpAddrAndRules() {
1026 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1027 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1028 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1029 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1030 RunCommand("IP RULES", {"ip", "rule", "show"});
1031 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1032}
1033
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001034static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001035 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001036
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001037 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001038 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001039 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001040 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001041 DumpFile("MEMORY INFO", "/proc/meminfo");
1042 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001043 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001044 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001045 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1046 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1047 DumpFile("SLAB INFO", "/proc/slabinfo");
1048 DumpFile("ZONEINFO", "/proc/zoneinfo");
1049 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1050 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1051 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001052
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001053 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1054 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1055 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001056
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001057 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001058 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemef0292972016-11-22 13:57:05 -08001059 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001060
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001061 if (ds.IsZipping()) {
1062 RunCommand(
1063 "HARDWARE HALS",
1064 {"lshal", std::string("--debug=") + kLsHalDebugPath},
1065 CommandOptions::AS_ROOT);
1066
1067 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1068
1069 unlink(kLsHalDebugPath.c_str());
1070 } else {
1071 RunCommand(
1072 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
1073 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001074
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001075 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001076 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001077 struct stat s;
1078 if (stat("/proc/modules", &s) != 0) {
1079 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1080 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001081 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001082 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001083
Colin Crossf45fa6b2012-03-26 12:38:26 -07001084 do_dmesg();
1085
Felipe Lemef0292972016-11-22 13:57:05 -08001086 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001087 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1088 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001089 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001090
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001091 /* Dump Bluetooth HCI logs */
1092 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001093
Felipe Leme9a523ae2016-10-20 15:10:33 -07001094 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001095 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001096 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001097 }
1098
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001099 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001100
Felipe Lemee184f662016-10-27 10:04:47 -07001101 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001102
Narayan Kamath8f788292017-05-25 13:20:39 +01001103 // NOTE: tombstones are always added as separate entries in the zip archive
1104 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001105 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1106 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001107 if (!tombstones_dumped) {
1108 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001109 }
1110
Jayachandran Ca94c7172017-06-10 15:08:12 -07001111 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001112
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001113 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001114
Jayachandran Ca94c7172017-06-10 15:08:12 -07001115 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001116
1117 dump_route_tables();
1118
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001119 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1120 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1121 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001122
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001123 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001124 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001125
Elliott Hughes23ccc622017-02-28 10:14:22 -08001126 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001127
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001128 RunCommand("VOLD DUMP", {"vdc", "dump"});
1129 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001130
Jin Qian24354422017-01-24 12:07:14 -08001131 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001132
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001133 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001136
Felipe Lemed8b94e52016-12-08 10:21:44 -08001137 printf("------ BACKLIGHTS ------\n");
1138 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001139 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001140 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001141 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001142 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001143 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001144 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001145 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001146 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001147 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001148 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001149
1150 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001151 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1152 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1153 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1154 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1155 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001156
Felipe Leme6f674ae2016-11-18 17:10:33 -08001157 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001158
Steven Moreland7440ddb2016-12-15 16:13:39 -08001159 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001160 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1161 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001162 // su does not exist on user builds, so try running without it.
1163 // This way any implementations of vril-dump that do not require
1164 // root can run on user builds.
1165 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001166 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001167 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001168 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001169 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001170 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001171 }
1172
Felipe Lemed8b94e52016-12-08 10:21:44 -08001173 printf("========================================================\n");
1174 printf("== Android Framework Services\n");
1175 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001176
Felipe Leme5bcce572016-09-27 09:21:08 -07001177 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1178 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001179
Felipe Lemed8b94e52016-12-08 10:21:44 -08001180 printf("========================================================\n");
1181 printf("== Checkins\n");
1182 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001183
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001184 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1185 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1186 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1187 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1188 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1189 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001190
Felipe Lemed8b94e52016-12-08 10:21:44 -08001191 printf("========================================================\n");
1192 printf("== Running Application Activities\n");
1193 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001194
Winson Chung1434a5c2017-02-28 17:09:24 -08001195 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001196
Felipe Lemed8b94e52016-12-08 10:21:44 -08001197 printf("========================================================\n");
1198 printf("== Running Application Services\n");
1199 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001200
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001201 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001202
Felipe Lemed8b94e52016-12-08 10:21:44 -08001203 printf("========================================================\n");
1204 printf("== Running Application Providers\n");
1205 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001206
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001207 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001208
Adrian Roos8b397ab2017-04-04 16:35:44 -07001209 printf("========================================================\n");
1210 printf("== Dropbox crashes\n");
1211 printf("========================================================\n");
1212
1213 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1214 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1215
Felipe Lemed8b94e52016-12-08 10:21:44 -08001216 printf("========================================================\n");
1217 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1218 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1219 printf("========================================================\n");
1220 printf("== dumpstate: done (id %d)\n", ds.id_);
1221 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001222}
1223
Jayachandran Ca94c7172017-06-10 15:08:12 -07001224// This method collects dumpsys for telephony debugging only
1225static void DumpstateTelephonyOnly() {
1226 DurationReporter duration_reporter("DUMPSTATE");
1227
1228 DumpIpTablesAsRoot();
1229
1230 if (!DropRootUser()) {
1231 return;
1232 }
1233
1234 do_dmesg();
1235 DoLogcat();
1236 DumpPacketStats();
1237 DoKmsg();
1238 DumpIpAddrAndRules();
1239 dump_route_tables();
1240
1241 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1242 CommandOptions::WithTimeout(10).Build());
1243
1244 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1245
1246 printf("========================================================\n");
1247 printf("== Android Framework Services\n");
1248 printf("========================================================\n");
1249
1250 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1251 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1252
1253 printf("========================================================\n");
1254 printf("== Running Application Services\n");
1255 printf("========================================================\n");
1256
1257 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1258
1259 printf("========================================================\n");
1260 printf("== dumpstate: done (id %d)\n", ds.id_);
1261 printf("========================================================\n");
1262}
1263
Felipe Leme6f674ae2016-11-18 17:10:33 -08001264void Dumpstate::DumpstateBoard() {
1265 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001266 printf("========================================================\n");
1267 printf("== Board\n");
1268 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001269
Chris Phoenix69d92212017-01-24 23:01:13 -08001270 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001271 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001272 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001273 return;
1274 }
1275
1276 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001277 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001278 return;
1279 }
1280
Jie Song9fbfad02017-06-20 16:29:42 -07001281 std::string path[NUM_OF_DUMPS];
1282 android::base::unique_fd fd[NUM_OF_DUMPS];
1283 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001284
Jie Song9fbfad02017-06-20 16:29:42 -07001285 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1286 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1287 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1288
1289 fd[i] = android::base::unique_fd(
1290 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1291 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1293 if (fd[i] < 0) {
1294 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1295 return;
1296 } else {
1297 numFds++;
1298 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001299 }
1300
Jie Song9fbfad02017-06-20 16:29:42 -07001301 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001302 if (handle == nullptr) {
1303 MYLOGE("Could not create native_handle\n");
1304 return;
1305 }
Jie Song9fbfad02017-06-20 16:29:42 -07001306
1307 for (int i = 0; i < numFds; i++) {
1308 handle->data[i] = fd[i].release();
1309 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001310
Felipe Lemef0292972016-11-22 13:57:05 -08001311 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001312 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1313 if (!status.isOk()) {
1314 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1315 native_handle_close(handle);
1316 native_handle_delete(handle);
1317 return;
1318 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001319
Jie Song9fbfad02017-06-20 16:29:42 -07001320 for (int i = 0; i < numFds; i++) {
1321 struct stat s;
1322 if (fstat(handle->data[i], &s) == -1) {
1323 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1324 } else if (s.st_size > 0) {
1325 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1326 } else {
1327 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1328 }
1329 }
1330
Felipe Lemed8b94e52016-12-08 10:21:44 -08001331 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001332
1333 native_handle_close(handle);
1334 native_handle_delete(handle);
1335
Jie Song9fbfad02017-06-20 16:29:42 -07001336 for (int i = 0; i < numFds; i++) {
1337 if (remove(path[i].c_str()) != 0) {
1338 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1339 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001340 }
1341}
1342
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001343static void ShowUsageAndExit(int exitCode = 1) {
1344 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001345 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001346 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1347 " -h: display this help message\n"
1348 " -b: play sound file instead of vibrate, at beginning of job\n"
1349 " -e: play sound file instead of vibrate, at end of job\n"
1350 " -o: write to file (instead of stdout)\n"
1351 " -d: append date to filename (requires -o)\n"
1352 " -p: capture screenshot to filename.png (requires -o)\n"
1353 " -z: generate zipped file (requires -o)\n"
1354 " -s: write output to control socket (for init)\n"
1355 " -S: write file location to control socket (for init; requires -o and -z)"
1356 " -q: disable vibrate\n"
1357 " -B: send broadcast when finished (requires -o)\n"
1358 " -P: send broadcast when started and update system properties on "
1359 "progress (requires -o and -B)\n"
1360 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1361 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001362 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001363 exit(exitCode);
1364}
1365
1366static void ExitOnInvalidArgs() {
1367 fprintf(stderr, "invalid combination of args\n");
1368 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001369}
1370
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001371static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001372 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001373}
1374
Wei Liuf87959e2016-08-26 14:51:42 -07001375static void register_sig_handler() {
1376 struct sigaction sa;
1377 sigemptyset(&sa.sa_mask);
1378 sa.sa_flags = 0;
1379 sa.sa_handler = sig_handler;
1380 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1381 sigaction(SIGSEGV, &sa, NULL); // segment fault
1382 sigaction(SIGINT, &sa, NULL); // ctrl-c
1383 sigaction(SIGTERM, &sa, NULL); // killed
1384 sigaction(SIGQUIT, &sa, NULL); // quit
1385}
1386
Felipe Leme1d486fe2016-10-14 18:06:47 -07001387bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001388 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001389 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001390 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001391 // Final timestamp
1392 char date[80];
1393 time_t the_real_now_please_stand_up = time(nullptr);
1394 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001395 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001396 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001397
Felipe Leme9a523ae2016-10-20 15:10:33 -07001398 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001399 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001400 return false;
1401 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001402 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001403 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001404 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001405 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001406
Felipe Leme0f3fb202016-06-10 17:10:53 -07001407 // Add log file (which contains stderr output) to zip...
1408 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001409 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001410 MYLOGE("Failed to add dumpstate log to .zip file\n");
1411 return false;
1412 }
1413 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001414 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001415 fprintf(stderr, "\n");
1416
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001417 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001418 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001419 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001420 return false;
1421 }
1422
Felipe Leme1d486fe2016-10-14 18:06:47 -07001423 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1424 ds.zip_file.reset(nullptr);
1425
Felipe Lemee9d2c542016-11-15 11:48:26 -08001426 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1427 if (remove(tmp_path_.c_str()) != 0) {
1428 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001429 }
1430
Felipe Leme1e9edc62015-12-21 16:02:13 -08001431 return true;
1432}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001433
Michal Karpinski4db754f2015-12-11 18:04:32 +00001434static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001435 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1436 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001437 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001438 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001439 return NULL;
1440 }
1441
1442 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001443 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001444
1445 std::vector<uint8_t> buffer(65536);
1446 while (1) {
1447 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1448 if (bytes_read == 0) {
1449 break;
1450 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001451 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001452 return NULL;
1453 }
1454
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001455 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001456 }
1457
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001458 uint8_t hash[SHA256_DIGEST_LENGTH];
1459 SHA256_Final(hash, &ctx);
1460
1461 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1462 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001463 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001464 }
1465 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1466 return std::string(hash_buffer);
1467}
1468
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001469static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1470 // clang-format off
1471 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1472 "--receiver-foreground", "--receiver-include-background", "-a", action};
1473 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001474
1475 am.insert(am.end(), args.begin(), args.end());
1476
Felipe Leme8d2410e2017-02-08 09:46:08 -08001477 RunCommand("", am,
1478 CommandOptions::WithTimeout(20)
1479 .Log("Sending broadcast: '%s'\n")
1480 .Always()
1481 .DropRoot()
1482 .RedirectStderr()
1483 .Build());
1484}
1485
Felipe Leme35b8cf12017-02-10 15:47:29 -08001486static void Vibrate(int duration_ms) {
1487 // clang-format off
1488 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1489 CommandOptions::WithTimeout(10)
1490 .Log("Vibrate: '%s'\n")
1491 .Always()
1492 .Build());
1493 // clang-format on
1494}
1495
Colin Crossf45fa6b2012-03-26 12:38:26 -07001496int main(int argc, char *argv[]) {
1497 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001498 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001499 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001500 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001501 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001502 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001503 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001504 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001505 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001506 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001507 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001508 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001509
Colin Crossf45fa6b2012-03-26 12:38:26 -07001510 /* set as high priority, and protect from OOM killer */
1511 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001512
Felipe Lemed071c682016-10-20 16:48:00 -07001513 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001514 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001515 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001516 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001517 } else {
1518 /* fallback to kernels <= 2.6.35 */
1519 oom_adj = fopen("/proc/self/oom_adj", "we");
1520 if (oom_adj) {
1521 fputs("-17", oom_adj);
1522 fclose(oom_adj);
1523 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001524 }
1525
Jeff Brown1dc94e32014-09-11 14:15:27 -07001526 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001527 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001528 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001529 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001530 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001531 case 'd': do_add_date = 1; break;
1532 case 'z': do_zip_file = 1; break;
1533 case 'o': use_outfile = optarg; break;
1534 case 's': use_socket = 1; break;
1535 case 'S': use_control_socket = 1; break;
1536 case 'v': show_header_only = true; break;
1537 case 'q': do_vibrate = 0; break;
1538 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001539 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001540 case 'R': is_remote_mode = 1; break;
1541 case 'B': do_broadcast = 1; break;
1542 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001543 case 'h':
1544 ShowUsageAndExit(0);
1545 break;
1546 default:
1547 fprintf(stderr, "Invalid option: %c\n", c);
1548 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001549 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001550 }
1551 }
1552
Felipe Lemed071c682016-10-20 16:48:00 -07001553 // TODO: use helper function to convert argv into a string
1554 for (int i = 0; i < argc; i++) {
1555 ds.args_ += argv[i];
1556 if (i < argc - 1) {
1557 ds.args_ += " ";
1558 }
1559 }
1560
1561 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001562 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001563 // Framework uses a system property to override some command-line args.
1564 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001565 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001566 // Currently, the dumpstate binder is only used by Shell to update progress.
1567 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001568 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001569 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001570 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001571 do_vibrate = 0;
1572 is_remote_mode = 1;
1573 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001574 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001575 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001576 } else if (ds.extra_options_ == "bugreporttelephony") {
1577 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001578 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001579 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001580 }
1581 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001582 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001583 }
1584
Naveen Kallab53a1c92017-03-16 18:17:25 -07001585 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1586 if (!ds.notification_title.empty()) {
1587 // Reset the property
1588 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1589
1590 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1591 if (!ds.notification_description.empty()) {
1592 // Reset the property
1593 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1594 }
1595 MYLOGD("notification (title: %s, description: %s)\n",
1596 ds.notification_title.c_str(), ds.notification_description.c_str());
1597 }
1598
Felipe Leme9a523ae2016-10-20 15:10:33 -07001599 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001600 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001601 }
1602
Felipe Leme2628e9e2016-04-12 16:36:51 -07001603 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001604 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001605 }
1606
Felipe Leme9a523ae2016-10-20 15:10:33 -07001607 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001608 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001609 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001610
Felipe Leme9a523ae2016-10-20 15:10:33 -07001611 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001612 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001613 }
1614
Felipe Lemed071c682016-10-20 16:48:00 -07001615 if (ds.version_ == VERSION_DEFAULT) {
1616 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001617 }
1618
Felipe Lemee184f662016-10-27 10:04:47 -07001619 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1620 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1621 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1622 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001623 exit(1);
1624 }
1625
1626 if (show_header_only) {
1627 ds.PrintHeader();
1628 exit(0);
1629 }
1630
Felipe Leme7447d7c2016-11-03 18:12:22 -07001631 /* redirect output if needed */
1632 bool is_redirecting = !use_socket && use_outfile;
1633
1634 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1635 std::string stats_path =
1636 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1637 : "";
1638 ds.progress_.reset(new Progress(stats_path));
1639
Felipe Lemed071c682016-10-20 16:48:00 -07001640 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001641 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001642 ds.id_ = ++last_id;
1643 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1644
1645 MYLOGI("begin\n");
1646
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001647 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001648
Felipe Leme75876a22016-10-27 16:31:27 -07001649 if (do_start_service) {
1650 MYLOGI("Starting 'dumpstate' service\n");
1651 android::status_t ret;
1652 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1653 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1654 }
1655 }
1656
Felipe Lemef0292972016-11-22 13:57:05 -08001657 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001658 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1659 }
1660
Felipe Leme7447d7c2016-11-03 18:12:22 -07001661 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001662 ds.extra_options_.c_str());
1663
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001664 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001665
Felipe Leme9a523ae2016-10-20 15:10:33 -07001666 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001667
Christopher Ferrised9354f2014-10-01 17:35:01 -07001668 // If we are going to use a socket, do it as early as possible
1669 // to avoid timeouts from bugreport.
1670 if (use_socket) {
1671 redirect_to_socket(stdout, "dumpstate");
1672 }
1673
Felipe Leme2628e9e2016-04-12 16:36:51 -07001674 if (use_control_socket) {
1675 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001676 ds.control_socket_fd_ = open_socket("dumpstate");
1677 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001678 }
1679
Felipe Leme71bbfc52015-11-23 14:14:51 -08001680 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001681 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001682 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001683 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001684 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1685 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001686 if (do_add_date) {
1687 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001688 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001689 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001690 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001691 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001692 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001693
1694 if (telephony_only) {
1695 ds.base_name_ += "-telephony";
1696 }
1697
Felipe Leme71bbfc52015-11-23 14:14:51 -08001698 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001699 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001700 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001701 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001702 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001703
Felipe Lemee844a9d2016-09-21 15:01:39 -07001704 MYLOGD(
1705 "Bugreport dir: %s\n"
1706 "Base name: %s\n"
1707 "Suffix: %s\n"
1708 "Log path: %s\n"
1709 "Temporary path: %s\n"
1710 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001711 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1712 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001713
Felipe Leme1e9edc62015-12-21 16:02:13 -08001714 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001715 ds.path_ = ds.GetPath(".zip");
1716 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1717 create_parent_dirs(ds.path_.c_str());
1718 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001719 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001720 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001721 do_zip_file = 0;
1722 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001723 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001724 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001725 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001726 }
1727
Felipe Leme9a523ae2016-10-20 15:10:33 -07001728 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001729 if (do_broadcast) {
1730 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001731
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001732 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001733 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001734 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001735 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001736 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001737 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001738 };
1739 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001740 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001741 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001742 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001743 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001744 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001745 }
1746 }
1747
Nick Kralevichf3599b32016-01-25 15:05:16 -08001748 /* read /proc/cmdline before dropping root */
1749 FILE *cmdline = fopen("/proc/cmdline", "re");
1750 if (cmdline) {
1751 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1752 fclose(cmdline);
1753 }
1754
John Michelau1f794c42012-09-17 11:20:19 -05001755 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001756 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001757 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001758
Felipe Leme9a523ae2016-10-20 15:10:33 -07001759 if (do_fb && ds.do_early_screenshot_) {
1760 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001761 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001762 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001763 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001764 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001765 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001766 }
1767 }
1768
Felipe Leme1e9edc62015-12-21 16:02:13 -08001769 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001770 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1771 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001772 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001773 }
1774 }
1775
Felipe Leme71bbfc52015-11-23 14:14:51 -08001776 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001777 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1778 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1779 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1780 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001781 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001782 /* TODO: rather than generating a text file now and zipping it later,
1783 it would be more efficient to redirect stdout to the zip entry
1784 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001785 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1786 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001787 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001788 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001789 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001790 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001791
1792 // Don't buffer stdout
1793 setvbuf(stdout, nullptr, _IONBF, 0);
1794
Felipe Leme608385d2016-02-01 10:35:38 -08001795 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1796 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001797 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001798 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001799
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001800 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001801 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001802 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001803 } else {
1804 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1805 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1806 // the raw trace.
1807 if (!dump_anrd_trace()) {
1808 dump_systrace();
1809 }
1810
1811 // Invoking the following dumpsys calls before dump_traces() to try and
1812 // keep the system stats as close to its initial state as possible.
1813 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1814 CommandOptions::WithTimeout(90).DropRoot().Build());
1815 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1816 CommandOptions::WithTimeout(10).DropRoot().Build());
1817
1818 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1819 dump_raft();
1820
1821 /* collect stack traces from Dalvik and native processes (needs root) */
1822 dump_traces_path = dump_traces();
1823
1824 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001825 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1826 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001827
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001828 ds.AddDir(RECOVERY_DIR, true);
1829 ds.AddDir(RECOVERY_DATA_DIR, true);
1830 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1831 if (!PropertiesHelper::IsUserBuild()) {
1832 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1833 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1834 }
1835 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001836 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001837
1838 // Capture any IPSec policies in play. No keys are exposed here.
1839 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1840 CommandOptions::WithTimeout(10).Build());
1841
1842 // Run ss as root so we can see socket marks.
1843 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1844 CommandOptions::WithTimeout(10).Build());
1845
1846 if (!DropRootUser()) {
1847 return -1;
1848 }
1849
1850 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001851 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001852
Felipe Leme55b42a62015-11-10 17:39:08 -08001853 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001854 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001855 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001856 }
1857
Felipe Leme6e01fa62015-11-11 19:35:14 -08001858 /* rename or zip the (now complete) .tmp file to its final location */
1859 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001860
1861 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001862 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001863 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001864 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001865 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001866 /* must whitelist which characters are allowed, otherwise it could cross directories */
1867 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001868 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001869 change_suffix = true;
1870 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001871 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001872 }
1873 }
1874 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001875 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1876 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001877 if (!ds.screenshot_path_.empty()) {
1878 std::string new_screenshot_path = ds.GetPath(".png");
1879 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1880 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1881 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001882 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001883 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001884 }
1885 }
1886 }
1887
Felipe Leme6e01fa62015-11-11 19:35:14 -08001888 bool do_text_file = true;
1889 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001890 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001891 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001892 do_text_file = true;
1893 } else {
1894 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001895 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001896 std::string new_path = ds.GetPath(".zip");
1897 if (ds.path_ != new_path) {
1898 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1899 if (rename(ds.path_.c_str(), new_path.c_str())) {
1900 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001901 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001902 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001903 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001904 }
1905 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001906 }
1907 }
1908 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001909 ds.path_ = ds.GetPath(".txt");
1910 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1911 ds.tmp_path_.c_str());
1912 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1913 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001914 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001915 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001916 }
1917 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001918 if (use_control_socket) {
1919 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001920 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001921 "FAIL:could not create zip file, check %s "
1922 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001923 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001924 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001925 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001926 }
1927 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001928 }
1929
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001930 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001931 for (int i = 0; i < 3; i++) {
1932 Vibrate(75);
1933 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001934 }
1935
Jeff Brown1dc94e32014-09-11 14:15:27 -07001936 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001937 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001938 if (!ds.path_.empty()) {
1939 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001940 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001941
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001942 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001943 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001944 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001945 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001946 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001947 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1948 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001949 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001950 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001951 if (do_fb) {
1952 am_args.push_back("--es");
1953 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001954 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001955 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001956 if (!ds.notification_title.empty()) {
1957 am_args.push_back("--es");
1958 am_args.push_back("android.intent.extra.TITLE");
1959 am_args.push_back(ds.notification_title);
1960 if (!ds.notification_description.empty()) {
1961 am_args.push_back("--es");
1962 am_args.push_back("android.intent.extra.DESCRIPTION");
1963 am_args.push_back(ds.notification_description);
1964 }
1965 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001966 if (is_remote_mode) {
1967 am_args.push_back("--es");
1968 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001969 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001970 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1971 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001972 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001973 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001974 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001975 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001976 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001977 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001978 }
1979
Felipe Leme7447d7c2016-11-03 18:12:22 -07001980 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1981 ds.progress_->GetInitialMax());
1982 ds.progress_->Save();
1983 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001984
Felipe Leme107a05f2016-03-08 15:11:15 -08001985 if (is_redirecting) {
1986 fclose(stderr);
1987 }
1988
Felipe Leme9a523ae2016-10-20 15:10:33 -07001989 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001990 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001991 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001992 }
1993
Colin Crossf45fa6b2012-03-26 12:38:26 -07001994 return 0;
1995}