blob: 364ead0d18cfc793e978179493ce2dfc38c088ef [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,
Felipe Leme678727a2016-09-21 17:22:11 -0700116 long dumpsysTimeout = 0) {
117 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
118}
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() {
833 unsigned long timeout;
834 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
835 // calculate timeout
836 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
837 if (timeout < 20000) {
838 timeout = 20000;
839 }
Tony Makae737652017-03-30 17:47:09 +0100840 RunCommand("SYSTEM LOG",
841 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
842 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800843 CommandOptions::WithTimeout(timeout / 1000).Build());
844 timeout = logcat_timeout("events");
845 if (timeout < 20000) {
846 timeout = 20000;
847 }
848 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100849 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
850 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800851 CommandOptions::WithTimeout(timeout / 1000).Build());
852 timeout = logcat_timeout("radio");
853 if (timeout < 20000) {
854 timeout = 20000;
855 }
856 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100857 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
858 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800859 CommandOptions::WithTimeout(timeout / 1000).Build());
860
861 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
862
863 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
864 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100865 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
866 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800867}
868
Jayachandran Ca94c7172017-06-10 15:08:12 -0700869static void DumpIpTablesAsRoot() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700870 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
871 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900872 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700873 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900874 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
875 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
876 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
877 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700878}
879
Narayan Kamath8f788292017-05-25 13:20:39 +0100880static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
881 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700882 std::string dump_traces_dir;
883
Felipe Lemee184f662016-10-27 10:04:47 -0700884 if (dump_traces_path != nullptr) {
885 if (add_to_zip) {
886 dump_traces_dir = dirname(dump_traces_path);
887 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
888 ds.AddDir(dump_traces_dir, true);
889 } else {
890 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
891 dump_traces_path);
892 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
893 }
894 }
895
Felipe Lemee184f662016-10-27 10:04:47 -0700896
897 // Make sure directory is not added twice.
898 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
899 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
900 // property - but in reality they're the same path (although the former could be nullptr).
901 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
902 // be revisited.
903 bool already_dumped = anr_traces_dir == dump_traces_dir;
904
Narayan Kamath8f788292017-05-25 13:20:39 +0100905 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700906 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
907
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100908 android::base::unique_fd fd(TEMP_FAILURE_RETRY(
909 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
910 if (fd.get() < 0) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100911 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700912 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100913 if (add_to_zip) {
914 if (!already_dumped) {
915 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
916 anr_traces_dir.c_str());
917 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700918 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100919 } else {
920 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
921 anr_traces_file.c_str());
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100922 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get());
Narayan Kamath8f788292017-05-25 13:20:39 +0100923 }
924 }
925}
926
927static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
928 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
929 anr_traces_dir.c_str());
930
931 // If we're here, dump_traces_path will always be a temporary file
932 // (created with mkostemp or similar) that contains dumps taken earlier
933 // on in the process.
934 if (dump_traces_path != nullptr) {
935 if (add_to_zip) {
936 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
937 } else {
938 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
939 dump_traces_path);
940 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
941 }
942
943 const int ret = unlink(dump_traces_path);
944 if (ret == -1) {
945 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
946 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700947 }
948 }
949
Narayan Kamathbd863722017-06-01 18:50:12 +0100950 // Add a specific message for the first ANR Dump.
951 if (anr_data->size() > 0) {
952 AddDumps(anr_data->begin(), anr_data->begin() + 1,
953 "VM TRACES AT LAST ANR", add_to_zip);
954
Narayan Kamath6b9516c2017-10-27 11:15:51 +0100955 // The "last" ANR will always be included as separate entry in the zip file. In addition,
956 // it will be present in the body of the main entry if |add_to_zip| == false.
957 //
958 // Historical ANRs are always included as separate entries in the bugreport zip file.
959 AddDumps(anr_data->begin() + ((add_to_zip) ? 1 : 0), anr_data->end(),
960 "HISTORICAL ANR", true /* add_to_zip */);
Narayan Kamathbd863722017-06-01 18:50:12 +0100961 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100962 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
963 }
964}
965
966static void AddAnrTraceFiles() {
967 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
968
969 std::string anr_traces_file;
970 std::string anr_traces_dir;
971 bool is_global_trace_file = true;
972
973 // First check whether the stack-trace-dir property is set. When it's set,
974 // each ANR trace will be written to a separate file and not to a global
975 // stack trace file.
976 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
977 if (anr_traces_dir.empty()) {
978 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
979 if (!anr_traces_file.empty()) {
Narayan Kamath8f788292017-05-25 13:20:39 +0100980 anr_traces_dir = dirname(anr_traces_file.c_str());
981 }
Narayan Kamathbd863722017-06-01 18:50:12 +0100982 } else {
983 is_global_trace_file = false;
Narayan Kamath8f788292017-05-25 13:20:39 +0100984 }
985
986 // We have neither configured a global trace file nor a trace directory,
987 // there will be nothing to dump.
988 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
989 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -0700990 return;
991 }
992
Narayan Kamath8f788292017-05-25 13:20:39 +0100993 if (is_global_trace_file) {
994 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
995 } else {
996 AddAnrTraceDir(add_to_zip, anr_traces_dir);
997 }
998
Felipe Lemee184f662016-10-27 10:04:47 -0700999 /* slow traces for slow operations */
1000 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001001 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001002 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001003 while (true) {
1004 const std::string slow_trace_path =
1005 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1006 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001007 // No traces file at this index, done with the files.
1008 break;
1009 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001010 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001011 i++;
1012 }
1013 }
1014}
1015
Wei Wang509bb5d2017-06-09 14:42:12 -07001016static void DumpBlockStatFiles() {
1017 DurationReporter duration_reporter("DUMP BLOCK STAT");
Wei Wang509bb5d2017-06-09 14:42:12 -07001018
Wei Wang1dc1ef52017-06-12 11:28:37 -07001019 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir);
1020
1021 if (dirptr == nullptr) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001022 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno));
1023 return;
1024 }
1025
1026 printf("------ DUMP BLOCK STAT ------\n\n");
Wei Wang1dc1ef52017-06-12 11:28:37 -07001027 while (struct dirent *d = readdir(dirptr.get())) {
Wei Wang509bb5d2017-06-09 14:42:12 -07001028 if ((d->d_name[0] == '.')
1029 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
1030 || (d->d_name[1] == '\0'))) {
1031 continue;
1032 }
1033 const std::string new_path =
1034 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name);
1035 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str());
1036 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd);
1037 printf("\n");
1038 }
Wei Wang1dc1ef52017-06-12 11:28:37 -07001039 return;
Wei Wang509bb5d2017-06-09 14:42:12 -07001040}
Jayachandran Ca94c7172017-06-10 15:08:12 -07001041
1042static void DumpPacketStats() {
1043 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1044 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1045 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1046 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1047 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
1048}
1049
1050static void DumpIpAddrAndRules() {
1051 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
1052 RunCommand("NETWORK INTERFACES", {"ip", "link"});
1053 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1054 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
1055 RunCommand("IP RULES", {"ip", "rule", "show"});
1056 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
1057}
1058
Vishnu Nair780b1282017-10-10 13:57:24 -07001059// Runs dumpsys on services that must dump first and and will take less than 100ms to dump.
1060static void RunDumpsysCritical() {
1061 if (ds.CurrentVersionSupportsPriorityDumps()) {
1062 RunDumpsys("DUMPSYS CRITICAL", {"--priority", "CRITICAL"},
1063 CommandOptions::WithTimeout(5).DropRoot().Build());
1064 } else {
1065 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1066 CommandOptions::WithTimeout(90).DropRoot().Build());
1067 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1068 CommandOptions::WithTimeout(10).DropRoot().Build());
1069 }
1070}
1071
1072// Runs dumpsys on services that must dump first but can take up to 250ms to dump.
1073static void RunDumpsysHigh() {
1074 if (ds.CurrentVersionSupportsPriorityDumps()) {
1075 RunDumpsys("DUMPSYS HIGH", {"--priority", "HIGH"},
1076 CommandOptions::WithTimeout(20).DropRoot().Build());
1077 } else {
1078 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"});
1079 }
1080}
1081
1082// Runs dumpsys on services that must dump but can take up to 10s to dump.
1083static void RunDumpsysNormal() {
1084 if (ds.CurrentVersionSupportsPriorityDumps()) {
1085 RunDumpsys("DUMPSYS NORMAL", {"--priority", "NORMAL"},
1086 CommandOptions::WithTimeout(90).DropRoot().Build());
1087 } else {
1088 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"},
1089 CommandOptions::WithTimeout(90).Build(), 10);
1090 }
1091}
1092
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001093static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001094 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001095
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001096 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
pengzhicai24ae8192017-05-25 17:29:33 +08001097 /* TODO: Remove duplicate uptime call when tools use it from header */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001098 RunCommand("UPTIME", {"uptime"});
Wei Wang509bb5d2017-06-09 14:42:12 -07001099 DumpBlockStatFiles();
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001100 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001101 DumpFile("MEMORY INFO", "/proc/meminfo");
1102 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001103 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001104 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001105 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1106 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1107 DumpFile("SLAB INFO", "/proc/slabinfo");
1108 DumpFile("ZONEINFO", "/proc/zoneinfo");
1109 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1110 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1111 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001112
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001113 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1114 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1115 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001116
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001117 RunCommand("PROCESSES AND THREADS",
Yohei Yukawa591a72d2017-10-05 21:36:35 -07001118 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"});
Felipe Lemef0292972016-11-22 13:57:05 -08001119 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001120
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001121 if (ds.IsZipping()) {
1122 RunCommand(
1123 "HARDWARE HALS",
1124 {"lshal", std::string("--debug=") + kLsHalDebugPath},
Yifan Hong48e83a12017-10-03 14:10:07 -07001125 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001126
1127 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1128
1129 unlink(kLsHalDebugPath.c_str());
1130 } else {
1131 RunCommand(
Yifan Hong48e83a12017-10-03 14:10:07 -07001132 "HARDWARE HALS", {"lshal", "--debug"},
1133 CommandOptions::WithTimeout(10).AsRootIfAvailable().Build());
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001134 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001135
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001136 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001137 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001138 struct stat s;
1139 if (stat("/proc/modules", &s) != 0) {
1140 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1141 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001142 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001143 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001144
Colin Crossf45fa6b2012-03-26 12:38:26 -07001145 do_dmesg();
1146
Felipe Lemef0292972016-11-22 13:57:05 -08001147 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001148 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1149 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001150 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001151
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001152 /* Dump Bluetooth HCI logs */
1153 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001154
Felipe Leme9a523ae2016-10-20 15:10:33 -07001155 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001156 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001157 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001158 }
1159
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001160 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001161
Felipe Lemee184f662016-10-27 10:04:47 -07001162 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001163
Narayan Kamath8f788292017-05-25 13:20:39 +01001164 // NOTE: tombstones are always added as separate entries in the zip archive
1165 // and are not interspersed with the main report.
Narayan Kamathbd863722017-06-01 18:50:12 +01001166 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(),
1167 "TOMBSTONE", true /* add_to_zip */);
Narayan Kamath8f788292017-05-25 13:20:39 +01001168 if (!tombstones_dumped) {
1169 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001170 }
1171
Jayachandran Ca94c7172017-06-10 15:08:12 -07001172 DumpPacketStats();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001173
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001174 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001175
Jayachandran Ca94c7172017-06-10 15:08:12 -07001176 DumpIpAddrAndRules();
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001177
1178 dump_route_tables();
1179
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001180 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1181 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1182 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001183
Vishnu Nair780b1282017-10-10 13:57:24 -07001184 RunDumpsysHigh();
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001185
Elliott Hughes23ccc622017-02-28 10:14:22 -08001186 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001187
Jin Qianf334d662017-10-10 14:41:37 -07001188 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"});
ynwangf649a6e2016-07-17 21:56:00 -07001189
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001190 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001191
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001192 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001193
Felipe Lemed8b94e52016-12-08 10:21:44 -08001194 printf("------ BACKLIGHTS ------\n");
1195 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001196 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001197 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001198 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001199 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001200 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001201 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001202 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001203 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001204 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001205 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001206
1207 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001208 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1209 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1210 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1211 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1212 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001213
Vishnu Nair36b4cdb2017-11-17 10:27:05 -08001214 /* Add window and surface trace files. */
1215 if (!PropertiesHelper::IsUserBuild()) {
1216 ds.AddDir(WMTRACE_DATA_DIR, false);
1217 }
1218
Felipe Leme6f674ae2016-11-18 17:10:33 -08001219 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001220
Steven Moreland7440ddb2016-12-15 16:13:39 -08001221 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001222 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1223 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001224 // su does not exist on user builds, so try running without it.
1225 // This way any implementations of vril-dump that do not require
1226 // root can run on user builds.
1227 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001228 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001229 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001230 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001231 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001232 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001233 }
1234
Felipe Lemed8b94e52016-12-08 10:21:44 -08001235 printf("========================================================\n");
1236 printf("== Android Framework Services\n");
1237 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001238
Vishnu Nair780b1282017-10-10 13:57:24 -07001239 RunDumpsysNormal();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001240
Felipe Lemed8b94e52016-12-08 10:21:44 -08001241 printf("========================================================\n");
1242 printf("== Checkins\n");
1243 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001244
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001245 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1246 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1247 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1248 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1249 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1250 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001251
Felipe Lemed8b94e52016-12-08 10:21:44 -08001252 printf("========================================================\n");
1253 printf("== Running Application Activities\n");
1254 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001255
Winson Chung1434a5c2017-02-28 17:09:24 -08001256 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001257
Felipe Lemed8b94e52016-12-08 10:21:44 -08001258 printf("========================================================\n");
1259 printf("== Running Application Services\n");
1260 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001261
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001262 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001263
Felipe Lemed8b94e52016-12-08 10:21:44 -08001264 printf("========================================================\n");
1265 printf("== Running Application Providers\n");
1266 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001267
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001268 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001269
Adrian Roos8b397ab2017-04-04 16:35:44 -07001270 printf("========================================================\n");
1271 printf("== Dropbox crashes\n");
1272 printf("========================================================\n");
1273
1274 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1275 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1276
Felipe Lemed8b94e52016-12-08 10:21:44 -08001277 printf("========================================================\n");
1278 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1279 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1280 printf("========================================================\n");
1281 printf("== dumpstate: done (id %d)\n", ds.id_);
1282 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001283}
1284
Jayachandran Ca94c7172017-06-10 15:08:12 -07001285// This method collects dumpsys for telephony debugging only
1286static void DumpstateTelephonyOnly() {
1287 DurationReporter duration_reporter("DUMPSTATE");
1288
1289 DumpIpTablesAsRoot();
1290
1291 if (!DropRootUser()) {
1292 return;
1293 }
1294
1295 do_dmesg();
1296 DoLogcat();
1297 DumpPacketStats();
1298 DoKmsg();
1299 DumpIpAddrAndRules();
1300 dump_route_tables();
1301
1302 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
1303 CommandOptions::WithTimeout(10).Build());
1304
1305 RunCommand("SYSTEM PROPERTIES", {"getprop"});
1306
1307 printf("========================================================\n");
1308 printf("== Android Framework Services\n");
1309 printf("========================================================\n");
1310
1311 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 10);
1312 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 10);
1313
1314 printf("========================================================\n");
1315 printf("== Running Application Services\n");
1316 printf("========================================================\n");
1317
1318 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
1319
1320 printf("========================================================\n");
1321 printf("== dumpstate: done (id %d)\n", ds.id_);
1322 printf("========================================================\n");
1323}
1324
Felipe Leme6f674ae2016-11-18 17:10:33 -08001325void Dumpstate::DumpstateBoard() {
1326 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001327 printf("========================================================\n");
1328 printf("== Board\n");
1329 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001330
Chris Phoenix69d92212017-01-24 23:01:13 -08001331 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001332 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001333 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001334 return;
1335 }
1336
1337 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001338 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001339 return;
1340 }
1341
Jie Song9fbfad02017-06-20 16:29:42 -07001342 std::string path[NUM_OF_DUMPS];
1343 android::base::unique_fd fd[NUM_OF_DUMPS];
1344 int numFds = 0;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001345
Jie Song9fbfad02017-06-20 16:29:42 -07001346 for (int i = 0; i < NUM_OF_DUMPS; i++) {
1347 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i];
1348 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str());
1349
1350 fd[i] = android::base::unique_fd(
1351 TEMP_FAILURE_RETRY(open(path[i].c_str(),
1352 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1353 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1354 if (fd[i] < 0) {
1355 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno));
1356 return;
1357 } else {
1358 numFds++;
1359 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001360 }
1361
Jie Song9fbfad02017-06-20 16:29:42 -07001362 native_handle_t *handle = native_handle_create(numFds, 0);
Felipe Leme6f674ae2016-11-18 17:10:33 -08001363 if (handle == nullptr) {
1364 MYLOGE("Could not create native_handle\n");
1365 return;
1366 }
Jie Song9fbfad02017-06-20 16:29:42 -07001367
1368 for (int i = 0; i < numFds; i++) {
1369 handle->data[i] = fd[i].release();
1370 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001371
Felipe Lemef0292972016-11-22 13:57:05 -08001372 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001373 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1374 if (!status.isOk()) {
1375 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1376 native_handle_close(handle);
1377 native_handle_delete(handle);
1378 return;
1379 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001380
Jie Song9fbfad02017-06-20 16:29:42 -07001381 for (int i = 0; i < numFds; i++) {
1382 struct stat s;
1383 if (fstat(handle->data[i], &s) == -1) {
1384 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno);
1385 } else if (s.st_size > 0) {
1386 AddZipEntry(kDumpstateBoardFiles[i], path[i]);
1387 } else {
1388 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str());
1389 }
1390 }
1391
Felipe Lemed8b94e52016-12-08 10:21:44 -08001392 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001393
1394 native_handle_close(handle);
1395 native_handle_delete(handle);
1396
Jie Song9fbfad02017-06-20 16:29:42 -07001397 for (int i = 0; i < numFds; i++) {
1398 if (remove(path[i].c_str()) != 0) {
1399 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno));
1400 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001401 }
1402}
1403
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001404static void ShowUsageAndExit(int exitCode = 1) {
1405 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001406 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001407 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1408 " -h: display this help message\n"
1409 " -b: play sound file instead of vibrate, at beginning of job\n"
1410 " -e: play sound file instead of vibrate, at end of job\n"
1411 " -o: write to file (instead of stdout)\n"
1412 " -d: append date to filename (requires -o)\n"
1413 " -p: capture screenshot to filename.png (requires -o)\n"
1414 " -z: generate zipped file (requires -o)\n"
1415 " -s: write output to control socket (for init)\n"
1416 " -S: write file location to control socket (for init; requires -o and -z)"
1417 " -q: disable vibrate\n"
1418 " -B: send broadcast when finished (requires -o)\n"
1419 " -P: send broadcast when started and update system properties on "
1420 "progress (requires -o and -B)\n"
1421 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1422 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001423 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001424 exit(exitCode);
1425}
1426
1427static void ExitOnInvalidArgs() {
1428 fprintf(stderr, "invalid combination of args\n");
1429 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001430}
1431
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001432static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001433 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001434}
1435
Wei Liuf87959e2016-08-26 14:51:42 -07001436static void register_sig_handler() {
1437 struct sigaction sa;
1438 sigemptyset(&sa.sa_mask);
1439 sa.sa_flags = 0;
1440 sa.sa_handler = sig_handler;
1441 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1442 sigaction(SIGSEGV, &sa, NULL); // segment fault
1443 sigaction(SIGINT, &sa, NULL); // ctrl-c
1444 sigaction(SIGTERM, &sa, NULL); // killed
1445 sigaction(SIGQUIT, &sa, NULL); // quit
1446}
1447
Felipe Leme1d486fe2016-10-14 18:06:47 -07001448bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001449 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001450 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001451 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001452 // Final timestamp
1453 char date[80];
1454 time_t the_real_now_please_stand_up = time(nullptr);
1455 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001456 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001457 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001458
Felipe Leme9a523ae2016-10-20 15:10:33 -07001459 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001460 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001461 return false;
1462 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001463 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001464 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001465 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001466 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001467
Felipe Leme0f3fb202016-06-10 17:10:53 -07001468 // Add log file (which contains stderr output) to zip...
1469 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001470 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001471 MYLOGE("Failed to add dumpstate log to .zip file\n");
1472 return false;
1473 }
1474 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001475 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001476 fprintf(stderr, "\n");
1477
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001478 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001479 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001480 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001481 return false;
1482 }
1483
Felipe Leme1d486fe2016-10-14 18:06:47 -07001484 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1485 ds.zip_file.reset(nullptr);
1486
Felipe Lemee9d2c542016-11-15 11:48:26 -08001487 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1488 if (remove(tmp_path_.c_str()) != 0) {
1489 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001490 }
1491
Felipe Leme1e9edc62015-12-21 16:02:13 -08001492 return true;
1493}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001494
Chih-Hung Hsiehcb057c22017-08-03 15:48:25 -07001495static std::string SHA256_file_hash(const std::string& filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001496 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1497 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001498 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001499 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001500 return NULL;
1501 }
1502
1503 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001504 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001505
1506 std::vector<uint8_t> buffer(65536);
1507 while (1) {
1508 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1509 if (bytes_read == 0) {
1510 break;
1511 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001512 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001513 return NULL;
1514 }
1515
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001516 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001517 }
1518
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001519 uint8_t hash[SHA256_DIGEST_LENGTH];
1520 SHA256_Final(hash, &ctx);
1521
1522 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1523 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001524 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001525 }
1526 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1527 return std::string(hash_buffer);
1528}
1529
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001530static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1531 // clang-format off
1532 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1533 "--receiver-foreground", "--receiver-include-background", "-a", action};
1534 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001535
1536 am.insert(am.end(), args.begin(), args.end());
1537
Felipe Leme8d2410e2017-02-08 09:46:08 -08001538 RunCommand("", am,
1539 CommandOptions::WithTimeout(20)
1540 .Log("Sending broadcast: '%s'\n")
1541 .Always()
1542 .DropRoot()
1543 .RedirectStderr()
1544 .Build());
1545}
1546
Felipe Leme35b8cf12017-02-10 15:47:29 -08001547static void Vibrate(int duration_ms) {
1548 // clang-format off
1549 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1550 CommandOptions::WithTimeout(10)
1551 .Log("Vibrate: '%s'\n")
1552 .Always()
1553 .Build());
1554 // clang-format on
1555}
1556
Colin Crossf45fa6b2012-03-26 12:38:26 -07001557int main(int argc, char *argv[]) {
1558 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001559 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001560 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001561 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001562 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001563 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001564 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001565 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001566 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001567 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001568 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001569 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001570
Colin Crossf45fa6b2012-03-26 12:38:26 -07001571 /* set as high priority, and protect from OOM killer */
1572 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001573
Felipe Lemed071c682016-10-20 16:48:00 -07001574 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001575 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001576 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001577 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001578 } else {
1579 /* fallback to kernels <= 2.6.35 */
1580 oom_adj = fopen("/proc/self/oom_adj", "we");
1581 if (oom_adj) {
1582 fputs("-17", oom_adj);
1583 fclose(oom_adj);
1584 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001585 }
1586
Jeff Brown1dc94e32014-09-11 14:15:27 -07001587 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001588 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001589 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001590 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001591 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001592 case 'd': do_add_date = 1; break;
1593 case 'z': do_zip_file = 1; break;
1594 case 'o': use_outfile = optarg; break;
1595 case 's': use_socket = 1; break;
1596 case 'S': use_control_socket = 1; break;
1597 case 'v': show_header_only = true; break;
1598 case 'q': do_vibrate = 0; break;
1599 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001600 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001601 case 'R': is_remote_mode = 1; break;
1602 case 'B': do_broadcast = 1; break;
1603 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001604 case 'h':
1605 ShowUsageAndExit(0);
1606 break;
1607 default:
1608 fprintf(stderr, "Invalid option: %c\n", c);
1609 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001610 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001611 }
1612 }
1613
Felipe Lemed071c682016-10-20 16:48:00 -07001614 // TODO: use helper function to convert argv into a string
1615 for (int i = 0; i < argc; i++) {
1616 ds.args_ += argv[i];
1617 if (i < argc - 1) {
1618 ds.args_ += " ";
1619 }
1620 }
1621
1622 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001623 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001624 // Framework uses a system property to override some command-line args.
1625 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001626 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001627 // Currently, the dumpstate binder is only used by Shell to update progress.
1628 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001629 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001630 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001631 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001632 do_vibrate = 0;
1633 is_remote_mode = 1;
1634 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001635 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001636 ds.update_progress_ = true;
Alain Vongsouvanh46edde32017-10-25 16:16:24 -07001637 do_zip_file = 1;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001638 } else if (ds.extra_options_ == "bugreporttelephony") {
1639 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001640 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001641 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001642 }
1643 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001644 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001645 }
1646
Naveen Kallab53a1c92017-03-16 18:17:25 -07001647 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1648 if (!ds.notification_title.empty()) {
1649 // Reset the property
1650 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1651
1652 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1653 if (!ds.notification_description.empty()) {
1654 // Reset the property
1655 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1656 }
1657 MYLOGD("notification (title: %s, description: %s)\n",
1658 ds.notification_title.c_str(), ds.notification_description.c_str());
1659 }
1660
Felipe Leme9a523ae2016-10-20 15:10:33 -07001661 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001662 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001663 }
1664
Felipe Leme2628e9e2016-04-12 16:36:51 -07001665 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001666 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001667 }
1668
Felipe Leme9a523ae2016-10-20 15:10:33 -07001669 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001670 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001671 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001672
Felipe Leme9a523ae2016-10-20 15:10:33 -07001673 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001674 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001675 }
1676
Felipe Lemed071c682016-10-20 16:48:00 -07001677 if (ds.version_ == VERSION_DEFAULT) {
1678 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001679 }
1680
Vishnu Nair780b1282017-10-10 13:57:24 -07001681 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR &&
1682 ds.version_ != VERSION_PRIORITY_DUMPS) {
1683 MYLOGE(
1684 "invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s', '%s')\n",
1685 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1686 VERSION_SPLIT_ANR.c_str(), VERSION_PRIORITY_DUMPS.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001687 exit(1);
1688 }
1689
1690 if (show_header_only) {
1691 ds.PrintHeader();
1692 exit(0);
1693 }
1694
Felipe Leme7447d7c2016-11-03 18:12:22 -07001695 /* redirect output if needed */
1696 bool is_redirecting = !use_socket && use_outfile;
1697
1698 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1699 std::string stats_path =
1700 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1701 : "";
1702 ds.progress_.reset(new Progress(stats_path));
1703
Felipe Lemed071c682016-10-20 16:48:00 -07001704 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001705 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001706 ds.id_ = ++last_id;
1707 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1708
1709 MYLOGI("begin\n");
1710
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001711 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001712
Felipe Leme75876a22016-10-27 16:31:27 -07001713 if (do_start_service) {
1714 MYLOGI("Starting 'dumpstate' service\n");
1715 android::status_t ret;
1716 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1717 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1718 }
1719 }
1720
Felipe Lemef0292972016-11-22 13:57:05 -08001721 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001722 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1723 }
1724
Felipe Leme7447d7c2016-11-03 18:12:22 -07001725 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001726 ds.extra_options_.c_str());
1727
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001728 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001729
Felipe Leme9a523ae2016-10-20 15:10:33 -07001730 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001731
Christopher Ferrised9354f2014-10-01 17:35:01 -07001732 // If we are going to use a socket, do it as early as possible
1733 // to avoid timeouts from bugreport.
1734 if (use_socket) {
1735 redirect_to_socket(stdout, "dumpstate");
1736 }
1737
Felipe Leme2628e9e2016-04-12 16:36:51 -07001738 if (use_control_socket) {
1739 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001740 ds.control_socket_fd_ = open_socket("dumpstate");
1741 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001742 }
1743
Felipe Leme71bbfc52015-11-23 14:14:51 -08001744 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001745 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001746 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001747 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001748 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1749 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001750 if (do_add_date) {
1751 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001752 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001753 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001754 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001755 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001756 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001757
1758 if (telephony_only) {
1759 ds.base_name_ += "-telephony";
1760 }
1761
Felipe Leme71bbfc52015-11-23 14:14:51 -08001762 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001763 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001764 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001765 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001766 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001767
Felipe Lemee844a9d2016-09-21 15:01:39 -07001768 MYLOGD(
1769 "Bugreport dir: %s\n"
1770 "Base name: %s\n"
1771 "Suffix: %s\n"
1772 "Log path: %s\n"
1773 "Temporary path: %s\n"
1774 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001775 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1776 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001777
Felipe Leme1e9edc62015-12-21 16:02:13 -08001778 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001779 ds.path_ = ds.GetPath(".zip");
1780 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1781 create_parent_dirs(ds.path_.c_str());
1782 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001783 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001784 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001785 do_zip_file = 0;
1786 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001787 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001788 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001789 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001790 }
1791
Felipe Leme9a523ae2016-10-20 15:10:33 -07001792 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001793 if (do_broadcast) {
1794 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001795
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001796 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001797 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001798 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001799 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001800 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001801 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001802 };
1803 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001804 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001805 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001806 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001807 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001808 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001809 }
1810 }
1811
Nick Kralevichf3599b32016-01-25 15:05:16 -08001812 /* read /proc/cmdline before dropping root */
1813 FILE *cmdline = fopen("/proc/cmdline", "re");
1814 if (cmdline) {
1815 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1816 fclose(cmdline);
1817 }
1818
John Michelau1f794c42012-09-17 11:20:19 -05001819 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001820 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001821 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001822
Felipe Leme9a523ae2016-10-20 15:10:33 -07001823 if (do_fb && ds.do_early_screenshot_) {
1824 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001825 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001826 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001827 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001828 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001829 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001830 }
1831 }
1832
Felipe Leme1e9edc62015-12-21 16:02:13 -08001833 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001834 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1835 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001836 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001837 }
1838 }
1839
Felipe Leme71bbfc52015-11-23 14:14:51 -08001840 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001841 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1842 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1843 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1844 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001845 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001846 /* TODO: rather than generating a text file now and zipping it later,
1847 it would be more efficient to redirect stdout to the zip entry
1848 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001849 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1850 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001851 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001852 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001853 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001854 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001855
1856 // Don't buffer stdout
1857 setvbuf(stdout, nullptr, _IONBF, 0);
1858
Felipe Leme608385d2016-02-01 10:35:38 -08001859 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1860 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001861 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001862 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001863
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001864 if (telephony_only) {
Jayachandran Ca94c7172017-06-10 15:08:12 -07001865 DumpstateTelephonyOnly();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001866 ds.DumpstateBoard();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001867 } else {
1868 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1869 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1870 // the raw trace.
1871 if (!dump_anrd_trace()) {
1872 dump_systrace();
1873 }
1874
1875 // Invoking the following dumpsys calls before dump_traces() to try and
1876 // keep the system stats as close to its initial state as possible.
Vishnu Nair780b1282017-10-10 13:57:24 -07001877 RunDumpsysCritical();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001878
1879 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1880 dump_raft();
1881
1882 /* collect stack traces from Dalvik and native processes (needs root) */
1883 dump_traces_path = dump_traces();
1884
1885 /* Run some operations that require root. */
Narayan Kamathbd863722017-06-01 18:50:12 +01001886 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1887 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()));
Narayan Kamath8f788292017-05-25 13:20:39 +01001888
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001889 ds.AddDir(RECOVERY_DIR, true);
1890 ds.AddDir(RECOVERY_DATA_DIR, true);
1891 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1892 if (!PropertiesHelper::IsUserBuild()) {
1893 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1894 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1895 }
1896 add_mountinfo();
Jayachandran Ca94c7172017-06-10 15:08:12 -07001897 DumpIpTablesAsRoot();
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001898
1899 // Capture any IPSec policies in play. No keys are exposed here.
1900 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1901 CommandOptions::WithTimeout(10).Build());
1902
1903 // Run ss as root so we can see socket marks.
1904 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1905 CommandOptions::WithTimeout(10).Build());
1906
Jin Qian3cd671e2017-09-27 18:50:04 -07001907 // Run iotop as root to show top 100 IO threads
1908 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
1909
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001910 if (!DropRootUser()) {
1911 return -1;
1912 }
1913
1914 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001915 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001916
Felipe Leme55b42a62015-11-10 17:39:08 -08001917 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001918 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001919 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001920 }
1921
Felipe Leme6e01fa62015-11-11 19:35:14 -08001922 /* rename or zip the (now complete) .tmp file to its final location */
1923 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001924
1925 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001926 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001927 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001928 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001929 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001930 /* must whitelist which characters are allowed, otherwise it could cross directories */
1931 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001932 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001933 change_suffix = true;
1934 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001935 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001936 }
1937 }
1938 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001939 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1940 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001941 if (!ds.screenshot_path_.empty()) {
1942 std::string new_screenshot_path = ds.GetPath(".png");
1943 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1944 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1945 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001946 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001947 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001948 }
1949 }
1950 }
1951
Felipe Leme6e01fa62015-11-11 19:35:14 -08001952 bool do_text_file = true;
1953 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001954 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001955 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001956 do_text_file = true;
1957 } else {
1958 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001959 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001960 std::string new_path = ds.GetPath(".zip");
1961 if (ds.path_ != new_path) {
1962 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1963 if (rename(ds.path_.c_str(), new_path.c_str())) {
1964 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001965 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001966 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001967 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001968 }
1969 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001970 }
1971 }
1972 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001973 ds.path_ = ds.GetPath(".txt");
1974 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1975 ds.tmp_path_.c_str());
1976 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1977 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001978 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001979 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001980 }
1981 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001982 if (use_control_socket) {
1983 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001984 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001985 "FAIL:could not create zip file, check %s "
1986 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001987 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001988 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001989 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001990 }
1991 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001992 }
1993
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001994 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001995 for (int i = 0; i < 3; i++) {
1996 Vibrate(75);
1997 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001998 }
1999
Jeff Brown1dc94e32014-09-11 14:15:27 -07002000 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08002001 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07002002 if (!ds.path_.empty()) {
2003 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002004 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08002005
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002006 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002007 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07002008 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07002009 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07002010 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07002011 "--es", "android.intent.extra.BUGREPORT", ds.path_,
2012 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002013 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07002014 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002015 if (do_fb) {
2016 am_args.push_back("--es");
2017 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002018 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08002019 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07002020 if (!ds.notification_title.empty()) {
2021 am_args.push_back("--es");
2022 am_args.push_back("android.intent.extra.TITLE");
2023 am_args.push_back(ds.notification_title);
2024 if (!ds.notification_description.empty()) {
2025 am_args.push_back("--es");
2026 am_args.push_back("android.intent.extra.DESCRIPTION");
2027 am_args.push_back(ds.notification_description);
2028 }
2029 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00002030 if (is_remote_mode) {
2031 am_args.push_back("--es");
2032 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002033 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002034 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
2035 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002036 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08002037 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00002038 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08002039 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08002040 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08002041 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07002042 }
2043
Felipe Leme7447d7c2016-11-03 18:12:22 -07002044 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
2045 ds.progress_->GetInitialMax());
2046 ds.progress_->Save();
2047 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07002048
Felipe Leme107a05f2016-03-08 15:11:15 -08002049 if (is_redirecting) {
2050 fclose(stderr);
2051 }
2052
Felipe Leme9a523ae2016-10-20 15:10:33 -07002053 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07002054 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07002055 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07002056 }
2057
Narayan Kamath6b9516c2017-10-27 11:15:51 +01002058 CloseDumpFds(tombstone_data.get());
2059 CloseDumpFds(anr_data.get());
2060
Colin Crossf45fa6b2012-03-26 12:38:26 -07002061 return 0;
2062}