blob: aba08d9de939920bc1db01e477b20313af49de49 [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"
Vishnu Nair36b4cdb2017-11-17 10:27:05 -080084#define WMTRACE_DATA_DIR "/data/misc/wmtrace"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070085
Narayan Kamath8f788292017-05-25 13:20:39 +010086// TODO(narayan): Since this information has to be kept in sync
87// with tombstoned, we should just put it in a common header.
88//
89// File: system/core/debuggerd/tombstoned/tombstoned.cpp
Narayan Kamathbd863722017-06-01 18:50:12 +010090static const std::string TOMBSTONE_DIR = "/data/tombstones/";
91static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_";
92static const std::string ANR_DIR = "/data/anr/";
93static const std::string ANR_FILE_PREFIX = "anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -070094
Narayan Kamath8f788292017-05-25 13:20:39 +010095struct DumpData {
96 std::string name;
97 int fd;
98 time_t mtime;
99};
100
101static bool operator<(const DumpData& d1, const DumpData& d2) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100102 return d1.mtime > d2.mtime;
Narayan Kamath8f788292017-05-25 13:20:39 +0100103}
104
105static std::unique_ptr<std::vector<DumpData>> tombstone_data;
106static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700107
Felipe Lemee844a9d2016-09-21 15:01:39 -0700108// TODO: temporary variables and functions used during C++ refactoring
109static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700110static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
111 const CommandOptions& options = CommandOptions::DEFAULT) {
112 return ds.RunCommand(title, fullCommand, options);
113}
114static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800115 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Vishnu Nair6921f802017-11-22 09:17:23 -0800116 long dumpsysTimeoutMs = 0) {
117 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs);
Felipe Leme678727a2016-09-21 17:22:11 -0700118}
119static int DumpFile(const std::string& title, const std::string& path) {
120 return ds.DumpFile(title, path);
121}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800122
Felipe Lemee844a9d2016-09-21 15:01:39 -0700123// Relative directory (inside the zip) for all files copied as-is into the bugreport.
124static const std::string ZIP_ROOT_DIR = "FS";
125
Steven Moreland7440ddb2016-12-15 16:13:39 -0800126// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
Jie Song9fbfad02017-06-20 16:29:42 -0700127static const std::string kDumpstateBoardPath = "/bugreports/";
128static const std::string kDumpstateBoardFiles[] = {
129 "dumpstate_board.txt",
Felipe Leme95d6ca52017-08-01 16:35:56 -0700130 "dumpstate_board.bin"
Jie Song9fbfad02017-06-20 16:29:42 -0700131};
132static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles);
133
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700134static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800135
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700136static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700137static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700138static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700139static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
140static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700141
Felipe Lemef0292972016-11-22 13:57:05 -0800142static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
143
Narayan Kamath8f788292017-05-25 13:20:39 +0100144/*
Narayan Kamathbd863722017-06-01 18:50:12 +0100145 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|.
146 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime|
147 * is set, the vector only contains files that were written in the last 30 minutes.
Andreas Gamped0d76952017-08-22 13:08:37 -0700148 * If |limit_by_count| is set, the vector only contains the ten latest files.
Narayan Kamath8f788292017-05-25 13:20:39 +0100149 */
Narayan Kamathbd863722017-06-01 18:50:12 +0100150static std::vector<DumpData>* GetDumpFds(const std::string& dir_path,
151 const std::string& file_prefix,
Andreas Gamped0d76952017-08-22 13:08:37 -0700152 bool limit_by_mtime,
153 bool limit_by_count = true) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100154 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
155
Narayan Kamath8f788292017-05-25 13:20:39 +0100156 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
Narayan Kamathbd863722017-06-01 18:50:12 +0100157 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir);
Narayan Kamath8f788292017-05-25 13:20:39 +0100158
Narayan Kamathbd863722017-06-01 18:50:12 +0100159 struct dirent* entry = nullptr;
160 while ((entry = readdir(dump_dir.get()))) {
161 if (entry->d_type != DT_REG) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100162 continue;
163 }
164
Narayan Kamathbd863722017-06-01 18:50:12 +0100165 const std::string base_name(entry->d_name);
166 if (base_name.find(file_prefix) != 0) {
167 continue;
168 }
169
170 const std::string abs_path = dir_path + base_name;
171 android::base::unique_fd fd(
172 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
173 if (fd == -1) {
174 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno));
175 break;
176 }
177
178 struct stat st = {};
179 if (fstat(fd, &st) == -1) {
180 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno));
Narayan Kamath8f788292017-05-25 13:20:39 +0100181 continue;
182 }
183
184 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
Narayan Kamathbd863722017-06-01 18:50:12 +0100185 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100186 continue;
187 }
188
Narayan Kamathbd863722017-06-01 18:50:12 +0100189 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime};
Narayan Kamath8f788292017-05-25 13:20:39 +0100190
191 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700192 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100193
194 std::sort(dump_data->begin(), dump_data->end());
195
Andreas Gamped0d76952017-08-22 13:08:37 -0700196 if (limit_by_count && dump_data->size() > 10) {
197 dump_data->erase(dump_data->begin() + 10, dump_data->end());
198 }
199
Narayan Kamath8f788292017-05-25 13:20:39 +0100200 return dump_data.release();
201}
202
Narayan Kamathbd863722017-06-01 18:50:12 +0100203static bool AddDumps(const std::vector<DumpData>::const_iterator start,
204 const std::vector<DumpData>::const_iterator end,
205 const char* type_name, const bool add_to_zip) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100206 bool dumped = false;
Narayan Kamathbd863722017-06-01 18:50:12 +0100207 for (auto it = start; it != end; ++it) {
208 const std::string& name = it->name;
209 const int fd = it->fd;
Narayan Kamath8f788292017-05-25 13:20:39 +0100210 dumped = true;
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100211
212 // Seek to the beginning of the file before dumping any data. A given
213 // DumpData entry might be dumped multiple times in the report.
214 //
215 // For example, the most recent ANR entry is dumped to the body of the
216 // main entry and it also shows up as a separate entry in the bugreport
217 // ZIP file.
218 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) {
219 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(),
220 strerror(errno));
221 }
222
Narayan Kamath8f788292017-05-25 13:20:39 +0100223 if (ds.IsZipping() && add_to_zip) {
224 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100225 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str());
Narayan Kamath8f788292017-05-25 13:20:39 +0100226 }
227 } else {
228 dump_file_from_fd(type_name, name.c_str(), fd);
229 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100230 }
231
232 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700233}
234
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100235static void CloseDumpFds(const std::vector<DumpData>* dumps) {
236 for (auto it = dumps->begin(); it != dumps->end(); ++it) {
237 close(it->fd);
238 }
239}
240
Felipe Leme635ca312016-01-05 14:23:02 -0800241// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700242void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800243 char path[PATH_MAX];
244
245 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
246 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700247 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800248 char linkname[PATH_MAX];
249 ssize_t r = readlink(path, linkname, PATH_MAX);
250 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800251 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800252 return;
253 }
254 linkname[r] = '\0';
255
256 if (mount_points.find(linkname) == mount_points.end()) {
257 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700258 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700259 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800260 mount_points.insert(linkname);
261 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800262 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800263 }
264 }
265}
266
267void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700268 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700269 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800270 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800271 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700272 for_each_pid(do_mountinfo, nullptr);
273 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800274}
275
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700276static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
277{
278 DIR *d;
279 struct dirent *de;
280 char path[PATH_MAX];
281
282 d = opendir(driverpath);
283 if (d == NULL) {
284 return;
285 }
286
287 while ((de = readdir(d))) {
288 if (de->d_type != DT_LNK) {
289 continue;
290 }
291 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700292 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700293 }
294
295 closedir(d);
296}
297
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700298
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700299
300// dump anrd's trace and add to the zip file.
301// 1. check if anrd is running on this device.
302// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
303// 3. wait until the trace generation completes and add to the zip file.
304static bool dump_anrd_trace() {
305 unsigned int pid;
306 char buf[50], path[PATH_MAX];
307 struct dirent *trace;
308 struct stat st;
309 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700310 int retry = 5;
311 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700312 long long cur_size = 0;
313 const char *trace_path = "/data/misc/anrd/";
314
Felipe Leme1d486fe2016-10-14 18:06:47 -0700315 if (!ds.IsZipping()) {
316 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700317 return false;
318 }
319
320 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700321 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700322
323 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700324 if (stat(trace_path, &st) == 0) {
325 old_mtime = st.st_mtime;
326 } else {
327 MYLOGE("Failed to find: %s\n", trace_path);
328 return false;
329 }
330
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700331 // send SIGUSR1 to the anrd to generate a trace.
332 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700333 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700334 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700335 MYLOGE("anrd signal timed out. Please manually collect trace\n");
336 return false;
337 }
338
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700339 while (retry-- > 0 && old_mtime == st.st_mtime) {
340 sleep(1);
341 stat(trace_path, &st);
342 }
343
344 if (retry < 0 && old_mtime == st.st_mtime) {
345 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
346 return false;
347 }
348
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700349 // identify the trace file by its creation time.
350 if (!(trace_dir = opendir(trace_path))) {
351 MYLOGE("Can't open trace file under %s\n", trace_path);
352 }
353 while ((trace = readdir(trace_dir))) {
354 if (strcmp(trace->d_name, ".") == 0
355 || strcmp(trace->d_name, "..") == 0) {
356 continue;
357 }
358 sprintf(path, "%s%s", trace_path, trace->d_name);
359 if (stat(path, &st) == 0) {
360 if (st.st_ctime > max_ctime) {
361 max_ctime = st.st_ctime;
362 sprintf(buf, "%s", trace->d_name);
363 }
364 }
365 }
366 closedir(trace_dir);
367
368 // Wait until the dump completes by checking the size of the trace.
369 if (max_ctime > 0) {
370 sprintf(path, "%s%s", trace_path, buf);
371 while(true) {
372 sleep(1);
373 if (stat(path, &st) == 0) {
374 if (st.st_size == cur_size) {
375 break;
376 } else if (st.st_size > cur_size) {
377 cur_size = st.st_size;
378 } else {
379 return false;
380 }
381 } else {
382 MYLOGE("Cant stat() %s anymore\n", path);
383 return false;
384 }
385 }
386 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700387 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700388 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
389 } else {
390 if (remove(path)) {
391 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
392 }
393 return true;
394 }
395 } else {
396 MYLOGE("Can't stats any trace file under %s\n", trace_path);
397 }
398 }
399 return false;
400}
401
Felipe Lemeefd7e272016-05-18 09:27:16 -0700402static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700403 if (!ds.IsZipping()) {
404 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700405 return;
406 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700407 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700408 if (systrace_path.empty()) {
409 MYLOGE("Not dumping systrace because path is empty\n");
410 return;
411 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700412 const char* path = "/sys/kernel/debug/tracing/tracing_on";
413 long int is_tracing;
414 if (read_file_as_long(path, &is_tracing)) {
415 return; // error already logged
416 }
417 if (is_tracing <= 0) {
418 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
419 return;
420 }
421
Felipe Leme14e034a2016-03-30 18:51:03 -0700422 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
423 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700424 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700425 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700426 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700427 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700428 // peacefully; ideally, we should call strace to stop itself, but there is no such option
429 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700430 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700431 // MYLOGE("could not stop systrace ");
432 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700433 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700434 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700435 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700436 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700437 if (remove(systrace_path.c_str())) {
438 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
439 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700440 }
441}
442
Felipe Lemeefd7e272016-05-18 09:27:16 -0700443static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800444 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700445 return;
446 }
447
Felipe Leme1d486fe2016-10-14 18:06:47 -0700448 std::string raft_path = ds.GetPath("-raft_log.txt");
449 if (raft_path.empty()) {
450 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700451 return;
452 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700453
454 struct stat s;
455 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
456 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
457 return;
458 }
459
Felipe Leme30dbfa12016-09-02 12:43:26 -0700460 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700461 if (!ds.IsZipping()) {
462 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700463 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700464 return;
465 }
466
Felipe Leme1d486fe2016-10-14 18:06:47 -0700467 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
468 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
469 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700470 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700471 if (remove(raft_path.c_str())) {
472 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700473 }
474 }
475}
476
Mark Salyzyn326842f2015-04-30 09:49:41 -0700477static bool skip_not_stat(const char *path) {
478 static const char stat[] = "/stat";
479 size_t len = strlen(path);
480 if (path[len - 1] == '/') { /* Directory? */
481 return false;
482 }
483 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
484}
485
Felipe Leme4c2d6632016-09-28 14:32:00 -0700486static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800487 return false;
488}
489
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700490unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700491
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800492//
493// stat offsets
494// Name units description
495// ---- ----- -----------
496// read I/Os requests number of read I/Os processed
497#define __STAT_READ_IOS 0
498// read merges requests number of read I/Os merged with in-queue I/O
499#define __STAT_READ_MERGES 1
500// read sectors sectors number of sectors read
501#define __STAT_READ_SECTORS 2
502// read ticks milliseconds total wait time for read requests
503#define __STAT_READ_TICKS 3
504// write I/Os requests number of write I/Os processed
505#define __STAT_WRITE_IOS 4
506// write merges requests number of write I/Os merged with in-queue I/O
507#define __STAT_WRITE_MERGES 5
508// write sectors sectors number of sectors written
509#define __STAT_WRITE_SECTORS 6
510// write ticks milliseconds total wait time for write requests
511#define __STAT_WRITE_TICKS 7
512// in_flight requests number of I/Os currently in flight
513#define __STAT_IN_FLIGHT 8
514// io_ticks milliseconds total time this block device has been active
515#define __STAT_IO_TICKS 9
516// time_in_queue milliseconds total wait time for all requests
517#define __STAT_IN_QUEUE 10
518#define __STAT_NUMBER_FIELD 11
519//
520// read I/Os, write I/Os
521// =====================
522//
523// These values increment when an I/O request completes.
524//
525// read merges, write merges
526// =========================
527//
528// These values increment when an I/O request is merged with an
529// already-queued I/O request.
530//
531// read sectors, write sectors
532// ===========================
533//
534// These values count the number of sectors read from or written to this
535// block device. The "sectors" in question are the standard UNIX 512-byte
536// sectors, not any device- or filesystem-specific block size. The
537// counters are incremented when the I/O completes.
538#define SECTOR_SIZE 512
539//
540// read ticks, write ticks
541// =======================
542//
543// These values count the number of milliseconds that I/O requests have
544// waited on this block device. If there are multiple I/O requests waiting,
545// these values will increase at a rate greater than 1000/second; for
546// example, if 60 read requests wait for an average of 30 ms, the read_ticks
547// field will increase by 60*30 = 1800.
548//
549// in_flight
550// =========
551//
552// This value counts the number of I/O requests that have been issued to
553// the device driver but have not yet completed. It does not include I/O
554// requests that are in the queue but not yet issued to the device driver.
555//
556// io_ticks
557// ========
558//
559// This value counts the number of milliseconds during which the device has
560// had I/O requests queued.
561//
562// time_in_queue
563// =============
564//
565// This value counts the number of milliseconds that I/O requests have waited
566// on this block device. If there are multiple I/O requests waiting, this
567// value will increase as the product of the number of milliseconds times the
568// number of requests waiting (see "read ticks" above for an example).
569#define S_TO_MS 1000
570//
571
Mark Salyzyn326842f2015-04-30 09:49:41 -0700572static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800573 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700574 bool z;
575 char *cp, *buffer = NULL;
576 size_t i = 0;
577 FILE *fp = fdopen(fd, "rb");
578 getline(&buffer, &i, fp);
579 fclose(fp);
580 if (!buffer) {
581 return -errno;
582 }
583 i = strlen(buffer);
584 while ((i > 0) && (buffer[i - 1] == '\n')) {
585 buffer[--i] = '\0';
586 }
587 if (!*buffer) {
588 free(buffer);
589 return 0;
590 }
591 z = true;
592 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800593 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700594 if (fields[i] != 0) {
595 z = false;
596 }
597 }
598 if (z) { /* never accessed */
599 free(buffer);
600 return 0;
601 }
602
Wei Wang509bb5d2017-06-09 14:42:12 -0700603 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) {
604 path += sizeof(BLK_DEV_SYS_DIR) - 1;
Mark Salyzyn326842f2015-04-30 09:49:41 -0700605 }
Wei Wang1dc1ef52017-06-12 11:28:37 -0700606
607 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev",
608 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect",
609 "W-wait", "in-fli", "activ", "T-wait", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700610 free(buffer);
611
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800612 if (fields[__STAT_IO_TICKS]) {
613 unsigned long read_perf = 0;
614 unsigned long read_ios = 0;
615 if (fields[__STAT_READ_TICKS]) {
616 unsigned long long divisor = fields[__STAT_READ_TICKS]
617 * fields[__STAT_IO_TICKS];
618 read_perf = ((unsigned long long)SECTOR_SIZE
619 * fields[__STAT_READ_SECTORS]
620 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
621 / divisor;
622 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
623 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
624 / divisor;
625 }
626
627 unsigned long write_perf = 0;
628 unsigned long write_ios = 0;
629 if (fields[__STAT_WRITE_TICKS]) {
630 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
631 * fields[__STAT_IO_TICKS];
632 write_perf = ((unsigned long long)SECTOR_SIZE
633 * fields[__STAT_WRITE_SECTORS]
634 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
635 / divisor;
636 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
637 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
638 / divisor;
639 }
640
641 unsigned queue = (fields[__STAT_IN_QUEUE]
642 + (fields[__STAT_IO_TICKS] >> 1))
643 / fields[__STAT_IO_TICKS];
644
645 if (!write_perf && !write_ios) {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700646 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 -0800647 } else {
Wei Wang1dc1ef52017-06-12 11:28:37 -0700648 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 -0800649 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800650 }
651
652 /* bugreport timeout factor adjustment */
653 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
654 worst_write_perf = write_perf;
655 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700656 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700657 return 0;
658}
659
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700660/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800661static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700662 log_id_t id = android_name_to_log_id(name);
663 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700664 /* Engineering margin is ten-fold our guess */
665 return 10 * (property_size + worst_write_perf) / worst_write_perf;
666}
667
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700668void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700669 std::string build, fingerprint, radio, bootloader, network;
670 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700671
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700672 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
673 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700674 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
675 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
676 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700677 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700678
Felipe Lemed8b94e52016-12-08 10:21:44 -0800679 printf("========================================================\n");
680 printf("== dumpstate: %s\n", date);
681 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700682
Felipe Lemed8b94e52016-12-08 10:21:44 -0800683 printf("\n");
684 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700685 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800686 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
687 printf("Bootloader: %s\n", bootloader.c_str());
688 printf("Radio: %s\n", radio.c_str());
689 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700690
Felipe Lemed8b94e52016-12-08 10:21:44 -0800691 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800692 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800693 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
pengzhicai24ae8192017-05-25 17:29:33 +0800694 ds.RunCommand("UPTIME", {"uptime"}, CommandOptions::DEFAULT);
Felipe Lemed8b94e52016-12-08 10:21:44 -0800695 printf("Bugreport format version: %s\n", version_.c_str());
696 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
697 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
698 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800699}
700
Felipe Leme24b66ee2016-06-16 10:55:26 -0700701// List of file extensions that can cause a zip file attachment to be rejected by some email
702// service providers.
703static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
704 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
705 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
706 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
707};
708
Felipe Leme1d486fe2016-10-14 18:06:47 -0700709bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
710 if (!IsZipping()) {
711 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
712 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800713 return false;
714 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700715 std::string valid_name = entry_name;
716
717 // Rename extension if necessary.
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -0700718 size_t idx = entry_name.rfind('.');
Felipe Leme24b66ee2016-06-16 10:55:26 -0700719 if (idx != std::string::npos) {
720 std::string extension = entry_name.substr(idx);
721 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
722 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
723 valid_name = entry_name + ".renamed";
724 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
725 }
726 }
727
Felipe Leme6fe9db62016-02-12 09:04:16 -0800728 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
729 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700730 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
731 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700732 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700733 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700734 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800735 return false;
736 }
737
Felipe Leme770410d2016-01-26 17:07:14 -0800738 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800739 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400740 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800741 if (bytes_read == 0) {
742 break;
743 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800744 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800745 return false;
746 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700747 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800748 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700749 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800750 return false;
751 }
752 }
753
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700754 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700755 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700756 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800757 return false;
758 }
759
760 return true;
761}
762
Felipe Leme1d486fe2016-10-14 18:06:47 -0700763bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
764 android::base::unique_fd fd(
765 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700766 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800767 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800768 return false;
769 }
770
Felipe Leme1d486fe2016-10-14 18:06:47 -0700771 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800772}
773
774/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700775static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800777}
778
Felipe Leme1d486fe2016-10-14 18:06:47 -0700779void Dumpstate::AddDir(const std::string& dir, bool recursive) {
780 if (!IsZipping()) {
781 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800782 return;
783 }
Felipe Leme678727a2016-09-21 17:22:11 -0700784 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800785 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700786 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800787}
788
Felipe Leme1d486fe2016-10-14 18:06:47 -0700789bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
790 if (!IsZipping()) {
791 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
792 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800793 return false;
794 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800795 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700796 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700797 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700798 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700799 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800800 return false;
801 }
802
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700803 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700804 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700805 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700806 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800807 return false;
808 }
809
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700810 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700811 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700812 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800813 return false;
814 }
815
816 return true;
817}
818
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800819static void DoKmsg() {
820 struct stat st;
821 if (!stat(PSTORE_LAST_KMSG, &st)) {
822 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
823 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
824 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
825 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
826 } else {
827 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
828 DumpFile("LAST KMSG", "/proc/last_kmsg");
829 }
830}
831
832static void DoLogcat() {
Vishnu Nair6921f802017-11-22 09:17:23 -0800833 unsigned long timeout_ms;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800834 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
835 // calculate timeout
Vishnu Nair6921f802017-11-22 09:17:23 -0800836 timeout_ms = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
837 if (timeout_ms < 20000) {
838 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800839 }
Tony Makae737652017-03-30 17:47:09 +0100840 RunCommand("SYSTEM LOG",
Vishnu Nair6921f802017-11-22 09:17:23 -0800841 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"},
842 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
843 timeout_ms = logcat_timeout("events");
844 if (timeout_ms < 20000) {
845 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800846 }
847 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100848 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
849 "-d", "*:v"},
Vishnu Nair6921f802017-11-22 09:17:23 -0800850 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
851 timeout_ms = logcat_timeout("radio");
852 if (timeout_ms < 20000) {
853 timeout_ms = 20000;
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800854 }
855 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100856 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
857 "-d", "*:v"},
Vishnu Nair6921f802017-11-22 09:17:23 -0800858 CommandOptions::WithTimeoutInMs(timeout_ms).Build());
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800859
860 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
861
862 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
863 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100864 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
865 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800866}
867
Jayachandran Ca94c7172017-06-10 15:08:12 -0700868static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700869 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
870 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900871 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700872 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900873 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
874 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
875 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
876 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700877}
878
Narayan Kamath8f788292017-05-25 13:20:39 +0100879static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
880 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700881 std::string dump_traces_dir;
882
Felipe Lemee184f662016-10-27 10:04:47 -0700883 if (dump_traces_path != nullptr) {
884 if (add_to_zip) {
885 dump_traces_dir = dirname(dump_traces_path);
886 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
887 ds.AddDir(dump_traces_dir, true);
888 } else {
889 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
890 dump_traces_path);
891 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
892 }
893 }
894
Felipe Lemee184f662016-10-27 10:04:47 -0700895
896 // Make sure directory is not added twice.
897 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
898 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
899 // property - but in reality they're the same path (although the former could be nullptr).
900 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
901 // be revisited.
902 bool already_dumped = anr_traces_dir == dump_traces_dir;
903
Narayan Kamath8f788292017-05-25 13:20:39 +0100904 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700905 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
906
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100907 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
908 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
909 if (fd.get() < 0) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100910 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700911 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100912 if (add_to_zip) {
913 if (!already_dumped) {
914 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
915 anr_traces_dir.c_str());
916 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700917 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100918 } else {
919 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
920 anr_traces_file.c_str());
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100921 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
Narayan Kamath8f788292017-05-25 13:20:39 +0100922 }
923 }
924}
925
926static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
927 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
928 anr_traces_dir.c_str());
929
930 // If we're here, dump_traces_path will always be a temporary file
931 // (created with mkostemp or similar) that contains dumps taken earlier
932 // on in the process.
933 if (dump_traces_path != nullptr) {
934 if (add_to_zip) {
935 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
936 } else {
937 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
938 dump_traces_path);
939 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
940 }
941
942 const int ret = unlink(dump_traces_path);
943 if (ret == -1) {
944 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
945 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700946 }
947 }
948
Narayan Kamathbd863722017-06-01 18:50:12 +0100949 // Add a specific message for the first ANR Dump.
950 if (anr_data->size() > 0) {
951 AddDumps(anr_data->begin(), anr_data->begin() + 1,
952 "VM TRACES AT LAST ANR", add_to_zip);
953
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100954 // The "last" ANR will always be included as separate entry in the zip file. In addition,
955 // it will be present in the body of the main entry if |add_to_zip| == false.
956 //
957 // Historical ANRs are always included as separate entries in the bugreport zip file.
958 AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
959 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100960 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100961 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
962 }
963}
964
965static void AddAnrTraceFiles() {
966 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
967
968 std::string anr_traces_file;
969 std::string anr_traces_dir;
970 bool is_global_trace_file = true;
971
972 // First check whether the stack-trace-dir property is set. When it's set,
973 // each ANR trace will be written to a separate file and not to a global
974 // stack trace file.
975 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
976 if (anr_traces_dir.empty()) {
977 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
978 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100979 anr_traces_dir = dirname(anr_traces_file.c_str());
980 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100981 } else {
982 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100983 }
984
985 // We have neither configured a global trace file nor a trace directory,
986 // there will be nothing to dump.
987 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
988 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700989 return;
990 }
991
Narayan Kamath8f788292017-05-25 13:20:39 +0100992 if (is_global_trace_file) {
993 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
994 } else {
995 AddAnrTraceDir(add_to_zip, anr_traces_dir);
996 }
997
Felipe Lemee184f662016-10-27 10:04:47 -0700998 /* slow traces for slow operations */
999 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001000 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001001 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001002 while (true) {
1003 const std::string slow_trace_path =
1004 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1005 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001006 // No traces file at this index, done with the files.
1007 break;
1008 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001009 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001010 i++;
1011 }
1012 }
1013}
1014
Wei Wang509bb5d2017-06-09 14:42:12 -07001015static void DumpBlockStatFiles() {
1016 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001017
Wei Wang1dc1ef52017-06-12 11:28:37 -07001018 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1019
1020 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001021 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1022 return;
1023 }
1024
1025 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001026 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001027 if ((d->d_name[0] == '.')
1028 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1029 || (d->d_name[1] == '\0'))) {
1030 continue;
1031 }
1032 const std::string new_path =
1033 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1034 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1035 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1036 printf("\n");
1037 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001038 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001039}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001040
1041static void DumpPacketStats() {
1042 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1043 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1044 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1045 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1046 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1047}
1048
1049static void DumpIpAddrAndRules() {
1050 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1051 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1052 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1053 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1054 RunCommand("IP RULES", {"ip", "rule", "show"});
1055 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1056}
1057
Vishnu Nair780b1282017-10-10 13:57:24 -07001058// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1059static void RunDumpsysCritical() {
1060 if (ds.CurrentVersionSupportsPriorityDumps()) {
1061 RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
1062 CommandOptions::WithTimeout(5).DropRoot().Build());
1063 } else {
1064 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1065 CommandOptions::WithTimeout(90).DropRoot().Build());
1066 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1067 CommandOptions::WithTimeout(10).DropRoot().Build());
1068 }
1069}
1070
1071// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1072static void RunDumpsysHigh() {
1073 if (ds.CurrentVersionSupportsPriorityDumps()) {
1074 RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
1075 CommandOptions::WithTimeout(20).DropRoot().Build());
1076 } else {
1077 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
1078 }
1079}
1080
1081// Runs dumpsys on services that must dump but can take up to 10s to dump.
1082static void RunDumpsysNormal() {
1083 if (ds.CurrentVersionSupportsPriorityDumps()) {
1084 RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
1085 CommandOptions::WithTimeout(90).DropRoot().Build());
1086 } else {
1087 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
1088 CommandOptions::WithTimeout(90).Build(), 10);
1089 }
1090}
1091
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001092static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001093 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001094
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001095 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
pengzhicai24ae8192017-05-25 17:29:33 +08001096 /* TODO: Remove duplicate uptime call when tools use it from header */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001097 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001098 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001099 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001100 DumpFile("MEMORY INFO", "/proc/meminfo");
1101 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001102 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001103 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001104 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1105 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1106 DumpFile("SLAB INFO", "/proc/slabinfo");
1107 DumpFile("ZONEINFO", "/proc/zoneinfo");
1108 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1109 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1110 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001111
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001112 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1113 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1114 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001115
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001116 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001117 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001118 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001119
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001120 if (ds.IsZipping()) {
1121 RunCommand(
1122 "HARDWARE HALS",
1123 {"lshal", std::string("--debug=") + kLsHalDebugPath},
Yifan Hong48e83a12017-10-03 14:10:07 -07001124 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001125
1126 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1127
1128 unlink(kLsHalDebugPath.c_str());
1129 } else {
1130 RunCommand(
Yifan Hong48e83a12017-10-03 14:10:07 -07001131 "HARDWARE HALS", {"lshal", "--debug"},
1132 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001133 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001136 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001137 struct stat s;
1138 if (stat("/proc/modules", &s) != 0) {
1139 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1140 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001141 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001142 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001143
Colin Crossf45fa6b2012-03-26 12:38:26 -07001144 do_dmesg();
1145
Felipe Lemef0292972016-11-22 13:57:05 -08001146 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001147 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1148 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001149 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001150
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001151 /* Dump Bluetooth HCI logs */
1152 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001153
Felipe Leme9a523ae2016-10-20 15:10:33 -07001154 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001155 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001156 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001157 }
1158
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001159 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001160
Felipe Lemee184f662016-10-27 10:04:47 -07001161 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001162
Narayan Kamath8f788292017-05-25 13:20:39 +01001163 // NOTE: tombstones are always added as separate entries in the zip archive
1164 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001165 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1166 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001167 if (!tombstones_dumped) {
1168 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001169 }
1170
Jayachandran Ca94c7172017-06-10 15:08:12 -07001171 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001172
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001173 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001174
Jayachandran Ca94c7172017-06-10 15:08:12 -07001175 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001176
1177 dump_route_tables();
1178
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001179 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1180 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1181 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001182
Vishnu Nair780b1282017-10-10 13:57:24 -07001183 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001184
Elliott Hughes23ccc622017-02-28 10:14:22 -08001185 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001186
Jin Qianf334d662017-10-10 14:41:37 -07001187 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001188
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001189 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001190
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001191 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001192
Felipe Lemed8b94e52016-12-08 10:21:44 -08001193 printf("------ BACKLIGHTS ------\n");
1194 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001195 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001196 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001197 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001198 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001199 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001200 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001201 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001202 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001203 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001204 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001205
1206 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001207 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1208 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1209 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1210 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1211 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001212
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001213 /* Add window and surface trace files. */
1214 if (!PropertiesHelper::IsUserBuild()) {
1215 ds.AddDir(WMTRACE_DATA_DIR, false);
1216 }
1217
Felipe Leme6f674ae2016-11-18 17:10:33 -08001218 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001219
Steven Moreland7440ddb2016-12-15 16:13:39 -08001220 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001221 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1222 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001223 // su does not exist on user builds, so try running without it.
1224 // This way any implementations of vril-dump that do not require
1225 // root can run on user builds.
1226 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001227 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001228 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001229 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001231 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001232 }
1233
Felipe Lemed8b94e52016-12-08 10:21:44 -08001234 printf("========================================================\n");
1235 printf("== Android Framework Services\n");
1236 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001237
Vishnu Nair780b1282017-10-10 13:57:24 -07001238 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001239
Felipe Lemed8b94e52016-12-08 10:21:44 -08001240 printf("========================================================\n");
1241 printf("== Checkins\n");
1242 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001243
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001244 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1245 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1246 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1247 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1248 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1249 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001250
Felipe Lemed8b94e52016-12-08 10:21:44 -08001251 printf("========================================================\n");
1252 printf("== Running Application Activities\n");
1253 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001254
Winson Chung1434a5c2017-02-28 17:09:24 -08001255 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001256
Felipe Lemed8b94e52016-12-08 10:21:44 -08001257 printf("========================================================\n");
1258 printf("== Running Application Services\n");
1259 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001260
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001261 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001262
Felipe Lemed8b94e52016-12-08 10:21:44 -08001263 printf("========================================================\n");
1264 printf("== Running Application Providers\n");
1265 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001266
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001267 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001268
Adrian Roos8b397ab2017-04-04 16:35:44 -07001269 printf("========================================================\n");
1270 printf("== Dropbox crashes\n");
1271 printf("========================================================\n");
1272
1273 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1274 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1275
Felipe Lemed8b94e52016-12-08 10:21:44 -08001276 printf("========================================================\n");
1277 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1278 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1279 printf("========================================================\n");
1280 printf("== dumpstate: done (id %d)\n", ds.id_);
1281 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001282}
1283
Jayachandran Ca94c7172017-06-10 15:08:12 -07001284// This method collects dumpsys for telephony debugging only
1285static void DumpstateTelephonyOnly() {
1286 DurationReporter duration_reporter("DUMPSTATE");
1287
1288 DumpIpTablesAsRoot();
1289
1290 if (!DropRootUser()) {
1291 return;
1292 }
1293
1294 do_dmesg();
1295 DoLogcat();
1296 DumpPacketStats();
1297 DoKmsg();
1298 DumpIpAddrAndRules();
1299 dump_route_tables();
1300
1301 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1302 CommandOptions::WithTimeout(10).Build());
1303
1304 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1305
1306 printf("========================================================\n");
1307 printf("== Android Framework Services\n");
1308 printf("========================================================\n");
1309
1310 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1311 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1312
1313 printf("========================================================\n");
1314 printf("== Running Application Services\n");
1315 printf("========================================================\n");
1316
1317 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1318
1319 printf("========================================================\n");
1320 printf("== dumpstate: done (id %d)\n", ds.id_);
1321 printf("========================================================\n");
1322}
1323
Felipe Leme6f674ae2016-11-18 17:10:33 -08001324void Dumpstate::DumpstateBoard() {
1325 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001326 printf("========================================================\n");
1327 printf("== Board\n");
1328 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001329
Chris Phoenix69d92212017-01-24 23:01:13 -08001330 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001331 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001332 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001333 return;
1334 }
1335
1336 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001337 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001338 return;
1339 }
1340
Jie Song9fbfad02017-06-20 16:29:42 -07001341 std::string path[NUM_OF_DUMPS];
1342 android::base::unique_fd fd[NUM_OF_DUMPS];
1343 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001344
Jie Song9fbfad02017-06-20 16:29:42 -07001345 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1346 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1347 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1348
1349 fd[i] = android::base::unique_fd(
1350 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1351 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1352 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1353 if (fd[i] < 0) {
1354 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1355 return;
1356 } else {
1357 numFds++;
1358 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001359 }
1360
Jie Song9fbfad02017-06-20 16:29:42 -07001361 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001362 if (handle == nullptr) {
1363 MYLOGE("Could not create native_handle\n");
1364 return;
1365 }
Jie Song9fbfad02017-06-20 16:29:42 -07001366
1367 for (int i = 0; i < numFds; i++) {
1368 handle->data[i] = fd[i].release();
1369 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001370
Felipe Lemef0292972016-11-22 13:57:05 -08001371 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001372 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1373 if (!status.isOk()) {
1374 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1375 native_handle_close(handle);
1376 native_handle_delete(handle);
1377 return;
1378 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001379
Jie Song9fbfad02017-06-20 16:29:42 -07001380 for (int i = 0; i < numFds; i++) {
1381 struct stat s;
1382 if (fstat(handle->data[i], &s) == -1) {
1383 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1384 } else if (s.st_size > 0) {
1385 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1386 } else {
1387 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1388 }
1389 }
1390
Felipe Lemed8b94e52016-12-08 10:21:44 -08001391 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001392
1393 native_handle_close(handle);
1394 native_handle_delete(handle);
1395
Jie Song9fbfad02017-06-20 16:29:42 -07001396 for (int i = 0; i < numFds; i++) {
1397 if (remove(path[i].c_str()) != 0) {
1398 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1399 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001400 }
1401}
1402
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001403static void ShowUsageAndExit(int exitCode = 1) {
1404 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001405 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001406 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1407 " -h: display this help message\n"
1408 " -b: play sound file instead of vibrate, at beginning of job\n"
1409 " -e: play sound file instead of vibrate, at end of job\n"
1410 " -o: write to file (instead of stdout)\n"
1411 " -d: append date to filename (requires -o)\n"
1412 " -p: capture screenshot to filename.png (requires -o)\n"
1413 " -z: generate zipped file (requires -o)\n"
1414 " -s: write output to control socket (for init)\n"
1415 " -S: write file location to control socket (for init; requires -o and -z)"
1416 " -q: disable vibrate\n"
1417 " -B: send broadcast when finished (requires -o)\n"
1418 " -P: send broadcast when started and update system properties on "
1419 "progress (requires -o and -B)\n"
1420 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1421 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001422 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001423 exit(exitCode);
1424}
1425
1426static void ExitOnInvalidArgs() {
1427 fprintf(stderr, "invalid combination of args\n");
1428 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001429}
1430
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001431static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001432 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001433}
1434
Wei Liuf87959e2016-08-26 14:51:42 -07001435static void register_sig_handler() {
1436 struct sigaction sa;
1437 sigemptyset(&sa.sa_mask);
1438 sa.sa_flags = 0;
1439 sa.sa_handler = sig_handler;
1440 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1441 sigaction(SIGSEGV, &sa, NULL); // segment fault
1442 sigaction(SIGINT, &sa, NULL); // ctrl-c
1443 sigaction(SIGTERM, &sa, NULL); // killed
1444 sigaction(SIGQUIT, &sa, NULL); // quit
1445}
1446
Felipe Leme1d486fe2016-10-14 18:06:47 -07001447bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001448 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001449 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001450 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001451 // Final timestamp
1452 char date[80];
1453 time_t the_real_now_please_stand_up = time(nullptr);
1454 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001455 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001456 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001457
Felipe Leme9a523ae2016-10-20 15:10:33 -07001458 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001459 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001460 return false;
1461 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001462 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001463 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001464 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001465 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001466
Felipe Leme0f3fb202016-06-10 17:10:53 -07001467 // Add log file (which contains stderr output) to zip...
1468 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001469 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001470 MYLOGE("Failed to add dumpstate log to .zip file\n");
1471 return false;
1472 }
1473 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001474 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001475 fprintf(stderr, "\n");
1476
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001477 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001478 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001479 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001480 return false;
1481 }
1482
Felipe Leme1d486fe2016-10-14 18:06:47 -07001483 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1484 ds.zip_file.reset(nullptr);
1485
Felipe Lemee9d2c542016-11-15 11:48:26 -08001486 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1487 if (remove(tmp_path_.c_str()) != 0) {
1488 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001489 }
1490
Felipe Leme1e9edc62015-12-21 16:02:13 -08001491 return true;
1492}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001493
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001494static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001495 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1496 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001497 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001498 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001499 return NULL;
1500 }
1501
1502 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001503 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001504
1505 std::vector<uint8_t> buffer(65536);
1506 while (1) {
1507 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1508 if (bytes_read == 0) {
1509 break;
1510 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001511 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001512 return NULL;
1513 }
1514
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001515 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001516 }
1517
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001518 uint8_t hash[SHA256_DIGEST_LENGTH];
1519 SHA256_Final(hash, &ctx);
1520
1521 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1522 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001523 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001524 }
1525 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1526 return std::string(hash_buffer);
1527}
1528
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001529static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1530 // clang-format off
1531 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1532 "--receiver-foreground", "--receiver-include-background", "-a", action};
1533 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001534
1535 am.insert(am.end(), args.begin(), args.end());
1536
Felipe Leme8d2410e2017-02-08 09:46:08 -08001537 RunCommand("", am,
1538 CommandOptions::WithTimeout(20)
1539 .Log("Sending broadcast: '%s'\n")
1540 .Always()
1541 .DropRoot()
1542 .RedirectStderr()
1543 .Build());
1544}
1545
Felipe Leme35b8cf12017-02-10 15:47:29 -08001546static void Vibrate(int duration_ms) {
1547 // clang-format off
1548 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1549 CommandOptions::WithTimeout(10)
1550 .Log("Vibrate: '%s'\n")
1551 .Always()
1552 .Build());
1553 // clang-format on
1554}
1555
Colin Crossf45fa6b2012-03-26 12:38:26 -07001556int main(int argc, char *argv[]) {
1557 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001558 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001559 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001560 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001561 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001562 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001563 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001564 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001565 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001566 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001567 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001568 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001569
Colin Crossf45fa6b2012-03-26 12:38:26 -07001570 /* set as high priority, and protect from OOM killer */
1571 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001572
Felipe Lemed071c682016-10-20 16:48:00 -07001573 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001574 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001575 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001576 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001577 } else {
1578 /* fallback to kernels <= 2.6.35 */
1579 oom_adj = fopen("/proc/self/oom_adj", "we");
1580 if (oom_adj) {
1581 fputs("-17", oom_adj);
1582 fclose(oom_adj);
1583 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001584 }
1585
Jeff Brown1dc94e32014-09-11 14:15:27 -07001586 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001587 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001588 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001589 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001590 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001591 case 'd': do_add_date = 1; break;
1592 case 'z': do_zip_file = 1; break;
1593 case 'o': use_outfile = optarg; break;
1594 case 's': use_socket = 1; break;
1595 case 'S': use_control_socket = 1; break;
1596 case 'v': show_header_only = true; break;
1597 case 'q': do_vibrate = 0; break;
1598 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001599 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001600 case 'R': is_remote_mode = 1; break;
1601 case 'B': do_broadcast = 1; break;
1602 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001603 case 'h':
1604 ShowUsageAndExit(0);
1605 break;
1606 default:
1607 fprintf(stderr, "Invalid option: %c\n", c);
1608 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001609 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001610 }
1611 }
1612
Felipe Lemed071c682016-10-20 16:48:00 -07001613 // TODO: use helper function to convert argv into a string
1614 for (int i = 0; i < argc; i++) {
1615 ds.args_ += argv[i];
1616 if (i < argc - 1) {
1617 ds.args_ += " ";
1618 }
1619 }
1620
1621 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001622 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001623 // Framework uses a system property to override some command-line args.
1624 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001625 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001626 // Currently, the dumpstate binder is only used by Shell to update progress.
1627 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001628 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001629 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001630 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001631 do_vibrate = 0;
1632 is_remote_mode = 1;
1633 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001634 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001635 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001636 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001637 } else if (ds.extra_options_ == "bugreporttelephony") {
1638 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001639 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001640 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001641 }
1642 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001643 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001644 }
1645
Naveen Kallab53a1c92017-03-16 18:17:25 -07001646 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1647 if (!ds.notification_title.empty()) {
1648 // Reset the property
1649 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1650
1651 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1652 if (!ds.notification_description.empty()) {
1653 // Reset the property
1654 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1655 }
1656 MYLOGD("notification (title: %s, description: %s)\n",
1657 ds.notification_title.c_str(), ds.notification_description.c_str());
1658 }
1659
Felipe Leme9a523ae2016-10-20 15:10:33 -07001660 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001661 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001662 }
1663
Felipe Leme2628e9e2016-04-12 16:36:51 -07001664 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001665 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001666 }
1667
Felipe Leme9a523ae2016-10-20 15:10:33 -07001668 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001669 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001670 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001671
Felipe Leme9a523ae2016-10-20 15:10:33 -07001672 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001673 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001674 }
1675
Felipe Lemed071c682016-10-20 16:48:00 -07001676 if (ds.version_ == VERSION_DEFAULT) {
1677 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001678 }
1679
Vishnu Nair780b1282017-10-10 13:57:24 -07001680 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR &&
1681 ds.version_ != VERSION_PRIORITY_DUMPS) {
1682 MYLOGE(
1683 "invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s', '%s')\n",
1684 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1685 VERSION_SPLIT_ANR.c_str(), VERSION_PRIORITY_DUMPS.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001686 exit(1);
1687 }
1688
1689 if (show_header_only) {
1690 ds.PrintHeader();
1691 exit(0);
1692 }
1693
Felipe Leme7447d7c2016-11-03 18:12:22 -07001694 /* redirect output if needed */
1695 bool is_redirecting = !use_socket && use_outfile;
1696
1697 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1698 std::string stats_path =
1699 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1700 : "";
1701 ds.progress_.reset(new Progress(stats_path));
1702
Felipe Lemed071c682016-10-20 16:48:00 -07001703 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001704 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001705 ds.id_ = ++last_id;
1706 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1707
1708 MYLOGI("begin\n");
1709
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001710 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001711
Felipe Leme75876a22016-10-27 16:31:27 -07001712 if (do_start_service) {
1713 MYLOGI("Starting 'dumpstate' service\n");
1714 android::status_t ret;
1715 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1716 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1717 }
1718 }
1719
Felipe Lemef0292972016-11-22 13:57:05 -08001720 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001721 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1722 }
1723
Felipe Leme7447d7c2016-11-03 18:12:22 -07001724 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001725 ds.extra_options_.c_str());
1726
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001727 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001728
Felipe Leme9a523ae2016-10-20 15:10:33 -07001729 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001730
Christopher Ferrised9354f2014-10-01 17:35:01 -07001731 // If we are going to use a socket, do it as early as possible
1732 // to avoid timeouts from bugreport.
1733 if (use_socket) {
1734 redirect_to_socket(stdout, "dumpstate");
1735 }
1736
Felipe Leme2628e9e2016-04-12 16:36:51 -07001737 if (use_control_socket) {
1738 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001739 ds.control_socket_fd_ = open_socket("dumpstate");
1740 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001741 }
1742
Felipe Leme71bbfc52015-11-23 14:14:51 -08001743 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001744 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001745 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001746 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001747 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1748 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001749 if (do_add_date) {
1750 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001751 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001752 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001753 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001754 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001755 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001756
1757 if (telephony_only) {
1758 ds.base_name_ += "-telephony";
1759 }
1760
Felipe Leme71bbfc52015-11-23 14:14:51 -08001761 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001762 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001763 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001764 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001765 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001766
Felipe Lemee844a9d2016-09-21 15:01:39 -07001767 MYLOGD(
1768 "Bugreport dir: %s\n"
1769 "Base name: %s\n"
1770 "Suffix: %s\n"
1771 "Log path: %s\n"
1772 "Temporary path: %s\n"
1773 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001774 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1775 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001776
Felipe Leme1e9edc62015-12-21 16:02:13 -08001777 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001778 ds.path_ = ds.GetPath(".zip");
1779 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1780 create_parent_dirs(ds.path_.c_str());
1781 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001782 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001783 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001784 do_zip_file = 0;
1785 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001786 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001787 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001788 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001789 }
1790
Felipe Leme9a523ae2016-10-20 15:10:33 -07001791 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001792 if (do_broadcast) {
1793 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001794
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001795 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001796 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001797 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001798 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001799 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001800 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001801 };
1802 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001803 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001804 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001805 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001806 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001807 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001808 }
1809 }
1810
Nick Kralevichf3599b32016-01-25 15:05:16 -08001811 /* read /proc/cmdline before dropping root */
1812 FILE *cmdline = fopen("/proc/cmdline", "re");
1813 if (cmdline) {
1814 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1815 fclose(cmdline);
1816 }
1817
John Michelau1f794c42012-09-17 11:20:19 -05001818 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001819 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001820 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001821
Felipe Leme9a523ae2016-10-20 15:10:33 -07001822 if (do_fb && ds.do_early_screenshot_) {
1823 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001824 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001825 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001826 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001827 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001828 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001829 }
1830 }
1831
Felipe Leme1e9edc62015-12-21 16:02:13 -08001832 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001833 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1834 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001835 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001836 }
1837 }
1838
Felipe Leme71bbfc52015-11-23 14:14:51 -08001839 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001840 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1841 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1842 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1843 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001844 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001845 /* TODO: rather than generating a text file now and zipping it later,
1846 it would be more efficient to redirect stdout to the zip entry
1847 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001848 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1849 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001850 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001851 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001852 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001853 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001854
1855 // Don't buffer stdout
1856 setvbuf(stdout, nullptr, _IONBF, 0);
1857
Felipe Leme608385d2016-02-01 10:35:38 -08001858 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1859 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001860 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001861 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001862
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001863 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001864 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001865 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001866 } else {
1867 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1868 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1869 // the raw trace.
1870 if (!dump_anrd_trace()) {
1871 dump_systrace();
1872 }
1873
1874 // Invoking the following dumpsys calls before dump_traces() to try and
1875 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07001876 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001877
1878 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1879 dump_raft();
1880
1881 /* collect stack traces from Dalvik and native processes (needs root) */
1882 dump_traces_path = dump_traces();
1883
1884 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001885 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1886 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001887
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001888 ds.AddDir(RECOVERY_DIR, true);
1889 ds.AddDir(RECOVERY_DATA_DIR, true);
1890 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1891 if (!PropertiesHelper::IsUserBuild()) {
1892 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1893 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1894 }
1895 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001896 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001897
1898 // Capture any IPSec policies in play. No keys are exposed here.
1899 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1900 CommandOptions::WithTimeout(10).Build());
1901
1902 // Run ss as root so we can see socket marks.
1903 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1904 CommandOptions::WithTimeout(10).Build());
1905
Jin Qian3cd671e2017-09-27 18:50:04 -07001906 // Run iotop as root to show top 100 IO threads
1907 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1908
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001909 if (!DropRootUser()) {
1910 return -1;
1911 }
1912
1913 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001914 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001915
Felipe Leme55b42a62015-11-10 17:39:08 -08001916 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001917 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001918 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001919 }
1920
Felipe Leme6e01fa62015-11-11 19:35:14 -08001921 /* rename or zip the (now complete) .tmp file to its final location */
1922 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001923
1924 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001925 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001926 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001927 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001928 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001929 /* must whitelist which characters are allowed, otherwise it could cross directories */
1930 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001931 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001932 change_suffix = true;
1933 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001934 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001935 }
1936 }
1937 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001938 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1939 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001940 if (!ds.screenshot_path_.empty()) {
1941 std::string new_screenshot_path = ds.GetPath(".png");
1942 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1943 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1944 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001945 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001946 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001947 }
1948 }
1949 }
1950
Felipe Leme6e01fa62015-11-11 19:35:14 -08001951 bool do_text_file = true;
1952 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001953 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001954 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001955 do_text_file = true;
1956 } else {
1957 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001958 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001959 std::string new_path = ds.GetPath(".zip");
1960 if (ds.path_ != new_path) {
1961 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1962 if (rename(ds.path_.c_str(), new_path.c_str())) {
1963 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001964 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001965 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001966 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001967 }
1968 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001969 }
1970 }
1971 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001972 ds.path_ = ds.GetPath(".txt");
1973 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1974 ds.tmp_path_.c_str());
1975 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1976 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001977 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001978 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001979 }
1980 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001981 if (use_control_socket) {
1982 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001983 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001984 "FAIL:could not create zip file, check %s "
1985 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001986 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001987 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001988 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001989 }
1990 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001991 }
1992
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001993 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001994 for (int i = 0; i < 3; i++) {
1995 Vibrate(75);
1996 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001997 }
1998
Jeff Brown1dc94e32014-09-11 14:15:27 -07001999 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002000 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002001 if (!ds.path_.empty()) {
2002 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002003 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002004
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002005 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002006 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002007 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002008 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002009 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002010 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2011 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002012 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002013 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002014 if (do_fb) {
2015 am_args.push_back("--es");
2016 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002017 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002018 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002019 if (!ds.notification_title.empty()) {
2020 am_args.push_back("--es");
2021 am_args.push_back("android.intent.extra.TITLE");
2022 am_args.push_back(ds.notification_title);
2023 if (!ds.notification_description.empty()) {
2024 am_args.push_back("--es");
2025 am_args.push_back("android.intent.extra.DESCRIPTION");
2026 am_args.push_back(ds.notification_description);
2027 }
2028 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002029 if (is_remote_mode) {
2030 am_args.push_back("--es");
2031 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002032 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002033 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2034 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002035 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002036 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002037 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002038 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002039 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002040 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002041 }
2042
Felipe Leme7447d7c2016-11-03 18:12:22 -07002043 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2044 ds.progress_->GetInitialMax());
2045 ds.progress_->Save();
2046 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002047
Felipe Leme107a05f2016-03-08 15:11:15 -08002048 if (is_redirecting) {
2049 fclose(stderr);
2050 }
2051
Felipe Leme9a523ae2016-10-20 15:10:33 -07002052 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002053 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002054 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002055 }
2056
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002057 CloseDumpFds(tombstone_data.get());
2058 CloseDumpFds(anr_data.get());
2059
Colin Crossf45fa6b2012-03-26 12:38:26 -07002060 return 0;
2061}