blob: 9e77e8fbcb994c75b7bd4ee3ec73c91678094a43 [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",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700129 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700130};
131static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
132
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700133static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800134
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700135static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700136static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700137static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700138static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
139static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700140
Felipe Lemef0292972016-11-22 13:57:05 -0800141static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
142
Narayan Kamath8f788292017-05-25 13:20:39 +0100143/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100144 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
145 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
146 * is set, the vector only contains files that were written in the last 30 minutes.
Narayan Kamath8f788292017-05-25 13:20:39 +0100147 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100148static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
149 const std::string& file_prefix,
150 bool limit_by_mtime) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100151 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
152
Narayan Kamath8f788292017-05-25 13:20:39 +0100153 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100154 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100155
Narayan Kamathbd863722017-06-01 18:50:12 +0100156 struct dirent* entry = nullptr;
157 while ((entry = readdir(dump_dir.get()))) {
158 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100159 continue;
160 }
161
Narayan Kamathbd863722017-06-01 18:50:12 +0100162 const std::string base_name(entry->d_name);
163 if (base_name.find(file_prefix) != 0) {
164 continue;
165 }
166
167 const std::string abs_path = dir_path + base_name;
168 android::base::unique_fd fd(
169 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
170 if (fd == -1) {
171 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
172 break;
173 }
174
175 struct stat st = {};
176 if (fstat(fd, &st) == -1) {
177 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100178 continue;
179 }
180
181 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100182 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100183 continue;
184 }
185
Narayan Kamathbd863722017-06-01 18:50:12 +0100186 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100187
188 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700189 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100190
191 std::sort(dump_data->begin(), dump_data->end());
192
193 return dump_data.release();
194}
195
Narayan Kamathbd863722017-06-01 18:50:12 +0100196static bool AddDumps(const std::vector<DumpData>::const_iterator start,
197 const std::vector<DumpData>::const_iterator end,
198 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100199 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100200 for (auto it = start; it != end; ++it) {
201 const std::string& name = it->name;
202 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100203 dumped = true;
204 if (ds.IsZipping() && add_to_zip) {
205 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
206 MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
207 }
208 } else {
209 dump_file_from_fd(type_name, name.c_str(), fd);
210 }
211
212 close(fd);
213 }
214
215 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700216}
217
Felipe Leme635ca312016-01-05 14:23:02 -0800218// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700219void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800220 char path[PATH_MAX];
221
222 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
223 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700224 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800225 char linkname[PATH_MAX];
226 ssize_t r = readlink(path, linkname, PATH_MAX);
227 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800228 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800229 return;
230 }
231 linkname[r] = '\0';
232
233 if (mount_points.find(linkname) == mount_points.end()) {
234 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700235 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700236 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800237 mount_points.insert(linkname);
238 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800239 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800240 }
241 }
242}
243
244void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700245 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700246 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800247 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800248 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700249 for_each_pid(do_mountinfo, nullptr);
250 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800251}
252
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700253static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
254{
255 DIR *d;
256 struct dirent *de;
257 char path[PATH_MAX];
258
259 d = opendir(driverpath);
260 if (d == NULL) {
261 return;
262 }
263
264 while ((de = readdir(d))) {
265 if (de->d_type != DT_LNK) {
266 continue;
267 }
268 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700269 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700270 }
271
272 closedir(d);
273}
274
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700275
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700276
277// dump anrd's trace and add to the zip file.
278// 1. check if anrd is running on this device.
279// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
280// 3. wait until the trace generation completes and add to the zip file.
281static bool dump_anrd_trace() {
282 unsigned int pid;
283 char buf[50], path[PATH_MAX];
284 struct dirent *trace;
285 struct stat st;
286 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700287 int retry = 5;
288 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700289 long long cur_size = 0;
290 const char *trace_path = "/data/misc/anrd/";
291
Felipe Leme1d486fe2016-10-14 18:06:47 -0700292 if (!ds.IsZipping()) {
293 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700294 return false;
295 }
296
297 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700298 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700299
300 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700301 if (stat(trace_path, &st) == 0) {
302 old_mtime = st.st_mtime;
303 } else {
304 MYLOGE("Failed to find: %s\n", trace_path);
305 return false;
306 }
307
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700308 // send SIGUSR1 to the anrd to generate a trace.
309 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700310 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700311 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700312 MYLOGE("anrd signal timed out. Please manually collect trace\n");
313 return false;
314 }
315
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700316 while (retry-- > 0 && old_mtime == st.st_mtime) {
317 sleep(1);
318 stat(trace_path, &st);
319 }
320
321 if (retry < 0 && old_mtime == st.st_mtime) {
322 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
323 return false;
324 }
325
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700326 // identify the trace file by its creation time.
327 if (!(trace_dir = opendir(trace_path))) {
328 MYLOGE("Can't open trace file under %s\n", trace_path);
329 }
330 while ((trace = readdir(trace_dir))) {
331 if (strcmp(trace->d_name, ".") == 0
332 || strcmp(trace->d_name, "..") == 0) {
333 continue;
334 }
335 sprintf(path, "%s%s", trace_path, trace->d_name);
336 if (stat(path, &st) == 0) {
337 if (st.st_ctime > max_ctime) {
338 max_ctime = st.st_ctime;
339 sprintf(buf, "%s", trace->d_name);
340 }
341 }
342 }
343 closedir(trace_dir);
344
345 // Wait until the dump completes by checking the size of the trace.
346 if (max_ctime > 0) {
347 sprintf(path, "%s%s", trace_path, buf);
348 while(true) {
349 sleep(1);
350 if (stat(path, &st) == 0) {
351 if (st.st_size == cur_size) {
352 break;
353 } else if (st.st_size > cur_size) {
354 cur_size = st.st_size;
355 } else {
356 return false;
357 }
358 } else {
359 MYLOGE("Cant stat() %s anymore\n", path);
360 return false;
361 }
362 }
363 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700364 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700365 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
366 } else {
367 if (remove(path)) {
368 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
369 }
370 return true;
371 }
372 } else {
373 MYLOGE("Can't stats any trace file under %s\n", trace_path);
374 }
375 }
376 return false;
377}
378
Felipe Lemeefd7e272016-05-18 09:27:16 -0700379static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700380 if (!ds.IsZipping()) {
381 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700382 return;
383 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700384 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700385 if (systrace_path.empty()) {
386 MYLOGE("Not dumping systrace because path is empty\n");
387 return;
388 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700389 const char* path = "/sys/kernel/debug/tracing/tracing_on";
390 long int is_tracing;
391 if (read_file_as_long(path, &is_tracing)) {
392 return; // error already logged
393 }
394 if (is_tracing <= 0) {
395 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
396 return;
397 }
398
Felipe Leme14e034a2016-03-30 18:51:03 -0700399 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
400 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700401 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700402 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700403 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700404 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700405 // peacefully; ideally, we should call strace to stop itself, but there is no such option
406 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700407 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700408 // MYLOGE("could not stop systrace ");
409 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700410 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700411 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700412 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700413 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700414 if (remove(systrace_path.c_str())) {
415 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
416 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700417 }
418}
419
Felipe Lemeefd7e272016-05-18 09:27:16 -0700420static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800421 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700422 return;
423 }
424
Felipe Leme1d486fe2016-10-14 18:06:47 -0700425 std::string raft_path = ds.GetPath("-raft_log.txt");
426 if (raft_path.empty()) {
427 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700428 return;
429 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700430
431 struct stat s;
432 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
433 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
434 return;
435 }
436
Felipe Leme30dbfa12016-09-02 12:43:26 -0700437 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700438 if (!ds.IsZipping()) {
439 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700440 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700441 return;
442 }
443
Felipe Leme1d486fe2016-10-14 18:06:47 -0700444 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
445 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
446 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700447 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 if (remove(raft_path.c_str())) {
449 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700450 }
451 }
452}
453
Mark Salyzyn326842f2015-04-30 09:49:41 -0700454static bool skip_not_stat(const char *path) {
455 static const char stat[] = "/stat";
456 size_t len = strlen(path);
457 if (path[len - 1] == '/') { /* Directory? */
458 return false;
459 }
460 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
461}
462
Felipe Leme4c2d6632016-09-28 14:32:00 -0700463static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800464 return false;
465}
466
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700467unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700468
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800469//
470// stat offsets
471// Name units description
472// ---- ----- -----------
473// read I/Os requests number of read I/Os processed
474#define __STAT_READ_IOS 0
475// read merges requests number of read I/Os merged with in-queue I/O
476#define __STAT_READ_MERGES 1
477// read sectors sectors number of sectors read
478#define __STAT_READ_SECTORS 2
479// read ticks milliseconds total wait time for read requests
480#define __STAT_READ_TICKS 3
481// write I/Os requests number of write I/Os processed
482#define __STAT_WRITE_IOS 4
483// write merges requests number of write I/Os merged with in-queue I/O
484#define __STAT_WRITE_MERGES 5
485// write sectors sectors number of sectors written
486#define __STAT_WRITE_SECTORS 6
487// write ticks milliseconds total wait time for write requests
488#define __STAT_WRITE_TICKS 7
489// in_flight requests number of I/Os currently in flight
490#define __STAT_IN_FLIGHT 8
491// io_ticks milliseconds total time this block device has been active
492#define __STAT_IO_TICKS 9
493// time_in_queue milliseconds total wait time for all requests
494#define __STAT_IN_QUEUE 10
495#define __STAT_NUMBER_FIELD 11
496//
497// read I/Os, write I/Os
498// =====================
499//
500// These values increment when an I/O request completes.
501//
502// read merges, write merges
503// =========================
504//
505// These values increment when an I/O request is merged with an
506// already-queued I/O request.
507//
508// read sectors, write sectors
509// ===========================
510//
511// These values count the number of sectors read from or written to this
512// block device. The "sectors" in question are the standard UNIX 512-byte
513// sectors, not any device- or filesystem-specific block size. The
514// counters are incremented when the I/O completes.
515#define SECTOR_SIZE 512
516//
517// read ticks, write ticks
518// =======================
519//
520// These values count the number of milliseconds that I/O requests have
521// waited on this block device. If there are multiple I/O requests waiting,
522// these values will increase at a rate greater than 1000/second; for
523// example, if 60 read requests wait for an average of 30 ms, the read_ticks
524// field will increase by 60*30 = 1800.
525//
526// in_flight
527// =========
528//
529// This value counts the number of I/O requests that have been issued to
530// the device driver but have not yet completed. It does not include I/O
531// requests that are in the queue but not yet issued to the device driver.
532//
533// io_ticks
534// ========
535//
536// This value counts the number of milliseconds during which the device has
537// had I/O requests queued.
538//
539// time_in_queue
540// =============
541//
542// This value counts the number of milliseconds that I/O requests have waited
543// on this block device. If there are multiple I/O requests waiting, this
544// value will increase as the product of the number of milliseconds times the
545// number of requests waiting (see "read ticks" above for an example).
546#define S_TO_MS 1000
547//
548
Mark Salyzyn326842f2015-04-30 09:49:41 -0700549static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800550 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700551 bool z;
552 char *cp, *buffer = NULL;
553 size_t i = 0;
554 FILE *fp = fdopen(fd, "rb");
555 getline(&buffer, &i, fp);
556 fclose(fp);
557 if (!buffer) {
558 return -errno;
559 }
560 i = strlen(buffer);
561 while ((i > 0) && (buffer[i - 1] == '\n')) {
562 buffer[--i] = '\0';
563 }
564 if (!*buffer) {
565 free(buffer);
566 return 0;
567 }
568 z = true;
569 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800570 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700571 if (fields[i] != 0) {
572 z = false;
573 }
574 }
575 if (z) { /* never accessed */
576 free(buffer);
577 return 0;
578 }
579
Wei Wang509bb5d2017-06-09 14:42:12 -0700580 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
581 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700582 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700583
584 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
585 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
586 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700587 free(buffer);
588
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800589 if (fields[__STAT_IO_TICKS]) {
590 unsigned long read_perf = 0;
591 unsigned long read_ios = 0;
592 if (fields[__STAT_READ_TICKS]) {
593 unsigned long long divisor = fields[__STAT_READ_TICKS]
594 * fields[__STAT_IO_TICKS];
595 read_perf = ((unsigned long long)SECTOR_SIZE
596 * fields[__STAT_READ_SECTORS]
597 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
598 / divisor;
599 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
600 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
601 / divisor;
602 }
603
604 unsigned long write_perf = 0;
605 unsigned long write_ios = 0;
606 if (fields[__STAT_WRITE_TICKS]) {
607 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
608 * fields[__STAT_IO_TICKS];
609 write_perf = ((unsigned long long)SECTOR_SIZE
610 * fields[__STAT_WRITE_SECTORS]
611 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
612 / divisor;
613 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
614 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
615 / divisor;
616 }
617
618 unsigned queue = (fields[__STAT_IN_QUEUE]
619 + (fields[__STAT_IO_TICKS] >> 1))
620 / fields[__STAT_IO_TICKS];
621
622 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700623 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 -0800624 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700625 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 -0800626 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800627 }
628
629 /* bugreport timeout factor adjustment */
630 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
631 worst_write_perf = write_perf;
632 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700633 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700634 return 0;
635}
636
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700637/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800638static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700639 log_id_t id = android_name_to_log_id(name);
640 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700641 /* Engineering margin is ten-fold our guess */
642 return 10 * (property_size + worst_write_perf) / worst_write_perf;
643}
644
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700645void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700646 std::string build, fingerprint, radio, bootloader, network;
647 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700648
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700649 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
650 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700651 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
652 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
653 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700654 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700655
Felipe Lemed8b94e52016-12-08 10:21:44 -0800656 printf("========================================================\n");
657 printf("== dumpstate: %s\n", date);
658 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700659
Felipe Lemed8b94e52016-12-08 10:21:44 -0800660 printf("\n");
661 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700662 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800663 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
664 printf("Bootloader: %s\n", bootloader.c_str());
665 printf("Radio: %s\n", radio.c_str());
666 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700667
Felipe Lemed8b94e52016-12-08 10:21:44 -0800668 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800669 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800670 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
671 printf("Bugreport format version: %s\n", version_.c_str());
672 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
673 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
674 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800675}
676
Felipe Leme24b66ee2016-06-16 10:55:26 -0700677// List of file extensions that can cause a zip file attachment to be rejected by some email
678// service providers.
679static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
680 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
681 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
682 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
683};
684
Felipe Leme1d486fe2016-10-14 18:06:47 -0700685bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
686 if (!IsZipping()) {
687 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
688 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800689 return false;
690 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700691 std::string valid_name = entry_name;
692
693 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700694 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700695 if (idx != std::string::npos) {
696 std::string extension = entry_name.substr(idx);
697 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
698 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
699 valid_name = entry_name + ".renamed";
700 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
701 }
702 }
703
Felipe Leme6fe9db62016-02-12 09:04:16 -0800704 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
705 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700706 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
707 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700708 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700709 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700710 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800711 return false;
712 }
713
Felipe Leme770410d2016-01-26 17:07:14 -0800714 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800715 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400716 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800717 if (bytes_read == 0) {
718 break;
719 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800720 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800721 return false;
722 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700723 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800724 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700725 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800726 return false;
727 }
728 }
729
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700730 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700731 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700732 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800733 return false;
734 }
735
736 return true;
737}
738
Felipe Leme1d486fe2016-10-14 18:06:47 -0700739bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
740 android::base::unique_fd fd(
741 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700742 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800743 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800744 return false;
745 }
746
Felipe Leme1d486fe2016-10-14 18:06:47 -0700747 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800748}
749
750/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700751static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700752 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800753}
754
Felipe Leme1d486fe2016-10-14 18:06:47 -0700755void Dumpstate::AddDir(const std::string& dir, bool recursive) {
756 if (!IsZipping()) {
757 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800758 return;
759 }
Felipe Leme678727a2016-09-21 17:22:11 -0700760 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800761 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700762 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800763}
764
Felipe Leme1d486fe2016-10-14 18:06:47 -0700765bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
766 if (!IsZipping()) {
767 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
768 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800769 return false;
770 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800771 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700772 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700773 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700774 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700775 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800776 return false;
777 }
778
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700779 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700780 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700781 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700782 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800783 return false;
784 }
785
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700786 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700787 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700788 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800789 return false;
790 }
791
792 return true;
793}
794
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800795static void DoKmsg() {
796 struct stat st;
797 if (!stat(PSTORE_LAST_KMSG, &st)) {
798 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
799 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
800 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
801 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
802 } else {
803 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
804 DumpFile("LAST KMSG", "/proc/last_kmsg");
805 }
806}
807
808static void DoLogcat() {
809 unsigned long timeout;
810 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
811 // calculate timeout
812 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
813 if (timeout < 20000) {
814 timeout = 20000;
815 }
Tony Makae737652017-03-30 17:47:09 +0100816 RunCommand("SYSTEM LOG",
817 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
818 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800819 CommandOptions::WithTimeout(timeout / 1000).Build());
820 timeout = logcat_timeout("events");
821 if (timeout < 20000) {
822 timeout = 20000;
823 }
824 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100825 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
826 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800827 CommandOptions::WithTimeout(timeout / 1000).Build());
828 timeout = logcat_timeout("radio");
829 if (timeout < 20000) {
830 timeout = 20000;
831 }
832 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100833 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
834 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800835 CommandOptions::WithTimeout(timeout / 1000).Build());
836
837 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
838
839 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
840 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100841 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
842 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800843}
844
Jayachandran Ca94c7172017-06-10 15:08:12 -0700845static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700846 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
847 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900848 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700849 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900850 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
851 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
852 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
853 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700854}
855
Narayan Kamath8f788292017-05-25 13:20:39 +0100856static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
857 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700858 std::string dump_traces_dir;
859
Felipe Lemee184f662016-10-27 10:04:47 -0700860 if (dump_traces_path != nullptr) {
861 if (add_to_zip) {
862 dump_traces_dir = dirname(dump_traces_path);
863 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
864 ds.AddDir(dump_traces_dir, true);
865 } else {
866 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
867 dump_traces_path);
868 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
869 }
870 }
871
Felipe Lemee184f662016-10-27 10:04:47 -0700872
873 // Make sure directory is not added twice.
874 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
875 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
876 // property - but in reality they're the same path (although the former could be nullptr).
877 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
878 // be revisited.
879 bool already_dumped = anr_traces_dir == dump_traces_dir;
880
Narayan Kamath8f788292017-05-25 13:20:39 +0100881 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700882 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
883
Narayan Kamath8f788292017-05-25 13:20:39 +0100884 int fd = TEMP_FAILURE_RETRY(
885 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
886 if (fd < 0) {
887 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700888 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100889 if (add_to_zip) {
890 if (!already_dumped) {
891 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
892 anr_traces_dir.c_str());
893 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700894 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100895 } else {
896 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
897 anr_traces_file.c_str());
898 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
899 }
900 }
901}
902
903static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
904 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
905 anr_traces_dir.c_str());
906
907 // If we're here, dump_traces_path will always be a temporary file
908 // (created with mkostemp or similar) that contains dumps taken earlier
909 // on in the process.
910 if (dump_traces_path != nullptr) {
911 if (add_to_zip) {
912 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
913 } else {
914 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
915 dump_traces_path);
916 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
917 }
918
919 const int ret = unlink(dump_traces_path);
920 if (ret == -1) {
921 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
922 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700923 }
924 }
925
Narayan Kamathbd863722017-06-01 18:50:12 +0100926 // Add a specific message for the first ANR Dump.
927 if (anr_data->size() > 0) {
928 AddDumps(anr_data->begin(), anr_data->begin() + 1,
929 "VM TRACES AT LAST ANR", add_to_zip);
930
931 if (anr_data->size() > 1) {
Narayan Kamath8cbab7c2017-07-27 11:21:07 +0100932 // NOTE: Historical ANRs are always added as separate entries in the
933 // bugreport zip file.
Narayan Kamathbd863722017-06-01 18:50:12 +0100934 AddDumps(anr_data->begin() + 1, anr_data->end(),
Narayan Kamath8cbab7c2017-07-27 11:21:07 +0100935 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100936 }
937 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100938 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
939 }
940}
941
942static void AddAnrTraceFiles() {
943 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
944
945 std::string anr_traces_file;
946 std::string anr_traces_dir;
947 bool is_global_trace_file = true;
948
949 // First check whether the stack-trace-dir property is set. When it's set,
950 // each ANR trace will be written to a separate file and not to a global
951 // stack trace file.
952 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
953 if (anr_traces_dir.empty()) {
954 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
955 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100956 anr_traces_dir = dirname(anr_traces_file.c_str());
957 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100958 } else {
959 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100960 }
961
962 // We have neither configured a global trace file nor a trace directory,
963 // there will be nothing to dump.
964 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
965 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700966 return;
967 }
968
Narayan Kamath8f788292017-05-25 13:20:39 +0100969 if (is_global_trace_file) {
970 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
971 } else {
972 AddAnrTraceDir(add_to_zip, anr_traces_dir);
973 }
974
Felipe Lemee184f662016-10-27 10:04:47 -0700975 /* slow traces for slow operations */
976 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +0100977 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -0700978 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +0100979 while (true) {
980 const std::string slow_trace_path =
981 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
982 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -0700983 // No traces file at this index, done with the files.
984 break;
985 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100986 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -0700987 i++;
988 }
989 }
990}
991
Wei Wang509bb5d2017-06-09 14:42:12 -0700992static void DumpBlockStatFiles() {
993 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -0700994
Wei Wang1dc1ef52017-06-12 11:28:37 -0700995 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
996
997 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -0700998 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
999 return;
1000 }
1001
1002 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001003 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001004 if ((d->d_name[0] == '.')
1005 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1006 || (d->d_name[1] == '\0'))) {
1007 continue;
1008 }
1009 const std::string new_path =
1010 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1011 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1012 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1013 printf("\n");
1014 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001015 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001016}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001017
1018static void DumpPacketStats() {
1019 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1020 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1021 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1022 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1023 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1024}
1025
1026static void DumpIpAddrAndRules() {
1027 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1028 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1029 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1030 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1031 RunCommand("IP RULES", {"ip", "rule", "show"});
1032 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1033}
1034
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001035static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001036 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001037
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001038 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001039 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001040 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001041 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001042 DumpFile("MEMORY INFO", "/proc/meminfo");
1043 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001044 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001045 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001046 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1047 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1048 DumpFile("SLAB INFO", "/proc/slabinfo");
1049 DumpFile("ZONEINFO", "/proc/zoneinfo");
1050 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1051 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1052 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001053
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001054 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1055 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1056 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001057
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001058 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001059 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemef0292972016-11-22 13:57:05 -08001060 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001061
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001062 if (ds.IsZipping()) {
1063 RunCommand(
1064 "HARDWARE HALS",
1065 {"lshal", std::string("--debug=") + kLsHalDebugPath},
1066 CommandOptions::AS_ROOT);
1067
1068 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1069
1070 unlink(kLsHalDebugPath.c_str());
1071 } else {
1072 RunCommand(
1073 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
1074 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001075
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001076 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001077 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001078 struct stat s;
1079 if (stat("/proc/modules", &s) != 0) {
1080 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1081 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001082 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001083 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001084
Colin Crossf45fa6b2012-03-26 12:38:26 -07001085 do_dmesg();
1086
Felipe Lemef0292972016-11-22 13:57:05 -08001087 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001088 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1089 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001090 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001091
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001092 /* Dump Bluetooth HCI logs */
1093 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001094
Felipe Leme9a523ae2016-10-20 15:10:33 -07001095 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001096 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001097 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001098 }
1099
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001100 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001101
Felipe Lemee184f662016-10-27 10:04:47 -07001102 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001103
Narayan Kamath8f788292017-05-25 13:20:39 +01001104 // NOTE: tombstones are always added as separate entries in the zip archive
1105 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001106 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1107 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001108 if (!tombstones_dumped) {
1109 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001110 }
1111
Jayachandran Ca94c7172017-06-10 15:08:12 -07001112 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001113
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001114 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001115
Jayachandran Ca94c7172017-06-10 15:08:12 -07001116 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001117
1118 dump_route_tables();
1119
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001120 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1121 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1122 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001123
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001124 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001125 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001126
Elliott Hughes23ccc622017-02-28 10:14:22 -08001127 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001128
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001129 RunCommand("VOLD DUMP", {"vdc", "dump"});
1130 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001131
Jin Qian24354422017-01-24 12:07:14 -08001132 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001133
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001134 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001135
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001136 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001137
Felipe Lemed8b94e52016-12-08 10:21:44 -08001138 printf("------ BACKLIGHTS ------\n");
1139 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001140 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001141 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001142 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001143 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001144 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001145 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001146 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001147 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001148 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001149 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001150
1151 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001152 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1153 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1154 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1155 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1156 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001157
Felipe Leme6f674ae2016-11-18 17:10:33 -08001158 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001159
Steven Moreland7440ddb2016-12-15 16:13:39 -08001160 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001161 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1162 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001163 // su does not exist on user builds, so try running without it.
1164 // This way any implementations of vril-dump that do not require
1165 // root can run on user builds.
1166 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001167 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001168 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001169 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001170 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001171 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001172 }
1173
Felipe Lemed8b94e52016-12-08 10:21:44 -08001174 printf("========================================================\n");
1175 printf("== Android Framework Services\n");
1176 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001177
Felipe Leme5bcce572016-09-27 09:21:08 -07001178 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1179 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001180
Felipe Lemed8b94e52016-12-08 10:21:44 -08001181 printf("========================================================\n");
1182 printf("== Checkins\n");
1183 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001184
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001185 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1186 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1187 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1188 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1189 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1190 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001191
Felipe Lemed8b94e52016-12-08 10:21:44 -08001192 printf("========================================================\n");
1193 printf("== Running Application Activities\n");
1194 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001195
Winson Chung1434a5c2017-02-28 17:09:24 -08001196 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001197
Felipe Lemed8b94e52016-12-08 10:21:44 -08001198 printf("========================================================\n");
1199 printf("== Running Application Services\n");
1200 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001201
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001202 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001203
Felipe Lemed8b94e52016-12-08 10:21:44 -08001204 printf("========================================================\n");
1205 printf("== Running Application Providers\n");
1206 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001207
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001208 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001209
Adrian Roos8b397ab2017-04-04 16:35:44 -07001210 printf("========================================================\n");
1211 printf("== Dropbox crashes\n");
1212 printf("========================================================\n");
1213
1214 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1215 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1216
Felipe Lemed8b94e52016-12-08 10:21:44 -08001217 printf("========================================================\n");
1218 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1219 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1220 printf("========================================================\n");
1221 printf("== dumpstate: done (id %d)\n", ds.id_);
1222 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001223}
1224
Jayachandran Ca94c7172017-06-10 15:08:12 -07001225// This method collects dumpsys for telephony debugging only
1226static void DumpstateTelephonyOnly() {
1227 DurationReporter duration_reporter("DUMPSTATE");
1228
1229 DumpIpTablesAsRoot();
1230
1231 if (!DropRootUser()) {
1232 return;
1233 }
1234
1235 do_dmesg();
1236 DoLogcat();
1237 DumpPacketStats();
1238 DoKmsg();
1239 DumpIpAddrAndRules();
1240 dump_route_tables();
1241
1242 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1243 CommandOptions::WithTimeout(10).Build());
1244
1245 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1246
1247 printf("========================================================\n");
1248 printf("== Android Framework Services\n");
1249 printf("========================================================\n");
1250
1251 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1252 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1253
1254 printf("========================================================\n");
1255 printf("== Running Application Services\n");
1256 printf("========================================================\n");
1257
1258 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1259
1260 printf("========================================================\n");
1261 printf("== dumpstate: done (id %d)\n", ds.id_);
1262 printf("========================================================\n");
1263}
1264
Felipe Leme6f674ae2016-11-18 17:10:33 -08001265void Dumpstate::DumpstateBoard() {
1266 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001267 printf("========================================================\n");
1268 printf("== Board\n");
1269 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001270
Chris Phoenix69d92212017-01-24 23:01:13 -08001271 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001272 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001273 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001274 return;
1275 }
1276
1277 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001278 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001279 return;
1280 }
1281
Jie Song9fbfad02017-06-20 16:29:42 -07001282 std::string path[NUM_OF_DUMPS];
1283 android::base::unique_fd fd[NUM_OF_DUMPS];
1284 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001285
Jie Song9fbfad02017-06-20 16:29:42 -07001286 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1287 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1288 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1289
1290 fd[i] = android::base::unique_fd(
1291 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1292 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1293 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1294 if (fd[i] < 0) {
1295 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1296 return;
1297 } else {
1298 numFds++;
1299 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001300 }
1301
Jie Song9fbfad02017-06-20 16:29:42 -07001302 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001303 if (handle == nullptr) {
1304 MYLOGE("Could not create native_handle\n");
1305 return;
1306 }
Jie Song9fbfad02017-06-20 16:29:42 -07001307
1308 for (int i = 0; i < numFds; i++) {
1309 handle->data[i] = fd[i].release();
1310 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001311
Felipe Lemef0292972016-11-22 13:57:05 -08001312 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001313 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1314 if (!status.isOk()) {
1315 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1316 native_handle_close(handle);
1317 native_handle_delete(handle);
1318 return;
1319 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001320
Jie Song9fbfad02017-06-20 16:29:42 -07001321 for (int i = 0; i < numFds; i++) {
1322 struct stat s;
1323 if (fstat(handle->data[i], &s) == -1) {
1324 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1325 } else if (s.st_size > 0) {
1326 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1327 } else {
1328 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1329 }
1330 }
1331
Felipe Lemed8b94e52016-12-08 10:21:44 -08001332 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001333
1334 native_handle_close(handle);
1335 native_handle_delete(handle);
1336
Jie Song9fbfad02017-06-20 16:29:42 -07001337 for (int i = 0; i < numFds; i++) {
1338 if (remove(path[i].c_str()) != 0) {
1339 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1340 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001341 }
1342}
1343
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001344static void ShowUsageAndExit(int exitCode = 1) {
1345 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001346 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001347 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1348 " -h: display this help message\n"
1349 " -b: play sound file instead of vibrate, at beginning of job\n"
1350 " -e: play sound file instead of vibrate, at end of job\n"
1351 " -o: write to file (instead of stdout)\n"
1352 " -d: append date to filename (requires -o)\n"
1353 " -p: capture screenshot to filename.png (requires -o)\n"
1354 " -z: generate zipped file (requires -o)\n"
1355 " -s: write output to control socket (for init)\n"
1356 " -S: write file location to control socket (for init; requires -o and -z)"
1357 " -q: disable vibrate\n"
1358 " -B: send broadcast when finished (requires -o)\n"
1359 " -P: send broadcast when started and update system properties on "
1360 "progress (requires -o and -B)\n"
1361 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1362 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001363 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001364 exit(exitCode);
1365}
1366
1367static void ExitOnInvalidArgs() {
1368 fprintf(stderr, "invalid combination of args\n");
1369 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001370}
1371
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001372static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001373 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001374}
1375
Wei Liuf87959e2016-08-26 14:51:42 -07001376static void register_sig_handler() {
1377 struct sigaction sa;
1378 sigemptyset(&sa.sa_mask);
1379 sa.sa_flags = 0;
1380 sa.sa_handler = sig_handler;
1381 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1382 sigaction(SIGSEGV, &sa, NULL); // segment fault
1383 sigaction(SIGINT, &sa, NULL); // ctrl-c
1384 sigaction(SIGTERM, &sa, NULL); // killed
1385 sigaction(SIGQUIT, &sa, NULL); // quit
1386}
1387
Felipe Leme1d486fe2016-10-14 18:06:47 -07001388bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001389 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001390 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001391 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001392 // Final timestamp
1393 char date[80];
1394 time_t the_real_now_please_stand_up = time(nullptr);
1395 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001396 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001397 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001398
Felipe Leme9a523ae2016-10-20 15:10:33 -07001399 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001400 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001401 return false;
1402 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001403 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001404 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001405 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001406 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001407
Felipe Leme0f3fb202016-06-10 17:10:53 -07001408 // Add log file (which contains stderr output) to zip...
1409 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001410 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001411 MYLOGE("Failed to add dumpstate log to .zip file\n");
1412 return false;
1413 }
1414 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001415 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001416 fprintf(stderr, "\n");
1417
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001418 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001419 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001420 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001421 return false;
1422 }
1423
Felipe Leme1d486fe2016-10-14 18:06:47 -07001424 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1425 ds.zip_file.reset(nullptr);
1426
Felipe Lemee9d2c542016-11-15 11:48:26 -08001427 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1428 if (remove(tmp_path_.c_str()) != 0) {
1429 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001430 }
1431
Felipe Leme1e9edc62015-12-21 16:02:13 -08001432 return true;
1433}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001434
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001435static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001436 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1437 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001438 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001439 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001440 return NULL;
1441 }
1442
1443 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001444 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001445
1446 std::vector<uint8_t> buffer(65536);
1447 while (1) {
1448 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1449 if (bytes_read == 0) {
1450 break;
1451 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001452 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001453 return NULL;
1454 }
1455
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001456 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001457 }
1458
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001459 uint8_t hash[SHA256_DIGEST_LENGTH];
1460 SHA256_Final(hash, &ctx);
1461
1462 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1463 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001464 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001465 }
1466 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1467 return std::string(hash_buffer);
1468}
1469
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001470static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1471 // clang-format off
1472 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1473 "--receiver-foreground", "--receiver-include-background", "-a", action};
1474 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001475
1476 am.insert(am.end(), args.begin(), args.end());
1477
Felipe Leme8d2410e2017-02-08 09:46:08 -08001478 RunCommand("", am,
1479 CommandOptions::WithTimeout(20)
1480 .Log("Sending broadcast: '%s'\n")
1481 .Always()
1482 .DropRoot()
1483 .RedirectStderr()
1484 .Build());
1485}
1486
Felipe Leme35b8cf12017-02-10 15:47:29 -08001487static void Vibrate(int duration_ms) {
1488 // clang-format off
1489 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1490 CommandOptions::WithTimeout(10)
1491 .Log("Vibrate: '%s'\n")
1492 .Always()
1493 .Build());
1494 // clang-format on
1495}
1496
Colin Crossf45fa6b2012-03-26 12:38:26 -07001497int main(int argc, char *argv[]) {
1498 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001499 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001500 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001501 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001502 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001503 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001504 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001505 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001506 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001507 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001508 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001509 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001510
Colin Crossf45fa6b2012-03-26 12:38:26 -07001511 /* set as high priority, and protect from OOM killer */
1512 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001513
Felipe Lemed071c682016-10-20 16:48:00 -07001514 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001515 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001516 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001517 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001518 } else {
1519 /* fallback to kernels <= 2.6.35 */
1520 oom_adj = fopen("/proc/self/oom_adj", "we");
1521 if (oom_adj) {
1522 fputs("-17", oom_adj);
1523 fclose(oom_adj);
1524 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001525 }
1526
Jeff Brown1dc94e32014-09-11 14:15:27 -07001527 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001528 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001529 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001530 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001531 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001532 case 'd': do_add_date = 1; break;
1533 case 'z': do_zip_file = 1; break;
1534 case 'o': use_outfile = optarg; break;
1535 case 's': use_socket = 1; break;
1536 case 'S': use_control_socket = 1; break;
1537 case 'v': show_header_only = true; break;
1538 case 'q': do_vibrate = 0; break;
1539 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001540 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001541 case 'R': is_remote_mode = 1; break;
1542 case 'B': do_broadcast = 1; break;
1543 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001544 case 'h':
1545 ShowUsageAndExit(0);
1546 break;
1547 default:
1548 fprintf(stderr, "Invalid option: %c\n", c);
1549 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001550 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001551 }
1552 }
1553
Felipe Lemed071c682016-10-20 16:48:00 -07001554 // TODO: use helper function to convert argv into a string
1555 for (int i = 0; i < argc; i++) {
1556 ds.args_ += argv[i];
1557 if (i < argc - 1) {
1558 ds.args_ += " ";
1559 }
1560 }
1561
1562 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001563 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001564 // Framework uses a system property to override some command-line args.
1565 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001566 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001567 // Currently, the dumpstate binder is only used by Shell to update progress.
1568 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001569 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001570 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001571 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001572 do_vibrate = 0;
1573 is_remote_mode = 1;
1574 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001575 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001576 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001577 } else if (ds.extra_options_ == "bugreporttelephony") {
1578 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001579 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001580 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001581 }
1582 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001583 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001584 }
1585
Naveen Kallab53a1c92017-03-16 18:17:25 -07001586 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1587 if (!ds.notification_title.empty()) {
1588 // Reset the property
1589 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1590
1591 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1592 if (!ds.notification_description.empty()) {
1593 // Reset the property
1594 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1595 }
1596 MYLOGD("notification (title: %s, description: %s)\n",
1597 ds.notification_title.c_str(), ds.notification_description.c_str());
1598 }
1599
Felipe Leme9a523ae2016-10-20 15:10:33 -07001600 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001601 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001602 }
1603
Felipe Leme2628e9e2016-04-12 16:36:51 -07001604 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001605 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001606 }
1607
Felipe Leme9a523ae2016-10-20 15:10:33 -07001608 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001609 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001610 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001611
Felipe Leme9a523ae2016-10-20 15:10:33 -07001612 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001613 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001614 }
1615
Felipe Lemed071c682016-10-20 16:48:00 -07001616 if (ds.version_ == VERSION_DEFAULT) {
1617 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001618 }
1619
Felipe Lemee184f662016-10-27 10:04:47 -07001620 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1621 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1622 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1623 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001624 exit(1);
1625 }
1626
1627 if (show_header_only) {
1628 ds.PrintHeader();
1629 exit(0);
1630 }
1631
Felipe Leme7447d7c2016-11-03 18:12:22 -07001632 /* redirect output if needed */
1633 bool is_redirecting = !use_socket && use_outfile;
1634
1635 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1636 std::string stats_path =
1637 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1638 : "";
1639 ds.progress_.reset(new Progress(stats_path));
1640
Felipe Lemed071c682016-10-20 16:48:00 -07001641 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001642 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001643 ds.id_ = ++last_id;
1644 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1645
1646 MYLOGI("begin\n");
1647
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001648 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001649
Felipe Leme75876a22016-10-27 16:31:27 -07001650 if (do_start_service) {
1651 MYLOGI("Starting 'dumpstate' service\n");
1652 android::status_t ret;
1653 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1654 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1655 }
1656 }
1657
Felipe Lemef0292972016-11-22 13:57:05 -08001658 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001659 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1660 }
1661
Felipe Leme7447d7c2016-11-03 18:12:22 -07001662 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001663 ds.extra_options_.c_str());
1664
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001665 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001666
Felipe Leme9a523ae2016-10-20 15:10:33 -07001667 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001668
Christopher Ferrised9354f2014-10-01 17:35:01 -07001669 // If we are going to use a socket, do it as early as possible
1670 // to avoid timeouts from bugreport.
1671 if (use_socket) {
1672 redirect_to_socket(stdout, "dumpstate");
1673 }
1674
Felipe Leme2628e9e2016-04-12 16:36:51 -07001675 if (use_control_socket) {
1676 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001677 ds.control_socket_fd_ = open_socket("dumpstate");
1678 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001679 }
1680
Felipe Leme71bbfc52015-11-23 14:14:51 -08001681 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001682 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001683 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001684 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001685 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1686 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001687 if (do_add_date) {
1688 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001689 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001690 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001691 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001692 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001693 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001694
1695 if (telephony_only) {
1696 ds.base_name_ += "-telephony";
1697 }
1698
Felipe Leme71bbfc52015-11-23 14:14:51 -08001699 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001700 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001701 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001702 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001703 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001704
Felipe Lemee844a9d2016-09-21 15:01:39 -07001705 MYLOGD(
1706 "Bugreport dir: %s\n"
1707 "Base name: %s\n"
1708 "Suffix: %s\n"
1709 "Log path: %s\n"
1710 "Temporary path: %s\n"
1711 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001712 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1713 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001714
Felipe Leme1e9edc62015-12-21 16:02:13 -08001715 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001716 ds.path_ = ds.GetPath(".zip");
1717 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1718 create_parent_dirs(ds.path_.c_str());
1719 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001720 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001721 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001722 do_zip_file = 0;
1723 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001724 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001725 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001726 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001727 }
1728
Felipe Leme9a523ae2016-10-20 15:10:33 -07001729 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001730 if (do_broadcast) {
1731 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001732
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001733 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001734 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001735 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001736 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001737 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001738 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001739 };
1740 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001741 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001742 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001743 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001744 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001745 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001746 }
1747 }
1748
Nick Kralevichf3599b32016-01-25 15:05:16 -08001749 /* read /proc/cmdline before dropping root */
1750 FILE *cmdline = fopen("/proc/cmdline", "re");
1751 if (cmdline) {
1752 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1753 fclose(cmdline);
1754 }
1755
John Michelau1f794c42012-09-17 11:20:19 -05001756 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001757 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001758 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759
Felipe Leme9a523ae2016-10-20 15:10:33 -07001760 if (do_fb && ds.do_early_screenshot_) {
1761 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001762 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001763 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001764 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001765 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001766 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001767 }
1768 }
1769
Felipe Leme1e9edc62015-12-21 16:02:13 -08001770 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001771 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1772 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001773 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001774 }
1775 }
1776
Felipe Leme71bbfc52015-11-23 14:14:51 -08001777 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001778 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1779 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1780 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1781 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001782 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001783 /* TODO: rather than generating a text file now and zipping it later,
1784 it would be more efficient to redirect stdout to the zip entry
1785 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001786 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1787 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001788 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001789 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001790 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001791 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001792
1793 // Don't buffer stdout
1794 setvbuf(stdout, nullptr, _IONBF, 0);
1795
Felipe Leme608385d2016-02-01 10:35:38 -08001796 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1797 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001798 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001799 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001800
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001801 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001802 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001803 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001804 } else {
1805 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1806 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1807 // the raw trace.
1808 if (!dump_anrd_trace()) {
1809 dump_systrace();
1810 }
1811
1812 // Invoking the following dumpsys calls before dump_traces() to try and
1813 // keep the system stats as close to its initial state as possible.
1814 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1815 CommandOptions::WithTimeout(90).DropRoot().Build());
1816 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1817 CommandOptions::WithTimeout(10).DropRoot().Build());
1818
1819 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1820 dump_raft();
1821
1822 /* collect stack traces from Dalvik and native processes (needs root) */
1823 dump_traces_path = dump_traces();
1824
1825 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001826 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1827 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001828
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001829 ds.AddDir(RECOVERY_DIR, true);
1830 ds.AddDir(RECOVERY_DATA_DIR, true);
1831 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1832 if (!PropertiesHelper::IsUserBuild()) {
1833 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1834 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1835 }
1836 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001837 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001838
1839 // Capture any IPSec policies in play. No keys are exposed here.
1840 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1841 CommandOptions::WithTimeout(10).Build());
1842
1843 // Run ss as root so we can see socket marks.
1844 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1845 CommandOptions::WithTimeout(10).Build());
1846
1847 if (!DropRootUser()) {
1848 return -1;
1849 }
1850
1851 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001852 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001853
Felipe Leme55b42a62015-11-10 17:39:08 -08001854 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001855 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001856 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001857 }
1858
Felipe Leme6e01fa62015-11-11 19:35:14 -08001859 /* rename or zip the (now complete) .tmp file to its final location */
1860 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001861
1862 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001863 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001864 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001865 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001866 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001867 /* must whitelist which characters are allowed, otherwise it could cross directories */
1868 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001869 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001870 change_suffix = true;
1871 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001872 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001873 }
1874 }
1875 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001876 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1877 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001878 if (!ds.screenshot_path_.empty()) {
1879 std::string new_screenshot_path = ds.GetPath(".png");
1880 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1881 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1882 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001883 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001884 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001885 }
1886 }
1887 }
1888
Felipe Leme6e01fa62015-11-11 19:35:14 -08001889 bool do_text_file = true;
1890 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001891 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001892 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001893 do_text_file = true;
1894 } else {
1895 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001896 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001897 std::string new_path = ds.GetPath(".zip");
1898 if (ds.path_ != new_path) {
1899 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1900 if (rename(ds.path_.c_str(), new_path.c_str())) {
1901 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001902 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001903 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001904 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001905 }
1906 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001907 }
1908 }
1909 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001910 ds.path_ = ds.GetPath(".txt");
1911 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1912 ds.tmp_path_.c_str());
1913 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1914 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001915 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001916 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001917 }
1918 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001919 if (use_control_socket) {
1920 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001921 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001922 "FAIL:could not create zip file, check %s "
1923 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001924 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001925 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001926 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001927 }
1928 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001929 }
1930
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001931 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001932 for (int i = 0; i < 3; i++) {
1933 Vibrate(75);
1934 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001935 }
1936
Jeff Brown1dc94e32014-09-11 14:15:27 -07001937 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001938 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001939 if (!ds.path_.empty()) {
1940 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001941 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001942
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001943 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001944 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001945 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001946 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001947 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001948 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1949 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001950 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001951 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001952 if (do_fb) {
1953 am_args.push_back("--es");
1954 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001955 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001956 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001957 if (!ds.notification_title.empty()) {
1958 am_args.push_back("--es");
1959 am_args.push_back("android.intent.extra.TITLE");
1960 am_args.push_back(ds.notification_title);
1961 if (!ds.notification_description.empty()) {
1962 am_args.push_back("--es");
1963 am_args.push_back("android.intent.extra.DESCRIPTION");
1964 am_args.push_back(ds.notification_description);
1965 }
1966 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001967 if (is_remote_mode) {
1968 am_args.push_back("--es");
1969 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001970 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001971 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1972 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001973 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001974 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001975 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001976 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001977 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001978 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001979 }
1980
Felipe Leme7447d7c2016-11-03 18:12:22 -07001981 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1982 ds.progress_->GetInitialMax());
1983 ds.progress_->Save();
1984 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001985
Felipe Leme107a05f2016-03-08 15:11:15 -08001986 if (is_redirecting) {
1987 fclose(stderr);
1988 }
1989
Felipe Leme9a523ae2016-10-20 15:10:33 -07001990 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001991 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001992 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001993 }
1994
Colin Crossf45fa6b2012-03-26 12:38:26 -07001995 return 0;
1996}