blob: f16a96e9640214b1e2131d77e05528c3ae595483 [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"
Todd Poynor2a83daa2013-11-22 15:44:22 -080075
Wei Liu341938b2016-04-27 16:18:17 -070076#define RAFT_DIR "/data/misc/raft"
Felipe Lemee82a27d2016-01-05 13:35:44 -080077#define RECOVERY_DIR "/cache/recovery"
Mark Salyzynd6ab0112016-03-25 12:56:39 -070078#define RECOVERY_DATA_DIR "/data/misc/recovery"
Mark Salyzyn4d42dea2016-04-01 10:03:14 -070079#define LOGPERSIST_DATA_DIR "/data/misc/logd"
David Brazdild2991962016-06-03 14:40:44 +010080#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur"
81#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref"
Erik Kline08165202016-05-30 11:55:44 +090082#define WLUTIL "/vendor/xbin/wlutil"
Christopher Ferris7dc7f322014-07-22 16:08:19 -070083
Narayan Kamath8f788292017-05-25 13:20:39 +010084// TODO(narayan): Since this information has to be kept in sync
85// with tombstoned, we should just put it in a common header.
86//
87// File: system/core/debuggerd/tombstoned/tombstoned.cpp
88static const std::string TOMBSTONE_DIR = "/data/tombstones";
89static const std::string TOMBSTONE_FILE_PREFIX = "/data/tombstones/tombstone_";
90static const std::string ANR_DIR = "/data/anr";
91static const std::string ANR_FILE_PREFIX = "/data/anr/anr_";
Christopher Ferris7dc7f322014-07-22 16:08:19 -070092
Narayan Kamath8f788292017-05-25 13:20:39 +010093struct DumpData {
94 std::string name;
95 int fd;
96 time_t mtime;
97};
98
99static bool operator<(const DumpData& d1, const DumpData& d2) {
100 return d1.mtime < d2.mtime;
101}
102
103static std::unique_ptr<std::vector<DumpData>> tombstone_data;
104static std::unique_ptr<std::vector<DumpData>> anr_data;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700105
Felipe Lemee844a9d2016-09-21 15:01:39 -0700106// TODO: temporary variables and functions used during C++ refactoring
107static Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme678727a2016-09-21 17:22:11 -0700108static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
109 const CommandOptions& options = CommandOptions::DEFAULT) {
110 return ds.RunCommand(title, fullCommand, options);
111}
112static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
Felipe Lemebda15a02016-11-16 17:48:25 -0800113 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS,
Felipe Leme678727a2016-09-21 17:22:11 -0700114 long dumpsysTimeout = 0) {
115 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
116}
117static int DumpFile(const std::string& title, const std::string& path) {
118 return ds.DumpFile(title, path);
119}
Felipe Lemee82a27d2016-01-05 13:35:44 -0800120
Felipe Lemee844a9d2016-09-21 15:01:39 -0700121// Relative directory (inside the zip) for all files copied as-is into the bugreport.
122static const std::string ZIP_ROOT_DIR = "FS";
123
Steven Moreland7440ddb2016-12-15 16:13:39 -0800124// Must be hardcoded because dumpstate HAL implementation need SELinux access to it
125static const std::string kDumpstateBoardPath = "/bugreports/dumpstate_board.txt";
Andreas Huber69ec3ac2017-03-23 09:47:51 -0700126static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt";
Steven Moreland7440ddb2016-12-15 16:13:39 -0800127
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700128static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options";
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700129static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id";
Felipe Lemed071c682016-10-20 16:48:00 -0700130static constexpr char PROPERTY_VERSION[] = "dumpstate.version";
Naveen Kallab53a1c92017-03-16 18:17:25 -0700131static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title";
132static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description";
Felipe Leme9ce6aa42016-09-21 10:02:25 -0700133
Felipe Lemef0292972016-11-22 13:57:05 -0800134static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build();
135
Narayan Kamath8f788292017-05-25 13:20:39 +0100136/*
137 * Returns a vector of dump fds under |file_prefix|. The returned vector
138 * is sorted by the mtimes of the dumps. If |limit_by_mtime| is set, the
139 * vector only contains files that were written in the last 30 minutes.
140 */
141static std::vector<DumpData>* GetDumpFds(const std::string& file_prefix, bool limit_by_mtime) {
142 const time_t thirty_minutes_ago = ds.now_ - 60 * 30;
143
144 size_t i = 0;
145 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>());
146 while (true) {
147 const std::string name = android::base::StringPrintf("%s%02zu", file_prefix.c_str(), i++);
148 android::base::unique_fd fd(
149 TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)));
150 if (fd == -1) {
151 if (errno != ENOENT) {
152 MYLOGW("Unable to open dump file: %s %s\n", name.c_str(), strerror(errno));
153 }
154
155 break;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700156 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100157
158 struct stat st;
159 if (fstat(fd, &st) == -1) {
160 MYLOGW("Unable to stat dump file: %s %s\n", name.c_str(), strerror(errno));
161 continue;
162 }
163
164 if (!S_ISREG(st.st_mode)) {
165 MYLOGW("Unexpected mode for dump file: %s %x\n", name.c_str(), st.st_mode);
166 continue;
167 }
168
169 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) {
170 MYLOGI("Excluding stale dump file: %s\n", name.c_str());
171 continue;
172 }
173
174 DumpData data = {.name = name, .fd = fd.release(), .mtime = st.st_mtime};
175
176 dump_data->push_back(data);
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700177 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100178
179 std::sort(dump_data->begin(), dump_data->end());
180
181 return dump_data.release();
182}
183
184static bool AddDumps(const std::vector<DumpData>& dump_list, const char* type_name,
185 const bool add_to_zip) {
186 bool dumped = false;
187 for (size_t i = 0; i < dump_list.size(); i++) {
188 const std::string& name = dump_list[i].name;
189 const int fd = dump_list[i].fd;
190 dumped = true;
191 if (ds.IsZipping() && add_to_zip) {
192 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) {
193 MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name);
194 }
195 } else {
196 dump_file_from_fd(type_name, name.c_str(), fd);
197 }
198
199 close(fd);
200 }
201
202 return dumped;
Christopher Ferris7dc7f322014-07-22 16:08:19 -0700203}
204
Felipe Leme635ca312016-01-05 14:23:02 -0800205// for_each_pid() callback to get mount info about a process.
Felipe Leme4c2d6632016-09-28 14:32:00 -0700206void do_mountinfo(int pid, const char* name __attribute__((unused))) {
Felipe Leme635ca312016-01-05 14:23:02 -0800207 char path[PATH_MAX];
208
209 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
210 // are added.
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700211 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid);
Felipe Leme635ca312016-01-05 14:23:02 -0800212 char linkname[PATH_MAX];
213 ssize_t r = readlink(path, linkname, PATH_MAX);
214 if (r == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800215 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
Felipe Leme635ca312016-01-05 14:23:02 -0800216 return;
217 }
218 linkname[r] = '\0';
219
220 if (mount_points.find(linkname) == mount_points.end()) {
221 // First time this mount point was found: add it
Nick Kralevichf0922cc2016-05-14 16:47:44 -0700222 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700223 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) {
Felipe Leme635ca312016-01-05 14:23:02 -0800224 mount_points.insert(linkname);
225 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800226 MYLOGE("Unable to add mountinfo %s to zip file\n", path);
Felipe Leme635ca312016-01-05 14:23:02 -0800227 }
228 }
229}
230
231void add_mountinfo() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700232 if (!ds.IsZipping()) return;
Felipe Leme678727a2016-09-21 17:22:11 -0700233 std::string title = "MOUNT INFO";
Felipe Leme635ca312016-01-05 14:23:02 -0800234 mount_points.clear();
Felipe Leme46b85da2016-11-21 17:40:45 -0800235 DurationReporter duration_reporter(title, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700236 for_each_pid(do_mountinfo, nullptr);
237 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
Felipe Leme635ca312016-01-05 14:23:02 -0800238}
239
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700240static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
241{
242 DIR *d;
243 struct dirent *de;
244 char path[PATH_MAX];
245
246 d = opendir(driverpath);
247 if (d == NULL) {
248 return;
249 }
250
251 while ((de = readdir(d))) {
252 if (de->d_type != DT_LNK) {
253 continue;
254 }
255 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700256 DumpFile(title, path);
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -0700257 }
258
259 closedir(d);
260}
261
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700262
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700263
264// dump anrd's trace and add to the zip file.
265// 1. check if anrd is running on this device.
266// 2. send a SIGUSR1 to its pid which will dump anrd's trace.
267// 3. wait until the trace generation completes and add to the zip file.
268static bool dump_anrd_trace() {
269 unsigned int pid;
270 char buf[50], path[PATH_MAX];
271 struct dirent *trace;
272 struct stat st;
273 DIR *trace_dir;
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700274 int retry = 5;
275 long max_ctime = 0, old_mtime;
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700276 long long cur_size = 0;
277 const char *trace_path = "/data/misc/anrd/";
278
Felipe Leme1d486fe2016-10-14 18:06:47 -0700279 if (!ds.IsZipping()) {
280 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700281 return false;
282 }
283
284 // find anrd's pid if it is running.
Ecco Park61ffcf72016-10-27 15:46:26 -0700285 pid = GetPidByName("/system/xbin/anrd");
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700286
287 if (pid > 0) {
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700288 if (stat(trace_path, &st) == 0) {
289 old_mtime = st.st_mtime;
290 } else {
291 MYLOGE("Failed to find: %s\n", trace_path);
292 return false;
293 }
294
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700295 // send SIGUSR1 to the anrd to generate a trace.
296 sprintf(buf, "%u", pid);
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700297 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700298 CommandOptions::WithTimeout(1).Build())) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700299 MYLOGE("anrd signal timed out. Please manually collect trace\n");
300 return false;
301 }
302
Zhengyin Qianafc38fe2016-09-08 16:50:09 -0700303 while (retry-- > 0 && old_mtime == st.st_mtime) {
304 sleep(1);
305 stat(trace_path, &st);
306 }
307
308 if (retry < 0 && old_mtime == st.st_mtime) {
309 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path);
310 return false;
311 }
312
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700313 // identify the trace file by its creation time.
314 if (!(trace_dir = opendir(trace_path))) {
315 MYLOGE("Can't open trace file under %s\n", trace_path);
316 }
317 while ((trace = readdir(trace_dir))) {
318 if (strcmp(trace->d_name, ".") == 0
319 || strcmp(trace->d_name, "..") == 0) {
320 continue;
321 }
322 sprintf(path, "%s%s", trace_path, trace->d_name);
323 if (stat(path, &st) == 0) {
324 if (st.st_ctime > max_ctime) {
325 max_ctime = st.st_ctime;
326 sprintf(buf, "%s", trace->d_name);
327 }
328 }
329 }
330 closedir(trace_dir);
331
332 // Wait until the dump completes by checking the size of the trace.
333 if (max_ctime > 0) {
334 sprintf(path, "%s%s", trace_path, buf);
335 while(true) {
336 sleep(1);
337 if (stat(path, &st) == 0) {
338 if (st.st_size == cur_size) {
339 break;
340 } else if (st.st_size > cur_size) {
341 cur_size = st.st_size;
342 } else {
343 return false;
344 }
345 } else {
346 MYLOGE("Cant stat() %s anymore\n", path);
347 return false;
348 }
349 }
350 // Add to the zip file.
Felipe Leme1d486fe2016-10-14 18:06:47 -0700351 if (!ds.AddZipEntry("anrd_trace.txt", path)) {
Zhengyin Qian068ecc72016-08-10 16:48:14 -0700352 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path);
353 } else {
354 if (remove(path)) {
355 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno));
356 }
357 return true;
358 }
359 } else {
360 MYLOGE("Can't stats any trace file under %s\n", trace_path);
361 }
362 }
363 return false;
364}
365
Felipe Lemeefd7e272016-05-18 09:27:16 -0700366static void dump_systrace() {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700367 if (!ds.IsZipping()) {
368 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n");
Felipe Leme71a74ac2016-03-17 15:43:25 -0700369 return;
370 }
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700371 std::string systrace_path = ds.GetPath("-systrace.txt");
Felipe Leme14e034a2016-03-30 18:51:03 -0700372 if (systrace_path.empty()) {
373 MYLOGE("Not dumping systrace because path is empty\n");
374 return;
375 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700376 const char* path = "/sys/kernel/debug/tracing/tracing_on";
377 long int is_tracing;
378 if (read_file_as_long(path, &is_tracing)) {
379 return; // error already logged
380 }
381 if (is_tracing <= 0) {
382 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
383 return;
384 }
385
Felipe Leme14e034a2016-03-30 18:51:03 -0700386 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
387 systrace_path.c_str());
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700388 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path},
Felipe Leme30dbfa12016-09-02 12:43:26 -0700389 CommandOptions::WithTimeout(120).Build())) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700390 MYLOGE("systrace timed out, its zip entry will be incomplete\n");
Felipe Lemec7fe8fe2016-09-21 18:13:20 -0700391 // TODO: RunCommand tries to kill the process, but atrace doesn't die
Felipe Leme30dbfa12016-09-02 12:43:26 -0700392 // peacefully; ideally, we should call strace to stop itself, but there is no such option
393 // yet (just a --async_stop, which stops and dump
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700394 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) {
Felipe Leme30dbfa12016-09-02 12:43:26 -0700395 // MYLOGE("could not stop systrace ");
396 // }
Felipe Leme14e034a2016-03-30 18:51:03 -0700397 }
Felipe Leme1d486fe2016-10-14 18:06:47 -0700398 if (!ds.AddZipEntry("systrace.txt", systrace_path)) {
Felipe Leme14e034a2016-03-30 18:51:03 -0700399 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
Felipe Leme71a74ac2016-03-17 15:43:25 -0700400 } else {
Felipe Leme14e034a2016-03-30 18:51:03 -0700401 if (remove(systrace_path.c_str())) {
402 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
403 }
Felipe Leme71a74ac2016-03-17 15:43:25 -0700404 }
405}
406
Felipe Lemeefd7e272016-05-18 09:27:16 -0700407static void dump_raft() {
Felipe Lemef0292972016-11-22 13:57:05 -0800408 if (PropertiesHelper::IsUserBuild()) {
Wei Liu341938b2016-04-27 16:18:17 -0700409 return;
410 }
411
Felipe Leme1d486fe2016-10-14 18:06:47 -0700412 std::string raft_path = ds.GetPath("-raft_log.txt");
413 if (raft_path.empty()) {
414 MYLOGD("raft_path is empty\n");
Wei Liu341938b2016-04-27 16:18:17 -0700415 return;
416 }
Wei Liuf0e78d42016-05-25 14:21:02 -0700417
418 struct stat s;
419 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) {
420 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR);
421 return;
422 }
423
Felipe Leme30dbfa12016-09-02 12:43:26 -0700424 CommandOptions options = CommandOptions::WithTimeout(600).Build();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700425 if (!ds.IsZipping()) {
426 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport.
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700427 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options);
Wei Liu341938b2016-04-27 16:18:17 -0700428 return;
429 }
430
Felipe Leme1d486fe2016-10-14 18:06:47 -0700431 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options);
432 if (!ds.AddZipEntry("raft_log.txt", raft_path)) {
433 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str());
Wei Liu341938b2016-04-27 16:18:17 -0700434 } else {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700435 if (remove(raft_path.c_str())) {
436 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno));
Wei Liu341938b2016-04-27 16:18:17 -0700437 }
438 }
439}
440
Naveen Kalla058e1e82016-10-19 21:38:44 -0700441/**
442 * Finds the last modified file in the directory dir whose name starts with file_prefix.
443 *
444 * Function returns empty string when it does not find a file
445 */
446static std::string GetLastModifiedFileWithPrefix(const std::string& dir,
447 const std::string& file_prefix) {
448 std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir);
449 if (d == nullptr) {
450 MYLOGD("Error %d opening %s\n", errno, dir.c_str());
451 return "";
452 }
453
454 // Find the newest file matching the file_prefix in dir
455 struct dirent *de;
456 time_t last_modified_time = 0;
457 std::string last_modified_file = "";
458 struct stat s;
459
460 while ((de = readdir(d.get()))) {
461 std::string file = std::string(de->d_name);
462 if (!file_prefix.empty()) {
463 if (!android::base::StartsWith(file, file_prefix.c_str())) continue;
464 }
465 file = dir + "/" + file;
466 int ret = stat(file.c_str(), &s);
467
468 if ((ret == 0) && (s.st_mtime > last_modified_time)) {
469 last_modified_file = file;
470 last_modified_time = s.st_mtime;
471 }
472 }
473
474 return last_modified_file;
475}
476
477static void DumpModemLogs() {
478 DurationReporter durationReporter("DUMP MODEM LOGS");
Felipe Lemef0292972016-11-22 13:57:05 -0800479 if (PropertiesHelper::IsUserBuild()) {
Naveen Kalla058e1e82016-10-19 21:38:44 -0700480 return;
481 }
482
483 if (!ds.IsZipping()) {
484 MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n");
485 return;
486 }
487
488 std::string file_prefix = android::base::GetProperty("ro.radio.log_prefix", "");
489
490 if(file_prefix.empty()) {
491 MYLOGD("No modem log : file_prefix is empty\n");
492 return;
493 }
494
Ecco Park6ca7d082017-01-27 15:07:35 -0800495 // TODO: b/33820081 we need to provide a right way to dump modem logs.
496 std::string radio_bugreport_dir = android::base::GetProperty("ro.radio.log_loc", "");
497 if (radio_bugreport_dir.empty()) {
498 radio_bugreport_dir = dirname(ds.GetPath("").c_str());
499 }
Naveen Kalla058e1e82016-10-19 21:38:44 -0700500
Ecco Park6ca7d082017-01-27 15:07:35 -0800501 MYLOGD("DumpModemLogs: directory is %s and file_prefix is %s\n",
502 radio_bugreport_dir.c_str(), file_prefix.c_str());
503
504 std::string modem_log_file = GetLastModifiedFileWithPrefix(radio_bugreport_dir, file_prefix);
Naveen Kalla058e1e82016-10-19 21:38:44 -0700505
506 struct stat s;
507 if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) {
508 MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str());
509 return;
510 }
511
512 std::string filename = basename(modem_log_file.c_str());
513 if (!ds.AddZipEntry(filename, modem_log_file)) {
514 MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str());
515 } else {
516 MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str());
Naveen Kallab77df782016-11-18 17:32:23 -0800517 if (remove(modem_log_file.c_str())) {
518 MYLOGE("Error removing modem log %s\n", modem_log_file.c_str());
519 }
Naveen Kalla058e1e82016-10-19 21:38:44 -0700520 }
521}
522
Mark Salyzyn326842f2015-04-30 09:49:41 -0700523static bool skip_not_stat(const char *path) {
524 static const char stat[] = "/stat";
525 size_t len = strlen(path);
526 if (path[len - 1] == '/') { /* Directory? */
527 return false;
528 }
529 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
530}
531
Felipe Leme4c2d6632016-09-28 14:32:00 -0700532static bool skip_none(const char* path __attribute__((unused))) {
Felipe Lemee82a27d2016-01-05 13:35:44 -0800533 return false;
534}
535
Mark Salyzyn326842f2015-04-30 09:49:41 -0700536static const char mmcblk0[] = "/sys/block/mmcblk0/";
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700537unsigned long worst_write_perf = 20000; /* in KB/s */
Mark Salyzyn326842f2015-04-30 09:49:41 -0700538
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800539//
540// stat offsets
541// Name units description
542// ---- ----- -----------
543// read I/Os requests number of read I/Os processed
544#define __STAT_READ_IOS 0
545// read merges requests number of read I/Os merged with in-queue I/O
546#define __STAT_READ_MERGES 1
547// read sectors sectors number of sectors read
548#define __STAT_READ_SECTORS 2
549// read ticks milliseconds total wait time for read requests
550#define __STAT_READ_TICKS 3
551// write I/Os requests number of write I/Os processed
552#define __STAT_WRITE_IOS 4
553// write merges requests number of write I/Os merged with in-queue I/O
554#define __STAT_WRITE_MERGES 5
555// write sectors sectors number of sectors written
556#define __STAT_WRITE_SECTORS 6
557// write ticks milliseconds total wait time for write requests
558#define __STAT_WRITE_TICKS 7
559// in_flight requests number of I/Os currently in flight
560#define __STAT_IN_FLIGHT 8
561// io_ticks milliseconds total time this block device has been active
562#define __STAT_IO_TICKS 9
563// time_in_queue milliseconds total wait time for all requests
564#define __STAT_IN_QUEUE 10
565#define __STAT_NUMBER_FIELD 11
566//
567// read I/Os, write I/Os
568// =====================
569//
570// These values increment when an I/O request completes.
571//
572// read merges, write merges
573// =========================
574//
575// These values increment when an I/O request is merged with an
576// already-queued I/O request.
577//
578// read sectors, write sectors
579// ===========================
580//
581// These values count the number of sectors read from or written to this
582// block device. The "sectors" in question are the standard UNIX 512-byte
583// sectors, not any device- or filesystem-specific block size. The
584// counters are incremented when the I/O completes.
585#define SECTOR_SIZE 512
586//
587// read ticks, write ticks
588// =======================
589//
590// These values count the number of milliseconds that I/O requests have
591// waited on this block device. If there are multiple I/O requests waiting,
592// these values will increase at a rate greater than 1000/second; for
593// example, if 60 read requests wait for an average of 30 ms, the read_ticks
594// field will increase by 60*30 = 1800.
595//
596// in_flight
597// =========
598//
599// This value counts the number of I/O requests that have been issued to
600// the device driver but have not yet completed. It does not include I/O
601// requests that are in the queue but not yet issued to the device driver.
602//
603// io_ticks
604// ========
605//
606// This value counts the number of milliseconds during which the device has
607// had I/O requests queued.
608//
609// time_in_queue
610// =============
611//
612// This value counts the number of milliseconds that I/O requests have waited
613// on this block device. If there are multiple I/O requests waiting, this
614// value will increase as the product of the number of milliseconds times the
615// number of requests waiting (see "read ticks" above for an example).
616#define S_TO_MS 1000
617//
618
Mark Salyzyn326842f2015-04-30 09:49:41 -0700619static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800620 unsigned long long fields[__STAT_NUMBER_FIELD];
Mark Salyzyn326842f2015-04-30 09:49:41 -0700621 bool z;
622 char *cp, *buffer = NULL;
623 size_t i = 0;
624 FILE *fp = fdopen(fd, "rb");
625 getline(&buffer, &i, fp);
626 fclose(fp);
627 if (!buffer) {
628 return -errno;
629 }
630 i = strlen(buffer);
631 while ((i > 0) && (buffer[i - 1] == '\n')) {
632 buffer[--i] = '\0';
633 }
634 if (!*buffer) {
635 free(buffer);
636 return 0;
637 }
638 z = true;
639 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800640 fields[i] = strtoull(cp, &cp, 10);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700641 if (fields[i] != 0) {
642 z = false;
643 }
644 }
645 if (z) { /* never accessed */
646 free(buffer);
647 return 0;
648 }
649
650 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
651 path += sizeof(mmcblk0) - 1;
652 }
653
Felipe Lemed8b94e52016-12-08 10:21:44 -0800654 printf("%s: %s\n", path, buffer);
Mark Salyzyn326842f2015-04-30 09:49:41 -0700655 free(buffer);
656
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800657 if (fields[__STAT_IO_TICKS]) {
658 unsigned long read_perf = 0;
659 unsigned long read_ios = 0;
660 if (fields[__STAT_READ_TICKS]) {
661 unsigned long long divisor = fields[__STAT_READ_TICKS]
662 * fields[__STAT_IO_TICKS];
663 read_perf = ((unsigned long long)SECTOR_SIZE
664 * fields[__STAT_READ_SECTORS]
665 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
666 / divisor;
667 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
668 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
669 / divisor;
670 }
671
672 unsigned long write_perf = 0;
673 unsigned long write_ios = 0;
674 if (fields[__STAT_WRITE_TICKS]) {
675 unsigned long long divisor = fields[__STAT_WRITE_TICKS]
676 * fields[__STAT_IO_TICKS];
677 write_perf = ((unsigned long long)SECTOR_SIZE
678 * fields[__STAT_WRITE_SECTORS]
679 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
680 / divisor;
681 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
682 * fields[__STAT_IN_QUEUE] + (divisor >> 1))
683 / divisor;
684 }
685
686 unsigned queue = (fields[__STAT_IN_QUEUE]
687 + (fields[__STAT_IO_TICKS] >> 1))
688 / fields[__STAT_IO_TICKS];
689
690 if (!write_perf && !write_ios) {
Felipe Lemed8b94e52016-12-08 10:21:44 -0800691 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800692 } else {
Felipe Lemed8b94e52016-12-08 10:21:44 -0800693 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf,
694 read_ios, write_perf, write_ios, queue);
Mark Salyzyn01d6c392016-02-04 09:20:44 -0800695 }
696
697 /* bugreport timeout factor adjustment */
698 if ((write_perf > 1) && (write_perf < worst_write_perf)) {
699 worst_write_perf = write_perf;
700 }
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700701 }
Mark Salyzyn326842f2015-04-30 09:49:41 -0700702 return 0;
703}
704
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700705/* timeout in ms */
Felipe Leme8620bb42015-11-10 11:04:45 -0800706static unsigned long logcat_timeout(const char *name) {
Mark Salyzyn6c3d90f2016-09-27 14:55:27 -0700707 log_id_t id = android_name_to_log_id(name);
708 unsigned long property_size = __android_logger_get_buffer_size(id);
Mark Salyzyn8f37aa52015-06-12 12:28:24 -0700709 /* Engineering margin is ten-fold our guess */
710 return 10 * (property_size + worst_write_perf) / worst_write_perf;
711}
712
Felipe Leme2b9b06c2016-10-14 09:13:06 -0700713void Dumpstate::PrintHeader() const {
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700714 std::string build, fingerprint, radio, bootloader, network;
715 char date[80];
Colin Crossf45fa6b2012-03-26 12:38:26 -0700716
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700717 build = android::base::GetProperty("ro.build.display.id", "(unknown)");
718 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)");
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700719 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
720 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
721 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
Felipe Lemebbaf3c12016-10-11 14:32:25 -0700722 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
Colin Crossf45fa6b2012-03-26 12:38:26 -0700723
Felipe Lemed8b94e52016-12-08 10:21:44 -0800724 printf("========================================================\n");
725 printf("== dumpstate: %s\n", date);
726 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -0700727
Felipe Lemed8b94e52016-12-08 10:21:44 -0800728 printf("\n");
729 printf("Build: %s\n", build.c_str());
Felipe Leme96c2bbb2016-09-26 09:21:21 -0700730 // NOTE: fingerprint entry format is important for other tools.
Felipe Lemed8b94e52016-12-08 10:21:44 -0800731 printf("Build fingerprint: '%s'\n", fingerprint.c_str());
732 printf("Bootloader: %s\n", bootloader.c_str());
733 printf("Radio: %s\n", radio.c_str());
734 printf("Network: %s\n", network.c_str());
Colin Crossf45fa6b2012-03-26 12:38:26 -0700735
Felipe Lemed8b94e52016-12-08 10:21:44 -0800736 printf("Kernel: ");
Felipe Lemef0292972016-11-22 13:57:05 -0800737 DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
Felipe Lemed8b94e52016-12-08 10:21:44 -0800738 printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
739 printf("Bugreport format version: %s\n", version_.c_str());
740 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_,
741 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str());
742 printf("\n");
Felipe Leme78f2c862015-12-21 09:55:22 -0800743}
744
Felipe Leme24b66ee2016-06-16 10:55:26 -0700745// List of file extensions that can cause a zip file attachment to be rejected by some email
746// service providers.
747static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = {
748 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp",
749 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct",
750 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh"
751};
752
Felipe Leme1d486fe2016-10-14 18:06:47 -0700753bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) {
754 if (!IsZipping()) {
755 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n",
756 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800757 return false;
758 }
Felipe Leme24b66ee2016-06-16 10:55:26 -0700759 std::string valid_name = entry_name;
760
761 // Rename extension if necessary.
762 size_t idx = entry_name.rfind(".");
763 if (idx != std::string::npos) {
764 std::string extension = entry_name.substr(idx);
765 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
766 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) {
767 valid_name = entry_name + ".renamed";
768 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str());
769 }
770 }
771
Felipe Leme6fe9db62016-02-12 09:04:16 -0800772 // Logging statement below is useful to time how long each entry takes, but it's too verbose.
773 // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700774 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress,
775 get_mtime(fd, ds.now_));
Felipe Leme1d486fe2016-10-14 18:06:47 -0700776 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700777 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700778 ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800779 return false;
780 }
781
Felipe Leme770410d2016-01-26 17:07:14 -0800782 std::vector<uint8_t> buffer(65536);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800783 while (1) {
Zach Riggle22200402016-08-18 01:01:24 -0400784 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size()));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800785 if (bytes_read == 0) {
786 break;
787 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800788 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800789 return false;
790 }
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700791 err = zip_writer_->WriteBytes(buffer.data(), bytes_read);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800792 if (err) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700793 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800794 return false;
795 }
796 }
797
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700798 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700799 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700800 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800801 return false;
802 }
803
804 return true;
805}
806
Felipe Leme1d486fe2016-10-14 18:06:47 -0700807bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) {
808 android::base::unique_fd fd(
809 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
Andreas Gampeaff68432016-07-18 18:01:27 -0700810 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -0800811 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
Felipe Lemee82a27d2016-01-05 13:35:44 -0800812 return false;
813 }
814
Felipe Leme1d486fe2016-10-14 18:06:47 -0700815 return AddZipEntryFromFd(entry_name, fd.get());
Felipe Lemee82a27d2016-01-05 13:35:44 -0800816}
817
818/* adds a file to the existing zipped bugreport */
Felipe Leme4c2d6632016-09-28 14:32:00 -0700819static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) {
Felipe Leme1d486fe2016-10-14 18:06:47 -0700820 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
Felipe Lemee82a27d2016-01-05 13:35:44 -0800821}
822
Felipe Leme1d486fe2016-10-14 18:06:47 -0700823void Dumpstate::AddDir(const std::string& dir, bool recursive) {
824 if (!IsZipping()) {
825 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800826 return;
827 }
Felipe Leme678727a2016-09-21 17:22:11 -0700828 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
Felipe Leme46b85da2016-11-21 17:40:45 -0800829 DurationReporter duration_reporter(dir, true);
Felipe Leme678727a2016-09-21 17:22:11 -0700830 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
Felipe Lemee82a27d2016-01-05 13:35:44 -0800831}
832
Felipe Leme1d486fe2016-10-14 18:06:47 -0700833bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) {
834 if (!IsZipping()) {
835 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n",
836 entry_name.c_str());
Felipe Leme111b9d02016-02-03 09:28:24 -0800837 return false;
838 }
Felipe Lemecbce55d2016-02-08 09:53:18 -0800839 MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700840 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_);
Felipe Leme1d486fe2016-10-14 18:06:47 -0700841 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700842 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700843 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800844 return false;
845 }
846
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700847 err = zip_writer_->WriteBytes(content.c_str(), content.length());
Felipe Leme1d486fe2016-10-14 18:06:47 -0700848 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700849 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -0700850 ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800851 return false;
852 }
853
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700854 err = zip_writer_->FinishEntry();
Felipe Leme1d486fe2016-10-14 18:06:47 -0700855 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -0700856 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme809d74e2016-02-02 12:57:00 -0800857 return false;
858 }
859
860 return true;
861}
862
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800863static void DoKmsg() {
864 struct stat st;
865 if (!stat(PSTORE_LAST_KMSG, &st)) {
866 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
867 DumpFile("LAST KMSG", PSTORE_LAST_KMSG);
868 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) {
869 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG);
870 } else {
871 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
872 DumpFile("LAST KMSG", "/proc/last_kmsg");
873 }
874}
875
876static void DoLogcat() {
877 unsigned long timeout;
878 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags");
879 // calculate timeout
880 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
881 if (timeout < 20000) {
882 timeout = 20000;
883 }
Tony Makae737652017-03-30 17:47:09 +0100884 RunCommand("SYSTEM LOG",
885 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid",
886 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800887 CommandOptions::WithTimeout(timeout / 1000).Build());
888 timeout = logcat_timeout("events");
889 if (timeout < 20000) {
890 timeout = 20000;
891 }
892 RunCommand("EVENT LOG",
Tony Makae737652017-03-30 17:47:09 +0100893 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid",
894 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800895 CommandOptions::WithTimeout(timeout / 1000).Build());
896 timeout = logcat_timeout("radio");
897 if (timeout < 20000) {
898 timeout = 20000;
899 }
900 RunCommand("RADIO LOG",
Tony Makae737652017-03-30 17:47:09 +0100901 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid",
902 "-d", "*:v"},
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800903 CommandOptions::WithTimeout(timeout / 1000).Build());
904
905 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"});
906
907 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
908 RunCommand("LAST LOGCAT",
Tony Makae737652017-03-30 17:47:09 +0100909 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid",
910 "-d", "*:v"});
Felipe Leme6ec6ac42017-01-10 15:29:53 -0800911}
912
913static void DumpIpTables() {
Felipe Lemeb0f669d2016-09-26 18:26:11 -0700914 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"});
915 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"});
Erik Kline32af8c22016-09-28 17:26:26 +0900916 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700917 /* no ip6 nat */
Erik Kline32af8c22016-09-28 17:26:26 +0900918 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"});
919 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"});
920 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"});
921 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"});
Felipe Lemec0808152016-06-17 17:37:13 -0700922}
923
Narayan Kamath8f788292017-05-25 13:20:39 +0100924static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file,
925 const std::string& anr_traces_dir) {
Felipe Lemee184f662016-10-27 10:04:47 -0700926 std::string dump_traces_dir;
927
Felipe Lemee184f662016-10-27 10:04:47 -0700928 if (dump_traces_path != nullptr) {
929 if (add_to_zip) {
930 dump_traces_dir = dirname(dump_traces_path);
931 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str());
932 ds.AddDir(dump_traces_dir, true);
933 } else {
934 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
935 dump_traces_path);
936 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
937 }
938 }
939
Felipe Lemee184f662016-10-27 10:04:47 -0700940
941 // Make sure directory is not added twice.
942 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is
943 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system
944 // property - but in reality they're the same path (although the former could be nullptr).
945 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should
946 // be revisited.
947 bool already_dumped = anr_traces_dir == dump_traces_dir;
948
Narayan Kamath8f788292017-05-25 13:20:39 +0100949 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n",
Felipe Lemee184f662016-10-27 10:04:47 -0700950 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped);
951
Narayan Kamath8f788292017-05-25 13:20:39 +0100952 int fd = TEMP_FAILURE_RETRY(
953 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
954 if (fd < 0) {
955 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700956 } else {
Narayan Kamath8f788292017-05-25 13:20:39 +0100957 if (add_to_zip) {
958 if (!already_dumped) {
959 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n",
960 anr_traces_dir.c_str());
961 ds.AddDir(anr_traces_dir, true);
Felipe Lemee184f662016-10-27 10:04:47 -0700962 }
Narayan Kamath8f788292017-05-25 13:20:39 +0100963 } else {
964 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n",
965 anr_traces_file.c_str());
966 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd);
967 }
968 }
969}
970
971static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) {
972 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path,
973 anr_traces_dir.c_str());
974
975 // If we're here, dump_traces_path will always be a temporary file
976 // (created with mkostemp or similar) that contains dumps taken earlier
977 // on in the process.
978 if (dump_traces_path != nullptr) {
979 if (add_to_zip) {
980 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path);
981 } else {
982 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n",
983 dump_traces_path);
984 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path);
985 }
986
987 const int ret = unlink(dump_traces_path);
988 if (ret == -1) {
989 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path,
990 strerror(errno));
Felipe Lemee184f662016-10-27 10:04:47 -0700991 }
992 }
993
Narayan Kamath8f788292017-05-25 13:20:39 +0100994 const bool anr_traces_dumped = AddDumps(*anr_data, "ANR", add_to_zip);
995 if (!anr_traces_dumped) {
996 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str());
997 }
998}
999
1000static void AddAnrTraceFiles() {
1001 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR;
1002
1003 std::string anr_traces_file;
1004 std::string anr_traces_dir;
1005 bool is_global_trace_file = true;
1006
1007 // First check whether the stack-trace-dir property is set. When it's set,
1008 // each ANR trace will be written to a separate file and not to a global
1009 // stack trace file.
1010 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", "");
1011 if (anr_traces_dir.empty()) {
1012 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", "");
1013 if (!anr_traces_file.empty()) {
1014 is_global_trace_file = true;
1015 anr_traces_dir = dirname(anr_traces_file.c_str());
1016 }
1017 }
1018
1019 // We have neither configured a global trace file nor a trace directory,
1020 // there will be nothing to dump.
1021 if (anr_traces_file.empty() && anr_traces_dir.empty()) {
1022 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
Felipe Lemee184f662016-10-27 10:04:47 -07001023 return;
1024 }
1025
Narayan Kamath8f788292017-05-25 13:20:39 +01001026 if (is_global_trace_file) {
1027 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir);
1028 } else {
1029 AddAnrTraceDir(add_to_zip, anr_traces_dir);
1030 }
1031
Felipe Lemee184f662016-10-27 10:04:47 -07001032 /* slow traces for slow operations */
1033 struct stat st;
Narayan Kamath8f788292017-05-25 13:20:39 +01001034 if (!anr_traces_dir.empty()) {
Felipe Lemee184f662016-10-27 10:04:47 -07001035 int i = 0;
Narayan Kamath8f788292017-05-25 13:20:39 +01001036 while (true) {
1037 const std::string slow_trace_path =
1038 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i);
1039 if (stat(slow_trace_path.c_str(), &st)) {
Felipe Lemee184f662016-10-27 10:04:47 -07001040 // No traces file at this index, done with the files.
1041 break;
1042 }
Narayan Kamath8f788292017-05-25 13:20:39 +01001043 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str());
Felipe Lemee184f662016-10-27 10:04:47 -07001044 i++;
1045 }
1046 }
1047}
1048
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001049static void dumpstate() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001050 DurationReporter duration_reporter("DUMPSTATE");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001051
Arve Hjønnevåg2db0f5f2014-10-15 18:08:37 -07001052 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001053 RunCommand("UPTIME", {"uptime"});
Mark Salyzyn326842f2015-04-30 09:49:41 -07001054 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
Mark Salyzyn8c8130e2015-12-09 11:21:28 -08001055 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001056 DumpFile("MEMORY INFO", "/proc/meminfo");
1057 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001058 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
Felipe Lemef0292972016-11-22 13:57:05 -08001059 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20);
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001060 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat");
1061 DumpFile("VMALLOC INFO", "/proc/vmallocinfo");
1062 DumpFile("SLAB INFO", "/proc/slabinfo");
1063 DumpFile("ZONEINFO", "/proc/zoneinfo");
1064 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo");
1065 DumpFile("BUDDYINFO", "/proc/buddyinfo");
1066 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001067
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001068 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources");
1069 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
1070 DumpFile("KERNEL SYNC", "/d/sync");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001071
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001072 RunCommand("PROCESSES AND THREADS",
Felipe Leme30dbfa12016-09-02 12:43:26 -07001073 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"});
Felipe Lemef0292972016-11-22 13:57:05 -08001074 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001075
Andreas Huber69ec3ac2017-03-23 09:47:51 -07001076 if (ds.IsZipping()) {
1077 RunCommand(
1078 "HARDWARE HALS",
1079 {"lshal", std::string("--debug=") + kLsHalDebugPath},
1080 CommandOptions::AS_ROOT);
1081
1082 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath);
1083
1084 unlink(kLsHalDebugPath.c_str());
1085 } else {
1086 RunCommand(
1087 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT);
1088 }
Steven Moreland81b429e2017-01-31 19:50:46 -08001089
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001090 RunCommand("PRINTENV", {"printenv"});
Elliott Hughes21b7c8d2016-10-28 08:53:02 -07001091 RunCommand("NETSTAT", {"netstat", "-nW"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001092 struct stat s;
1093 if (stat("/proc/modules", &s) != 0) {
1094 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n");
1095 } else {
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001096 RunCommand("LSMOD", {"lsmod"});
Felipe Lemee4eca582016-06-10 17:48:08 -07001097 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001098
Colin Crossf45fa6b2012-03-26 12:38:26 -07001099 do_dmesg();
1100
Felipe Lemef0292972016-11-22 13:57:05 -08001101 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT);
Jeff Brown1dc94e32014-09-11 14:15:27 -07001102 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
1103 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
Mark Salyzyna297c322016-02-05 15:33:17 -08001104 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001105
Ajay Panicker2ff8e872017-04-27 14:04:32 -07001106 /* Dump Bluetooth HCI logs */
1107 ds.AddDir("/data/misc/bluetooth/logs", true);
Ajay Panickerd886ec42016-09-14 12:26:46 -07001108
Felipe Leme9a523ae2016-10-20 15:10:33 -07001109 if (!ds.do_early_screenshot_) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001110 MYLOGI("taking late screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001111 ds.TakeScreenshot();
Jeff Sharkey5a930032013-03-19 15:05:19 -07001112 }
1113
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001114 DoLogcat();
Mark Salyzynecc07632015-07-30 14:57:09 -07001115
Felipe Lemee184f662016-10-27 10:04:47 -07001116 AddAnrTraceFiles();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001117
Narayan Kamath8f788292017-05-25 13:20:39 +01001118 // NOTE: tombstones are always added as separate entries in the zip archive
1119 // and are not interspersed with the main report.
1120 const bool tombstones_dumped = AddDumps(*tombstone_data, "TOMBSTONE", true /* add_to_zip */);
1121 if (!tombstones_dumped) {
1122 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str());
Christopher Ferris7dc7f322014-07-22 16:08:19 -07001123 }
1124
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001125 DumpFile("NETWORK DEV INFO", "/proc/net/dev");
1126 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
1127 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
1128 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
1129 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001130
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001131 DoKmsg();
Mark Salyzyn2262c162014-12-16 09:09:26 -08001132
Colin Crossf45fa6b2012-03-26 12:38:26 -07001133 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
Elliott Hughesa59828a2015-01-27 20:48:52 -08001134
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001135 RunCommand("NETWORK INTERFACES", {"ip", "link"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001136
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001137 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"});
1138 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"});
Lorenzo Colittid4c3d382014-07-30 14:38:20 +09001139
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001140 RunCommand("IP RULES", {"ip", "rule", "show"});
1141 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"});
Sreeram Ramachandran2b3bba32014-07-08 15:40:55 -07001142
1143 dump_route_tables();
1144
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001145 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"});
1146 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"});
1147 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"});
1148 RunCommand("WIFI NETWORKS", {"wpa_cli", "IFNAME=wlan0", "list_networks"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001149 CommandOptions::WithTimeout(20).Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001150
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001151 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"},
Felipe Leme30dbfa12016-09-02 12:43:26 -07001152 CommandOptions::WithTimeout(10).Build());
Lorenzo Colitti6afc38c2015-09-09 22:59:25 +09001153
Elliott Hughes23ccc622017-02-28 10:14:22 -08001154 RunCommand("SYSTEM PROPERTIES", {"getprop"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001155
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001156 RunCommand("VOLD DUMP", {"vdc", "dump"});
1157 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001158
Jin Qian24354422017-01-24 12:07:14 -08001159 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build());
ynwangf649a6e2016-07-17 21:56:00 -07001160
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001161 RunCommand("FILESYSTEMS & FREE SPACE", {"df"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001162
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001163 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001164
Felipe Lemed8b94e52016-12-08 10:21:44 -08001165 printf("------ BACKLIGHTS ------\n");
1166 printf("LCD brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001167 DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001168 printf("Button brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001169 DumpFile("", "/sys/class/leds/button-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001170 printf("Keyboard brightness=");
Felipe Leme678727a2016-09-21 17:22:11 -07001171 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001172 printf("ALS mode=");
Felipe Leme678727a2016-09-21 17:22:11 -07001173 DumpFile("", "/sys/class/leds/lcd-backlight/als");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001174 printf("LCD driver registers:\n");
Felipe Leme678727a2016-09-21 17:22:11 -07001175 DumpFile("", "/sys/class/leds/lcd-backlight/registers");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001176 printf("\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001177
1178 /* Binder state is expensive to look at as it uses a lot of memory. */
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001179 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
1180 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
1181 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
1182 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats");
1183 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001184
Felipe Leme6f674ae2016-11-18 17:10:33 -08001185 ds.DumpstateBoard();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001186
Steven Moreland7440ddb2016-12-15 16:13:39 -08001187 /* Migrate the ril_dumpstate to a device specific dumpstate? */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001188 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0);
1189 if (rilDumpstateTimeout > 0) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001190 // su does not exist on user builds, so try running without it.
1191 // This way any implementations of vril-dump that do not require
1192 // root can run on user builds.
1193 CommandOptions::CommandOptionsBuilder options =
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001194 CommandOptions::WithTimeout(rilDumpstateTimeout);
Felipe Lemef0292972016-11-22 13:57:05 -08001195 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme30dbfa12016-09-02 12:43:26 -07001196 options.AsRoot();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001197 }
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001198 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build());
Colin Crossf45fa6b2012-03-26 12:38:26 -07001199 }
1200
Felipe Lemed8b94e52016-12-08 10:21:44 -08001201 printf("========================================================\n");
1202 printf("== Android Framework Services\n");
1203 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001204
Felipe Leme5bcce572016-09-27 09:21:08 -07001205 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(),
1206 10);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001207
Felipe Lemed8b94e52016-12-08 10:21:44 -08001208 printf("========================================================\n");
1209 printf("== Checkins\n");
1210 printf("========================================================\n");
Dianne Hackborn02bea972013-06-26 18:59:09 -07001211
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001212 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
1213 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"});
1214 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"});
1215 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"});
1216 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"});
1217 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"});
Dianne Hackborn02bea972013-06-26 18:59:09 -07001218
Felipe Lemed8b94e52016-12-08 10:21:44 -08001219 printf("========================================================\n");
1220 printf("== Running Application Activities\n");
1221 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001222
Winson Chung1434a5c2017-02-28 17:09:24 -08001223 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001224
Felipe Lemed8b94e52016-12-08 10:21:44 -08001225 printf("========================================================\n");
1226 printf("== Running Application Services\n");
1227 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001228
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001229 RunDumpsys("APP SERVICES", {"activity", "service", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001230
Felipe Lemed8b94e52016-12-08 10:21:44 -08001231 printf("========================================================\n");
1232 printf("== Running Application Providers\n");
1233 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001234
Felipe Lemeb0f669d2016-09-26 18:26:11 -07001235 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"});
Colin Crossf45fa6b2012-03-26 12:38:26 -07001236
Adrian Roos8b397ab2017-04-04 16:35:44 -07001237 printf("========================================================\n");
1238 printf("== Dropbox crashes\n");
1239 printf("========================================================\n");
1240
1241 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
1242 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
1243
Naveen Kalla058e1e82016-10-19 21:38:44 -07001244 // DumpModemLogs adds the modem logs if available to the bugreport.
1245 // Do this at the end to allow for sufficient time for the modem logs to be
1246 // collected.
1247 DumpModemLogs();
1248
Felipe Lemed8b94e52016-12-08 10:21:44 -08001249 printf("========================================================\n");
1250 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
1251 ds.progress_->GetMax(), ds.progress_->GetInitialMax());
1252 printf("========================================================\n");
1253 printf("== dumpstate: done (id %d)\n", ds.id_);
1254 printf("========================================================\n");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001255}
1256
Felipe Leme6f674ae2016-11-18 17:10:33 -08001257void Dumpstate::DumpstateBoard() {
1258 DurationReporter duration_reporter("dumpstate_board()");
Felipe Lemed8b94e52016-12-08 10:21:44 -08001259 printf("========================================================\n");
1260 printf("== Board\n");
1261 printf("========================================================\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001262
Chris Phoenix69d92212017-01-24 23:01:13 -08001263 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService());
Felipe Leme6f674ae2016-11-18 17:10:33 -08001264 if (dumpstate_device == nullptr) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001265 MYLOGE("No IDumpstateDevice implementation\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001266 return;
1267 }
1268
1269 if (!IsZipping()) {
Steven Moreland7440ddb2016-12-15 16:13:39 -08001270 MYLOGD("Not dumping board info because it's not a zipped bugreport\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001271 return;
1272 }
1273
Steven Moreland7440ddb2016-12-15 16:13:39 -08001274 std::string path = kDumpstateBoardPath;
Felipe Leme6f674ae2016-11-18 17:10:33 -08001275 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path.c_str());
1276
1277 int fd =
1278 TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1279 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1280 if (fd < 0) {
1281 MYLOGE("Could not open file %s: %s\n", path.c_str(), strerror(errno));
1282 return;
1283 }
1284
1285 native_handle_t* handle = native_handle_create(1, 0);
1286 if (handle == nullptr) {
1287 MYLOGE("Could not create native_handle\n");
1288 return;
1289 }
1290 handle->data[0] = fd;
1291
Felipe Lemef0292972016-11-22 13:57:05 -08001292 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call.
Steven Moreland7440ddb2016-12-15 16:13:39 -08001293 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle);
1294 if (!status.isOk()) {
1295 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str());
1296 native_handle_close(handle);
1297 native_handle_delete(handle);
1298 return;
1299 }
Felipe Leme6f674ae2016-11-18 17:10:33 -08001300
1301 AddZipEntry("dumpstate-board.txt", path);
Felipe Lemed8b94e52016-12-08 10:21:44 -08001302 printf("*** See dumpstate-board.txt entry ***\n");
Felipe Leme6f674ae2016-11-18 17:10:33 -08001303
1304 native_handle_close(handle);
1305 native_handle_delete(handle);
1306
1307 if (remove(path.c_str()) != 0) {
1308 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno));
1309 }
1310}
1311
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001312static void ShowUsageAndExit(int exitCode = 1) {
1313 fprintf(stderr,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001314 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] "
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001315 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
1316 " -h: display this help message\n"
1317 " -b: play sound file instead of vibrate, at beginning of job\n"
1318 " -e: play sound file instead of vibrate, at end of job\n"
1319 " -o: write to file (instead of stdout)\n"
1320 " -d: append date to filename (requires -o)\n"
1321 " -p: capture screenshot to filename.png (requires -o)\n"
1322 " -z: generate zipped file (requires -o)\n"
1323 " -s: write output to control socket (for init)\n"
1324 " -S: write file location to control socket (for init; requires -o and -z)"
1325 " -q: disable vibrate\n"
1326 " -B: send broadcast when finished (requires -o)\n"
1327 " -P: send broadcast when started and update system properties on "
1328 "progress (requires -o and -B)\n"
1329 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
1330 "shouldn't be used with -P)\n"
Felipe Lemed071c682016-10-20 16:48:00 -07001331 " -v: prints the dumpstate header and exit\n");
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001332 exit(exitCode);
1333}
1334
1335static void ExitOnInvalidArgs() {
1336 fprintf(stderr, "invalid combination of args\n");
1337 ShowUsageAndExit();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001338}
1339
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001340static void sig_handler(int) {
Andres Morales2e671bb2014-08-21 12:38:22 -07001341 _exit(EXIT_FAILURE);
John Michelau885f8882013-05-06 16:42:02 -05001342}
1343
Wei Liuf87959e2016-08-26 14:51:42 -07001344static void register_sig_handler() {
1345 struct sigaction sa;
1346 sigemptyset(&sa.sa_mask);
1347 sa.sa_flags = 0;
1348 sa.sa_handler = sig_handler;
1349 sigaction(SIGPIPE, &sa, NULL); // broken pipe
1350 sigaction(SIGSEGV, &sa, NULL); // segment fault
1351 sigaction(SIGINT, &sa, NULL); // ctrl-c
1352 sigaction(SIGTERM, &sa, NULL); // killed
1353 sigaction(SIGQUIT, &sa, NULL); // quit
1354}
1355
Felipe Leme1d486fe2016-10-14 18:06:47 -07001356bool Dumpstate::FinishZipFile() {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001357 std::string entry_name = base_name_ + "-" + name_ + ".txt";
Felipe Leme1d486fe2016-10-14 18:06:47 -07001358 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001359 tmp_path_.c_str());
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001360 // Final timestamp
1361 char date[80];
1362 time_t the_real_now_please_stand_up = time(nullptr);
1363 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001364 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date,
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001365 the_real_now_please_stand_up - ds.now_);
Felipe Leme5b9d3bf2016-08-16 17:20:21 -07001366
Felipe Leme9a523ae2016-10-20 15:10:33 -07001367 if (!ds.AddZipEntry(entry_name, tmp_path_)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001368 MYLOGE("Failed to add text entry to .zip file\n");
Felipe Leme1e9edc62015-12-21 16:02:13 -08001369 return false;
1370 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001371 if (!AddTextZipEntry("main_entry.txt", entry_name)) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001372 MYLOGE("Failed to add main_entry.txt to .zip file\n");
Felipe Leme111b9d02016-02-03 09:28:24 -08001373 return false;
Felipe Leme809d74e2016-02-02 12:57:00 -08001374 }
Felipe Leme1e9edc62015-12-21 16:02:13 -08001375
Felipe Leme0f3fb202016-06-10 17:10:53 -07001376 // Add log file (which contains stderr output) to zip...
1377 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001378 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) {
Felipe Leme0f3fb202016-06-10 17:10:53 -07001379 MYLOGE("Failed to add dumpstate log to .zip file\n");
1380 return false;
1381 }
1382 // ... and re-opens it for further logging.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001383 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
Felipe Leme0f3fb202016-06-10 17:10:53 -07001384 fprintf(stderr, "\n");
1385
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001386 int32_t err = zip_writer_->Finish();
Felipe Leme1d486fe2016-10-14 18:06:47 -07001387 if (err != 0) {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001388 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001389 return false;
1390 }
1391
Felipe Leme1d486fe2016-10-14 18:06:47 -07001392 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor.
1393 ds.zip_file.reset(nullptr);
1394
Felipe Lemee9d2c542016-11-15 11:48:26 -08001395 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str())
1396 if (remove(tmp_path_.c_str()) != 0) {
1397 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno));
Felipe Lemec4eee562016-04-21 15:42:55 -07001398 }
1399
Felipe Leme1e9edc62015-12-21 16:02:13 -08001400 return true;
1401}
Felipe Leme6e01fa62015-11-11 19:35:14 -08001402
Michal Karpinski4db754f2015-12-11 18:04:32 +00001403static std::string SHA256_file_hash(std::string filepath) {
Andreas Gampe27cd7b22016-07-18 18:24:05 -07001404 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
1405 | O_CLOEXEC | O_NOFOLLOW)));
Andreas Gampeaff68432016-07-18 18:01:27 -07001406 if (fd == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001407 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001408 return NULL;
1409 }
1410
1411 SHA256_CTX ctx;
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001412 SHA256_Init(&ctx);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001413
1414 std::vector<uint8_t> buffer(65536);
1415 while (1) {
1416 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
1417 if (bytes_read == 0) {
1418 break;
1419 } else if (bytes_read == -1) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001420 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
Michal Karpinski4db754f2015-12-11 18:04:32 +00001421 return NULL;
1422 }
1423
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001424 SHA256_Update(&ctx, buffer.data(), bytes_read);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001425 }
1426
Elliott Hughesc4dc1412016-04-12 16:28:31 -07001427 uint8_t hash[SHA256_DIGEST_LENGTH];
1428 SHA256_Final(hash, &ctx);
1429
1430 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1];
1431 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) {
Michal Karpinskicbbdf732016-01-07 20:45:02 +00001432 sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001433 }
1434 hash_buffer[sizeof(hash_buffer) - 1] = 0;
1435 return std::string(hash_buffer);
1436}
1437
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001438static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) {
1439 // clang-format off
1440 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0",
1441 "--receiver-foreground", "--receiver-include-background", "-a", action};
1442 // clang-format on
Felipe Leme8d2410e2017-02-08 09:46:08 -08001443
1444 am.insert(am.end(), args.begin(), args.end());
1445
Felipe Leme8d2410e2017-02-08 09:46:08 -08001446 RunCommand("", am,
1447 CommandOptions::WithTimeout(20)
1448 .Log("Sending broadcast: '%s'\n")
1449 .Always()
1450 .DropRoot()
1451 .RedirectStderr()
1452 .Build());
1453}
1454
Felipe Leme35b8cf12017-02-10 15:47:29 -08001455static void Vibrate(int duration_ms) {
1456 // clang-format off
1457 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"},
1458 CommandOptions::WithTimeout(10)
1459 .Log("Vibrate: '%s'\n")
1460 .Always()
1461 .Build());
1462 // clang-format on
1463}
1464
Colin Crossf45fa6b2012-03-26 12:38:26 -07001465int main(int argc, char *argv[]) {
1466 int do_add_date = 0;
Felipe Leme6e01fa62015-11-11 19:35:14 -08001467 int do_zip_file = 0;
John Michelau1f794c42012-09-17 11:20:19 -05001468 int do_vibrate = 1;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001469 char* use_outfile = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001470 int use_socket = 0;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001471 int use_control_socket = 0;
Colin Crossf45fa6b2012-03-26 12:38:26 -07001472 int do_fb = 0;
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001473 int do_broadcast = 0;
Michal Karpinski4db754f2015-12-11 18:04:32 +00001474 int is_remote_mode = 0;
Felipe Lemed071c682016-10-20 16:48:00 -07001475 bool show_header_only = false;
Felipe Leme75876a22016-10-27 16:31:27 -07001476 bool do_start_service = false;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001477 bool telephony_only = false;
Felipe Leme8fecfdd2016-02-09 10:40:07 -08001478
Colin Crossf45fa6b2012-03-26 12:38:26 -07001479 /* set as high priority, and protect from OOM killer */
1480 setpriority(PRIO_PROCESS, 0, -20);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001481
Felipe Lemed071c682016-10-20 16:48:00 -07001482 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we");
Colin Crossf45fa6b2012-03-26 12:38:26 -07001483 if (oom_adj) {
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001484 fputs("-1000", oom_adj);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001485 fclose(oom_adj);
Wei Wang9c1f9bb2016-06-28 14:32:35 -07001486 } else {
1487 /* fallback to kernels <= 2.6.35 */
1488 oom_adj = fopen("/proc/self/oom_adj", "we");
1489 if (oom_adj) {
1490 fputs("-17", oom_adj);
1491 fclose(oom_adj);
1492 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001493 }
1494
Jeff Brown1dc94e32014-09-11 14:15:27 -07001495 /* parse arguments */
Colin Crossf45fa6b2012-03-26 12:38:26 -07001496 int c;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001497 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001498 switch (c) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001499 // clang-format off
Felipe Lemed071c682016-10-20 16:48:00 -07001500 case 'd': do_add_date = 1; break;
1501 case 'z': do_zip_file = 1; break;
1502 case 'o': use_outfile = optarg; break;
1503 case 's': use_socket = 1; break;
1504 case 'S': use_control_socket = 1; break;
1505 case 'v': show_header_only = true; break;
1506 case 'q': do_vibrate = 0; break;
1507 case 'p': do_fb = 1; break;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001508 case 'P': ds.update_progress_ = true; break;
Felipe Lemed071c682016-10-20 16:48:00 -07001509 case 'R': is_remote_mode = 1; break;
1510 case 'B': do_broadcast = 1; break;
1511 case 'V': break; // compatibility no-op
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001512 case 'h':
1513 ShowUsageAndExit(0);
1514 break;
1515 default:
1516 fprintf(stderr, "Invalid option: %c\n", c);
1517 ShowUsageAndExit();
Felipe Lemee844a9d2016-09-21 15:01:39 -07001518 // clang-format on
Colin Crossf45fa6b2012-03-26 12:38:26 -07001519 }
1520 }
1521
Felipe Lemed071c682016-10-20 16:48:00 -07001522 // TODO: use helper function to convert argv into a string
1523 for (int i = 0; i < argc; i++) {
1524 ds.args_ += argv[i];
1525 if (i < argc - 1) {
1526 ds.args_ += " ";
1527 }
1528 }
1529
1530 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001531 if (!ds.extra_options_.empty()) {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001532 // Framework uses a system property to override some command-line args.
1533 // Currently, it contains the type of the requested bugreport.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001534 if (ds.extra_options_ == "bugreportplus") {
Felipe Leme75876a22016-10-27 16:31:27 -07001535 // Currently, the dumpstate binder is only used by Shell to update progress.
1536 do_start_service = true;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001537 ds.update_progress_ = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001538 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001539 } else if (ds.extra_options_ == "bugreportremote") {
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001540 do_vibrate = 0;
1541 is_remote_mode = 1;
1542 do_fb = 0;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001543 } else if (ds.extra_options_ == "bugreportwear") {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001544 ds.update_progress_ = true;
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001545 } else if (ds.extra_options_ == "bugreporttelephony") {
1546 telephony_only = true;
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001547 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001548 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str());
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001549 }
1550 // Reset the property
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001551 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, "");
Felipe Leme9ce6aa42016-09-21 10:02:25 -07001552 }
1553
Naveen Kallab53a1c92017-03-16 18:17:25 -07001554 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, "");
1555 if (!ds.notification_title.empty()) {
1556 // Reset the property
1557 android::base::SetProperty(PROPERTY_EXTRA_TITLE, "");
1558
1559 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1560 if (!ds.notification_description.empty()) {
1561 // Reset the property
1562 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, "");
1563 }
1564 MYLOGD("notification (title: %s, description: %s)\n",
1565 ds.notification_title.c_str(), ds.notification_description.c_str());
1566 }
1567
Felipe Leme9a523ae2016-10-20 15:10:33 -07001568 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001569 ExitOnInvalidArgs();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001570 }
1571
Felipe Leme2628e9e2016-04-12 16:36:51 -07001572 if (use_control_socket && !do_zip_file) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001573 ExitOnInvalidArgs();
Felipe Leme2628e9e2016-04-12 16:36:51 -07001574 }
1575
Felipe Leme9a523ae2016-10-20 15:10:33 -07001576 if (ds.update_progress_ && !do_broadcast) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001577 ExitOnInvalidArgs();
Felipe Leme71bbfc52015-11-23 14:14:51 -08001578 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001579
Felipe Leme9a523ae2016-10-20 15:10:33 -07001580 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) {
Felipe Leme4a0db9f2016-09-28 09:35:01 -07001581 ExitOnInvalidArgs();
Michal Karpinski4db754f2015-12-11 18:04:32 +00001582 }
1583
Felipe Lemed071c682016-10-20 16:48:00 -07001584 if (ds.version_ == VERSION_DEFAULT) {
1585 ds.version_ = VERSION_CURRENT;
Felipe Leme809d74e2016-02-02 12:57:00 -08001586 }
1587
Felipe Lemee184f662016-10-27 10:04:47 -07001588 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) {
1589 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n",
1590 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(),
1591 VERSION_SPLIT_ANR.c_str());
Felipe Lemed071c682016-10-20 16:48:00 -07001592 exit(1);
1593 }
1594
1595 if (show_header_only) {
1596 ds.PrintHeader();
1597 exit(0);
1598 }
1599
Felipe Leme7447d7c2016-11-03 18:12:22 -07001600 /* redirect output if needed */
1601 bool is_redirecting = !use_socket && use_outfile;
1602
1603 // TODO: temporarily set progress until it's part of the Dumpstate constructor
1604 std::string stats_path =
1605 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile))
1606 : "";
1607 ds.progress_.reset(new Progress(stats_path));
1608
Felipe Lemed071c682016-10-20 16:48:00 -07001609 /* gets the sequential id */
Felipe Leme7447d7c2016-11-03 18:12:22 -07001610 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0);
Felipe Lemed071c682016-10-20 16:48:00 -07001611 ds.id_ = ++last_id;
1612 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id));
1613
1614 MYLOGI("begin\n");
1615
Felipe Leme6ae5c4f2017-01-10 14:13:22 -08001616 register_sig_handler();
Felipe Lemed071c682016-10-20 16:48:00 -07001617
Felipe Leme75876a22016-10-27 16:31:27 -07001618 if (do_start_service) {
1619 MYLOGI("Starting 'dumpstate' service\n");
1620 android::status_t ret;
1621 if ((ret = android::os::DumpstateService::Start()) != android::OK) {
1622 MYLOGE("Unable to start DumpstateService: %d\n", ret);
1623 }
1624 }
1625
Felipe Lemef0292972016-11-22 13:57:05 -08001626 if (PropertiesHelper::IsDryRun()) {
Felipe Lemed071c682016-10-20 16:48:00 -07001627 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n");
1628 }
1629
Felipe Leme7447d7c2016-11-03 18:12:22 -07001630 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(),
Felipe Lemed071c682016-10-20 16:48:00 -07001631 ds.extra_options_.c_str());
1632
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001633 MYLOGI("bugreport format version: %s\n", ds.version_.c_str());
Felipe Leme809d74e2016-02-02 12:57:00 -08001634
Felipe Leme9a523ae2016-10-20 15:10:33 -07001635 ds.do_early_screenshot_ = ds.update_progress_;
Felipe Lemee338bf62015-12-07 14:03:50 -08001636
Christopher Ferrised9354f2014-10-01 17:35:01 -07001637 // If we are going to use a socket, do it as early as possible
1638 // to avoid timeouts from bugreport.
1639 if (use_socket) {
1640 redirect_to_socket(stdout, "dumpstate");
1641 }
1642
Felipe Leme2628e9e2016-04-12 16:36:51 -07001643 if (use_control_socket) {
1644 MYLOGD("Opening control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001645 ds.control_socket_fd_ = open_socket("dumpstate");
1646 ds.update_progress_ = 1;
Felipe Leme2628e9e2016-04-12 16:36:51 -07001647 }
1648
Felipe Leme71bbfc52015-11-23 14:14:51 -08001649 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001650 ds.bugreport_dir_ = dirname(use_outfile);
Felipe Lemef8124bd2016-12-15 08:54:22 -08001651 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD");
Ian Pedowitz570e6ec2017-03-17 22:36:53 -07001652 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE");
Felipe Lemef8124bd2016-12-15 08:54:22 -08001653 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile),
1654 device_name.c_str(), build_id.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001655 if (do_add_date) {
1656 char date[80];
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001657 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_));
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001658 ds.name_ = date;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001659 } else {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001660 ds.name_ = "undated";
Felipe Leme71bbfc52015-11-23 14:14:51 -08001661 }
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001662
1663 if (telephony_only) {
1664 ds.base_name_ += "-telephony";
1665 }
1666
Felipe Leme71bbfc52015-11-23 14:14:51 -08001667 if (do_fb) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001668 ds.screenshot_path_ = ds.GetPath(".png");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001669 }
Felipe Leme9a523ae2016-10-20 15:10:33 -07001670 ds.tmp_path_ = ds.GetPath(".tmp");
Felipe Leme75876a22016-10-27 16:31:27 -07001671 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt");
Felipe Leme71bbfc52015-11-23 14:14:51 -08001672
Felipe Lemee844a9d2016-09-21 15:01:39 -07001673 MYLOGD(
1674 "Bugreport dir: %s\n"
1675 "Base name: %s\n"
1676 "Suffix: %s\n"
1677 "Log path: %s\n"
1678 "Temporary path: %s\n"
1679 "Screenshot path: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001680 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(),
1681 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str());
Felipe Leme71bbfc52015-11-23 14:14:51 -08001682
Felipe Leme1e9edc62015-12-21 16:02:13 -08001683 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001684 ds.path_ = ds.GetPath(".zip");
1685 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str());
1686 create_parent_dirs(ds.path_.c_str());
1687 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb"));
Felipe Leme1d486fe2016-10-14 18:06:47 -07001688 if (ds.zip_file == nullptr) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001689 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001690 do_zip_file = 0;
1691 } else {
Felipe Lemec6bc8bc2016-10-27 15:58:27 -07001692 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get()));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001693 }
Felipe Leme1d486fe2016-10-14 18:06:47 -07001694 ds.AddTextZipEntry("version.txt", ds.version_);
Felipe Leme1e9edc62015-12-21 16:02:13 -08001695 }
1696
Felipe Leme9a523ae2016-10-20 15:10:33 -07001697 if (ds.update_progress_) {
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001698 if (do_broadcast) {
1699 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001700
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001701 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001702 "--receiver-permission", "android.permission.DUMP",
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001703 "--es", "android.intent.extra.NAME", ds.name_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001704 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001705 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001706 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001707 };
1708 // clang-format on
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001709 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args);
Felipe Lemedcd1f0d2016-08-04 12:48:50 -07001710 }
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001711 if (use_control_socket) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001712 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001713 }
Felipe Leme71bbfc52015-11-23 14:14:51 -08001714 }
1715 }
1716
Nick Kralevichf3599b32016-01-25 15:05:16 -08001717 /* read /proc/cmdline before dropping root */
1718 FILE *cmdline = fopen("/proc/cmdline", "re");
1719 if (cmdline) {
1720 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
1721 fclose(cmdline);
1722 }
1723
John Michelau1f794c42012-09-17 11:20:19 -05001724 if (do_vibrate) {
Felipe Leme35b8cf12017-02-10 15:47:29 -08001725 Vibrate(150);
John Michelau1f794c42012-09-17 11:20:19 -05001726 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001727
Felipe Leme9a523ae2016-10-20 15:10:33 -07001728 if (do_fb && ds.do_early_screenshot_) {
1729 if (ds.screenshot_path_.empty()) {
Felipe Leme3634a1e2015-12-09 10:11:47 -08001730 // should not have happened
Felipe Lemecbce55d2016-02-08 09:53:18 -08001731 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
Felipe Leme3634a1e2015-12-09 10:11:47 -08001732 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001733 MYLOGI("taking early screenshot\n");
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001734 ds.TakeScreenshot();
Felipe Lemee338bf62015-12-07 14:03:50 -08001735 }
1736 }
1737
Felipe Leme1e9edc62015-12-21 16:02:13 -08001738 if (do_zip_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001739 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) {
1740 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001741 strerror(errno));
Felipe Leme1e9edc62015-12-21 16:02:13 -08001742 }
1743 }
1744
Felipe Leme71bbfc52015-11-23 14:14:51 -08001745 if (is_redirecting) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001746 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str()));
1747 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) {
1748 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
1749 ds.log_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001750 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001751 /* TODO: rather than generating a text file now and zipping it later,
1752 it would be more efficient to redirect stdout to the zip entry
1753 directly, but the libziparchive doesn't support that option yet. */
Felipe Leme9a523ae2016-10-20 15:10:33 -07001754 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str()));
1755 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) {
Felipe Leme6fe9db62016-02-12 09:04:16 -08001756 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001757 ds.tmp_path_.c_str(), strerror(errno));
Felipe Leme6fe9db62016-02-12 09:04:16 -08001758 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001759 }
Felipe Lemed8b94e52016-12-08 10:21:44 -08001760
1761 // Don't buffer stdout
1762 setvbuf(stdout, nullptr, _IONBF, 0);
1763
Felipe Leme608385d2016-02-01 10:35:38 -08001764 // NOTE: there should be no stdout output until now, otherwise it would break the header.
1765 // In particular, DurationReport objects should be created passing 'title, NULL', so their
Felipe Lemecbce55d2016-02-08 09:53:18 -08001766 // duration is logged into MYLOG instead.
Felipe Lemebbaf3c12016-10-11 14:32:25 -07001767 ds.PrintHeader();
Colin Crossf45fa6b2012-03-26 12:38:26 -07001768
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001769 if (telephony_only) {
1770 DumpIpTables();
1771 if (!DropRootUser()) {
1772 return -1;
1773 }
1774 do_dmesg();
1775 DoLogcat();
1776 DoKmsg();
1777 ds.DumpstateBoard();
1778 DumpModemLogs();
1779 } else {
1780 // Dumps systrace right away, otherwise it will be filled with unnecessary events.
1781 // First try to dump anrd trace if the daemon is running. Otherwise, dump
1782 // the raw trace.
1783 if (!dump_anrd_trace()) {
1784 dump_systrace();
1785 }
1786
1787 // Invoking the following dumpsys calls before dump_traces() to try and
1788 // keep the system stats as close to its initial state as possible.
1789 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"},
1790 CommandOptions::WithTimeout(90).DropRoot().Build());
1791 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"},
1792 CommandOptions::WithTimeout(10).DropRoot().Build());
1793
1794 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed.
1795 dump_raft();
1796
1797 /* collect stack traces from Dalvik and native processes (needs root) */
1798 dump_traces_path = dump_traces();
1799
1800 /* Run some operations that require root. */
Narayan Kamath8f788292017-05-25 13:20:39 +01001801 tombstone_data.reset(GetDumpFds(TOMBSTONE_FILE_PREFIX, !ds.IsZipping()));
1802 anr_data.reset(GetDumpFds(ANR_FILE_PREFIX, !ds.IsZipping()));
1803
Felipe Leme6ec6ac42017-01-10 15:29:53 -08001804 ds.AddDir(RECOVERY_DIR, true);
1805 ds.AddDir(RECOVERY_DATA_DIR, true);
1806 ds.AddDir(LOGPERSIST_DATA_DIR, false);
1807 if (!PropertiesHelper::IsUserBuild()) {
1808 ds.AddDir(PROFILE_DATA_DIR_CUR, true);
1809 ds.AddDir(PROFILE_DATA_DIR_REF, true);
1810 }
1811 add_mountinfo();
1812 DumpIpTables();
1813
1814 // Capture any IPSec policies in play. No keys are exposed here.
1815 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"},
1816 CommandOptions::WithTimeout(10).Build());
1817
1818 // Run ss as root so we can see socket marks.
1819 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"},
1820 CommandOptions::WithTimeout(10).Build());
1821
1822 if (!DropRootUser()) {
1823 return -1;
1824 }
1825
1826 dumpstate();
Zhengyin Qian068ecc72016-08-10 16:48:14 -07001827 }
Felipe Leme71a74ac2016-03-17 15:43:25 -07001828
Felipe Leme55b42a62015-11-10 17:39:08 -08001829 /* close output if needed */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001830 if (is_redirecting) {
Colin Crossf45fa6b2012-03-26 12:38:26 -07001831 fclose(stdout);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001832 }
1833
Felipe Leme6e01fa62015-11-11 19:35:14 -08001834 /* rename or zip the (now complete) .tmp file to its final location */
1835 if (use_outfile) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001836
1837 /* check if user changed the suffix using system properties */
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001838 std::string name = android::base::GetProperty(
Felipe Leme75876a22016-10-27 16:31:27 -07001839 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), "");
Felipe Lemead5f6c42015-11-30 14:26:46 -08001840 bool change_suffix= false;
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001841 if (!name.empty()) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001842 /* must whitelist which characters are allowed, otherwise it could cross directories */
1843 std::regex valid_regex("^[-_a-zA-Z0-9]+$");
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001844 if (std::regex_match(name.c_str(), valid_regex)) {
Felipe Lemead5f6c42015-11-30 14:26:46 -08001845 change_suffix = true;
1846 } else {
Felipe Leme96c2bbb2016-09-26 09:21:21 -07001847 MYLOGE("invalid suffix provided by user: %s\n", name.c_str());
Felipe Lemead5f6c42015-11-30 14:26:46 -08001848 }
1849 }
1850 if (change_suffix) {
Felipe Leme2b9b06c2016-10-14 09:13:06 -07001851 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str());
1852 ds.name_ = name;
Felipe Leme9a523ae2016-10-20 15:10:33 -07001853 if (!ds.screenshot_path_.empty()) {
1854 std::string new_screenshot_path = ds.GetPath(".png");
1855 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) {
1856 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(),
1857 new_screenshot_path.c_str(), strerror(errno));
Felipe Lemead5f6c42015-11-30 14:26:46 -08001858 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001859 ds.screenshot_path_ = new_screenshot_path;
Felipe Lemead5f6c42015-11-30 14:26:46 -08001860 }
1861 }
1862 }
1863
Felipe Leme6e01fa62015-11-11 19:35:14 -08001864 bool do_text_file = true;
1865 if (do_zip_file) {
Felipe Leme1d486fe2016-10-14 18:06:47 -07001866 if (!ds.FinishZipFile()) {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001867 MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001868 do_text_file = true;
1869 } else {
1870 do_text_file = false;
Felipe Leme91274352016-02-26 15:03:52 -08001871 // Since zip file is already created, it needs to be renamed.
Felipe Leme9a523ae2016-10-20 15:10:33 -07001872 std::string new_path = ds.GetPath(".zip");
1873 if (ds.path_ != new_path) {
1874 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str());
1875 if (rename(ds.path_.c_str(), new_path.c_str())) {
1876 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001877 strerror(errno));
Felipe Leme91274352016-02-26 15:03:52 -08001878 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001879 ds.path_ = new_path;
Felipe Leme91274352016-02-26 15:03:52 -08001880 }
1881 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001882 }
1883 }
1884 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001885 ds.path_ = ds.GetPath(".txt");
1886 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(),
1887 ds.tmp_path_.c_str());
1888 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) {
1889 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(),
Felipe Leme1d486fe2016-10-14 18:06:47 -07001890 strerror(errno));
Felipe Leme9a523ae2016-10-20 15:10:33 -07001891 ds.path_.clear();
Felipe Leme6e01fa62015-11-11 19:35:14 -08001892 }
1893 }
Felipe Leme2628e9e2016-04-12 16:36:51 -07001894 if (use_control_socket) {
1895 if (do_text_file) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001896 dprintf(ds.control_socket_fd_,
Felipe Lemee844a9d2016-09-21 15:01:39 -07001897 "FAIL:could not create zip file, check %s "
1898 "for more details\n",
Felipe Leme9a523ae2016-10-20 15:10:33 -07001899 ds.log_path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001900 } else {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001901 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str());
Felipe Leme2628e9e2016-04-12 16:36:51 -07001902 }
1903 }
Colin Crossf45fa6b2012-03-26 12:38:26 -07001904 }
1905
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001906 /* vibrate a few but shortly times to let user know it's finished */
Felipe Leme35b8cf12017-02-10 15:47:29 -08001907 for (int i = 0; i < 3; i++) {
1908 Vibrate(75);
1909 usleep((75 + 50) * 1000);
Felipe Lemecc2a2fa2016-02-25 14:02:44 -08001910 }
1911
Jeff Brown1dc94e32014-09-11 14:15:27 -07001912 /* tell activity manager we're done */
Felipe Leme71bbfc52015-11-23 14:14:51 -08001913 if (do_broadcast) {
Felipe Leme9a523ae2016-10-20 15:10:33 -07001914 if (!ds.path_.empty()) {
1915 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str());
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001916 // clang-format off
Christopher Tatecfaa07a2017-01-23 12:20:21 -08001917
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001918 std::vector<std::string> am_args = {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001919 "--receiver-permission", "android.permission.DUMP",
Felipe Lemee844a9d2016-09-21 15:01:39 -07001920 "--ei", "android.intent.extra.ID", std::to_string(ds.id_),
Felipe Leme75876a22016-10-27 16:31:27 -07001921 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_),
Felipe Leme7447d7c2016-11-03 18:12:22 -07001922 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()),
Felipe Leme9a523ae2016-10-20 15:10:33 -07001923 "--es", "android.intent.extra.BUGREPORT", ds.path_,
1924 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001925 };
Felipe Lemeaabfcae2016-07-29 09:49:04 -07001926 // clang-format on
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001927 if (do_fb) {
1928 am_args.push_back("--es");
1929 am_args.push_back("android.intent.extra.SCREENSHOT");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001930 am_args.push_back(ds.screenshot_path_);
Felipe Leme36b3f6f2015-11-19 15:41:04 -08001931 }
Naveen Kallab53a1c92017-03-16 18:17:25 -07001932 if (!ds.notification_title.empty()) {
1933 am_args.push_back("--es");
1934 am_args.push_back("android.intent.extra.TITLE");
1935 am_args.push_back(ds.notification_title);
1936 if (!ds.notification_description.empty()) {
1937 am_args.push_back("--es");
1938 am_args.push_back("android.intent.extra.DESCRIPTION");
1939 am_args.push_back(ds.notification_description);
1940 }
1941 }
Michal Karpinski4db754f2015-12-11 18:04:32 +00001942 if (is_remote_mode) {
1943 am_args.push_back("--es");
1944 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001945 am_args.push_back(SHA256_file_hash(ds.path_));
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001946 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED",
1947 am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001948 } else {
Felipe Lemea4ef1f02017-02-15 17:27:40 -08001949 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args);
Michal Karpinski4db754f2015-12-11 18:04:32 +00001950 }
Felipe Leme6e01fa62015-11-11 19:35:14 -08001951 } else {
Felipe Lemecbce55d2016-02-08 09:53:18 -08001952 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
Felipe Leme6e01fa62015-11-11 19:35:14 -08001953 }
Jeff Sharkey27f9e6d2013-03-13 15:45:50 -07001954 }
1955
Felipe Leme7447d7c2016-11-03 18:12:22 -07001956 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(),
1957 ds.progress_->GetInitialMax());
1958 ds.progress_->Save();
1959 MYLOGI("done (id %d)\n", ds.id_);
Colin Crossf45fa6b2012-03-26 12:38:26 -07001960
Felipe Leme107a05f2016-03-08 15:11:15 -08001961 if (is_redirecting) {
1962 fclose(stderr);
1963 }
1964
Felipe Leme9a523ae2016-10-20 15:10:33 -07001965 if (use_control_socket && ds.control_socket_fd_ != -1) {
Felipe Lemee844a9d2016-09-21 15:01:39 -07001966 MYLOGD("Closing control socket\n");
Felipe Leme9a523ae2016-10-20 15:10:33 -07001967 close(ds.control_socket_fd_);
Felipe Leme2628e9e2016-04-12 16:36:51 -07001968 }
1969
Colin Crossf45fa6b2012-03-26 12:38:26 -07001970 return 0;
1971}