dumpstate.cpp revision 5f6ee4a11de1de262cea6465c2f991834b2e4792
163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay/* 263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Copyright (C) 2008 The Android Open Source Project 363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * you may not use this file except in compliance with the License. 663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * You may obtain a copy of the License at 763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * 1063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * Unless required by applicable law or agreed to in writing, software 1163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 1263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1363d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * See the License for the specific language governing permissions and 1463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay * limitations under the License. 1563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay */ 1663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 172a32c7e1264b14a20ed900abadea828b804a46ceAurimas Liutikas#define LOG_TAG "dumpstate" 1863d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas#include <dirent.h> 2063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include <errno.h> 2163d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include <fcntl.h> 227fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay#include <libgen.h> 237fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay#include <limits.h> 247fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay#include <stdbool.h> 2583f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <stdio.h> 2683f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <stdlib.h> 2783f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <string.h> 2883f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/poll.h> 2983f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/prctl.h> 3083f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/resource.h> 3183f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/stat.h> 3283f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/time.h> 3383f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <sys/wait.h> 3483f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <unistd.h> 3583f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <memory> 3683f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <regex> 3783f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <set> 3883f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <string> 3983f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <vector> 4083f7464907e288099c0f2d3014d69acf6e571d16Steve McKay 4183f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android-base/file.h> 4283f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android-base/properties.h> 4383f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android-base/stringprintf.h> 4483f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android-base/strings.h> 4583f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android-base/unique_fd.h> 4683f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h> 4783f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <android/hidl/manager/1.0/IServiceManager.h> 4883f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <cutils/native_handle.h> 4983f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <cutils/properties.h> 5083f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <dumpsys.h> 5183f7464907e288099c0f2d3014d69acf6e571d16Steve McKay#include <hidl/ServiceManagement.h> 5263d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include <openssl/sha.h> 537fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay#include <private/android_filesystem_config.h> 5463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include <private/android_logger.h> 5563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include <serviceutils/PriorityDumper.h> 5663d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include "DumpstateInternal.h" 5763d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include "DumpstateSectionReporter.h" 587fb763509e07f98d650efc25c91bff8b1cb239acSteve McKay#include "DumpstateService.h" 5963d2846409d84487d4856d3b8d18cc4684352e29Steve McKay#include "dumpstate.h" 6063d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 6163d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing ::android::hardware::dumpstate::V1_0::IDumpstateDevice; 6263d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing ::std::literals::chrono_literals::operator""ms; 637fb763509e07f98d650efc25c91bff8b1cb239acSteve McKayusing ::std::literals::chrono_literals::operator""s; 6463d2846409d84487d4856d3b8d18cc4684352e29Steve McKay 6563d2846409d84487d4856d3b8d18cc4684352e29Steve McKay// TODO: remove once moved to namespace 6663d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::defaultServiceManager; 6763d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::Dumpsys; 687fb763509e07f98d650efc25c91bff8b1cb239acSteve McKayusing android::INVALID_OPERATION; 6963d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::IServiceManager; 7063d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::OK; 7163d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::sp; 7263d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::status_t; 7363d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::String16; 7463d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::String8; 7563d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::TIMED_OUT; 7663d2846409d84487d4856d3b8d18cc4684352e29Steve McKayusing android::UNKNOWN_ERROR; 77using android::Vector; 78using android::os::dumpstate::CommandOptions; 79using android::os::dumpstate::DumpFileToFd; 80using android::os::dumpstate::DumpstateSectionReporter; 81using android::os::dumpstate::GetPidByName; 82using android::os::dumpstate::PropertiesHelper; 83 84/* read before root is shed */ 85static char cmdline_buf[16384] = "(unknown)"; 86static const char *dump_traces_path = NULL; 87 88// TODO: variables and functions below should be part of dumpstate object 89 90static std::set<std::string> mount_points; 91void add_mountinfo(); 92 93#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" 94#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0" 95#define BLK_DEV_SYS_DIR "/sys/block" 96 97#define RAFT_DIR "/data/misc/raft" 98#define RECOVERY_DIR "/cache/recovery" 99#define RECOVERY_DATA_DIR "/data/misc/recovery" 100#define LOGPERSIST_DATA_DIR "/data/misc/logd" 101#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur" 102#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref" 103#define WLUTIL "/vendor/xbin/wlutil" 104#define WMTRACE_DATA_DIR "/data/misc/wmtrace" 105 106// TODO(narayan): Since this information has to be kept in sync 107// with tombstoned, we should just put it in a common header. 108// 109// File: system/core/debuggerd/tombstoned/tombstoned.cpp 110static const std::string TOMBSTONE_DIR = "/data/tombstones/"; 111static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_"; 112static const std::string ANR_DIR = "/data/anr/"; 113static const std::string ANR_FILE_PREFIX = "anr_"; 114 115// TODO: temporary variables and functions used during C++ refactoring 116static Dumpstate& ds = Dumpstate::GetInstance(); 117static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, 118 const CommandOptions& options = CommandOptions::DEFAULT) { 119 return ds.RunCommand(title, fullCommand, options); 120} 121static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs, 122 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS, 123 long dumpsysTimeoutMs = 0) { 124 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeoutMs); 125} 126static int DumpFile(const std::string& title, const std::string& path) { 127 return ds.DumpFile(title, path); 128} 129 130// Relative directory (inside the zip) for all files copied as-is into the bugreport. 131static const std::string ZIP_ROOT_DIR = "FS"; 132 133// Must be hardcoded because dumpstate HAL implementation need SELinux access to it 134static const std::string kDumpstateBoardPath = "/bugreports/"; 135static const std::string kProtoPath = "proto/"; 136static const std::string kProtoExt = ".proto"; 137static const std::string kDumpstateBoardFiles[] = { 138 "dumpstate_board.txt", 139 "dumpstate_board.bin" 140}; 141static const int NUM_OF_DUMPS = arraysize(kDumpstateBoardFiles); 142 143static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; 144static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; 145static constexpr char PROPERTY_VERSION[] = "dumpstate.version"; 146static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title"; 147static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description"; 148 149static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build(); 150 151/* 152 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|. 153 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime| 154 * is set, the vector only contains files that were written in the last 30 minutes. 155 * If |limit_by_count| is set, the vector only contains the ten latest files. 156 */ 157static std::vector<DumpData> GetDumpFds(const std::string& dir_path, 158 const std::string& file_prefix, 159 bool limit_by_mtime, 160 bool limit_by_count = true) { 161 const time_t thirty_minutes_ago = ds.now_ - 60 * 30; 162 163 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); 164 165 if (dump_dir == nullptr) { 166 MYLOGW("Unable to open directory %s: %s\n", dir_path.c_str(), strerror(errno)); 167 return std::vector<DumpData>(); 168 } 169 170 std::vector<DumpData> dump_data; 171 struct dirent* entry = nullptr; 172 while ((entry = readdir(dump_dir.get()))) { 173 if (entry->d_type != DT_REG) { 174 continue; 175 } 176 177 const std::string base_name(entry->d_name); 178 if (base_name.find(file_prefix) != 0) { 179 continue; 180 } 181 182 const std::string abs_path = dir_path + base_name; 183 android::base::unique_fd fd( 184 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK))); 185 if (fd == -1) { 186 MYLOGW("Unable to open dump file %s: %s\n", abs_path.c_str(), strerror(errno)); 187 break; 188 } 189 190 struct stat st = {}; 191 if (fstat(fd, &st) == -1) { 192 MYLOGW("Unable to stat dump file %s: %s\n", abs_path.c_str(), strerror(errno)); 193 continue; 194 } 195 196 if (limit_by_mtime && st.st_mtime < thirty_minutes_ago) { 197 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str()); 198 continue; 199 } 200 201 dump_data.emplace_back(DumpData{abs_path, std::move(fd), st.st_mtime}); 202 } 203 204 // Sort in descending modification time so that we only keep the newest 205 // reports if |limit_by_count| is true. 206 std::sort(dump_data.begin(), dump_data.end(), 207 [](const DumpData& d1, const DumpData& d2) { return d1.mtime > d2.mtime; }); 208 209 if (limit_by_count && dump_data.size() > 10) { 210 dump_data.erase(dump_data.begin() + 10, dump_data.end()); 211 } 212 213 return dump_data; 214} 215 216static bool AddDumps(const std::vector<DumpData>::const_iterator start, 217 const std::vector<DumpData>::const_iterator end, 218 const char* type_name, const bool add_to_zip) { 219 bool dumped = false; 220 for (auto it = start; it != end; ++it) { 221 const std::string& name = it->name; 222 const int fd = it->fd; 223 dumped = true; 224 225 // Seek to the beginning of the file before dumping any data. A given 226 // DumpData entry might be dumped multiple times in the report. 227 // 228 // For example, the most recent ANR entry is dumped to the body of the 229 // main entry and it also shows up as a separate entry in the bugreport 230 // ZIP file. 231 if (lseek(fd, 0, SEEK_SET) != static_cast<off_t>(0)) { 232 MYLOGE("Unable to add %s to zip file, lseek failed: %s\n", name.c_str(), 233 strerror(errno)); 234 } 235 236 if (ds.IsZipping() && add_to_zip) { 237 if (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd, /* timeout = */ 0ms) != OK) { 238 MYLOGE("Unable to add %s to zip file, addZipEntryFromFd failed\n", name.c_str()); 239 } 240 } else { 241 dump_file_from_fd(type_name, name.c_str(), fd); 242 } 243 } 244 245 return dumped; 246} 247 248// for_each_pid() callback to get mount info about a process. 249void do_mountinfo(int pid, const char* name __attribute__((unused))) { 250 char path[PATH_MAX]; 251 252 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points 253 // are added. 254 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); 255 char linkname[PATH_MAX]; 256 ssize_t r = readlink(path, linkname, PATH_MAX); 257 if (r == -1) { 258 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno)); 259 return; 260 } 261 linkname[r] = '\0'; 262 263 if (mount_points.find(linkname) == mount_points.end()) { 264 // First time this mount point was found: add it 265 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid); 266 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) { 267 mount_points.insert(linkname); 268 } else { 269 MYLOGE("Unable to add mountinfo %s to zip file\n", path); 270 } 271 } 272} 273 274void add_mountinfo() { 275 if (!ds.IsZipping()) return; 276 std::string title = "MOUNT INFO"; 277 mount_points.clear(); 278 DurationReporter duration_reporter(title, true); 279 for_each_pid(do_mountinfo, nullptr); 280 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size()); 281} 282 283static void dump_dev_files(const char *title, const char *driverpath, const char *filename) 284{ 285 DIR *d; 286 struct dirent *de; 287 char path[PATH_MAX]; 288 289 d = opendir(driverpath); 290 if (d == NULL) { 291 return; 292 } 293 294 while ((de = readdir(d))) { 295 if (de->d_type != DT_LNK) { 296 continue; 297 } 298 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename); 299 DumpFile(title, path); 300 } 301 302 closedir(d); 303} 304 305 306 307// dump anrd's trace and add to the zip file. 308// 1. check if anrd is running on this device. 309// 2. send a SIGUSR1 to its pid which will dump anrd's trace. 310// 3. wait until the trace generation completes and add to the zip file. 311static bool dump_anrd_trace() { 312 unsigned int pid; 313 char buf[50], path[PATH_MAX]; 314 struct dirent *trace; 315 struct stat st; 316 DIR *trace_dir; 317 int retry = 5; 318 long max_ctime = 0, old_mtime; 319 long long cur_size = 0; 320 const char *trace_path = "/data/misc/anrd/"; 321 322 if (!ds.IsZipping()) { 323 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n"); 324 return false; 325 } 326 327 // find anrd's pid if it is running. 328 pid = GetPidByName("/system/xbin/anrd"); 329 330 if (pid > 0) { 331 if (stat(trace_path, &st) == 0) { 332 old_mtime = st.st_mtime; 333 } else { 334 MYLOGE("Failed to find: %s\n", trace_path); 335 return false; 336 } 337 338 // send SIGUSR1 to the anrd to generate a trace. 339 sprintf(buf, "%u", pid); 340 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf}, 341 CommandOptions::WithTimeout(1).Build())) { 342 MYLOGE("anrd signal timed out. Please manually collect trace\n"); 343 return false; 344 } 345 346 while (retry-- > 0 && old_mtime == st.st_mtime) { 347 sleep(1); 348 stat(trace_path, &st); 349 } 350 351 if (retry < 0 && old_mtime == st.st_mtime) { 352 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path); 353 return false; 354 } 355 356 // identify the trace file by its creation time. 357 if (!(trace_dir = opendir(trace_path))) { 358 MYLOGE("Can't open trace file under %s\n", trace_path); 359 } 360 while ((trace = readdir(trace_dir))) { 361 if (strcmp(trace->d_name, ".") == 0 362 || strcmp(trace->d_name, "..") == 0) { 363 continue; 364 } 365 sprintf(path, "%s%s", trace_path, trace->d_name); 366 if (stat(path, &st) == 0) { 367 if (st.st_ctime > max_ctime) { 368 max_ctime = st.st_ctime; 369 sprintf(buf, "%s", trace->d_name); 370 } 371 } 372 } 373 closedir(trace_dir); 374 375 // Wait until the dump completes by checking the size of the trace. 376 if (max_ctime > 0) { 377 sprintf(path, "%s%s", trace_path, buf); 378 while(true) { 379 sleep(1); 380 if (stat(path, &st) == 0) { 381 if (st.st_size == cur_size) { 382 break; 383 } else if (st.st_size > cur_size) { 384 cur_size = st.st_size; 385 } else { 386 return false; 387 } 388 } else { 389 MYLOGE("Cant stat() %s anymore\n", path); 390 return false; 391 } 392 } 393 // Add to the zip file. 394 if (!ds.AddZipEntry("anrd_trace.txt", path)) { 395 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path); 396 } else { 397 if (remove(path)) { 398 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno)); 399 } 400 return true; 401 } 402 } else { 403 MYLOGE("Can't stats any trace file under %s\n", trace_path); 404 } 405 } 406 return false; 407} 408 409static void dump_systrace() { 410 if (!ds.IsZipping()) { 411 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n"); 412 return; 413 } 414 std::string systrace_path = ds.GetPath("-systrace.txt"); 415 if (systrace_path.empty()) { 416 MYLOGE("Not dumping systrace because path is empty\n"); 417 return; 418 } 419 const char* path = "/sys/kernel/debug/tracing/tracing_on"; 420 long int is_tracing; 421 if (read_file_as_long(path, &is_tracing)) { 422 return; // error already logged 423 } 424 if (is_tracing <= 0) { 425 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing); 426 return; 427 } 428 429 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes", 430 systrace_path.c_str()); 431 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path}, 432 CommandOptions::WithTimeout(120).Build())) { 433 MYLOGE("systrace timed out, its zip entry will be incomplete\n"); 434 // TODO: RunCommand tries to kill the process, but atrace doesn't die 435 // peacefully; ideally, we should call strace to stop itself, but there is no such option 436 // yet (just a --async_stop, which stops and dump 437 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) { 438 // MYLOGE("could not stop systrace "); 439 // } 440 } 441 if (!ds.AddZipEntry("systrace.txt", systrace_path)) { 442 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str()); 443 } else { 444 if (remove(systrace_path.c_str())) { 445 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno)); 446 } 447 } 448} 449 450static void dump_raft() { 451 if (PropertiesHelper::IsUserBuild()) { 452 return; 453 } 454 455 std::string raft_path = ds.GetPath("-raft_log.txt"); 456 if (raft_path.empty()) { 457 MYLOGD("raft_path is empty\n"); 458 return; 459 } 460 461 struct stat s; 462 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) { 463 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR); 464 return; 465 } 466 467 CommandOptions options = CommandOptions::WithTimeout(600).Build(); 468 if (!ds.IsZipping()) { 469 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport. 470 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options); 471 return; 472 } 473 474 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options); 475 if (!ds.AddZipEntry("raft_log.txt", raft_path)) { 476 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str()); 477 } else { 478 if (remove(raft_path.c_str())) { 479 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno)); 480 } 481 } 482} 483 484static bool skip_not_stat(const char *path) { 485 static const char stat[] = "/stat"; 486 size_t len = strlen(path); 487 if (path[len - 1] == '/') { /* Directory? */ 488 return false; 489 } 490 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ 491} 492 493static bool skip_none(const char* path __attribute__((unused))) { 494 return false; 495} 496 497unsigned long worst_write_perf = 20000; /* in KB/s */ 498 499// 500// stat offsets 501// Name units description 502// ---- ----- ----------- 503// read I/Os requests number of read I/Os processed 504#define __STAT_READ_IOS 0 505// read merges requests number of read I/Os merged with in-queue I/O 506#define __STAT_READ_MERGES 1 507// read sectors sectors number of sectors read 508#define __STAT_READ_SECTORS 2 509// read ticks milliseconds total wait time for read requests 510#define __STAT_READ_TICKS 3 511// write I/Os requests number of write I/Os processed 512#define __STAT_WRITE_IOS 4 513// write merges requests number of write I/Os merged with in-queue I/O 514#define __STAT_WRITE_MERGES 5 515// write sectors sectors number of sectors written 516#define __STAT_WRITE_SECTORS 6 517// write ticks milliseconds total wait time for write requests 518#define __STAT_WRITE_TICKS 7 519// in_flight requests number of I/Os currently in flight 520#define __STAT_IN_FLIGHT 8 521// io_ticks milliseconds total time this block device has been active 522#define __STAT_IO_TICKS 9 523// time_in_queue milliseconds total wait time for all requests 524#define __STAT_IN_QUEUE 10 525#define __STAT_NUMBER_FIELD 11 526// 527// read I/Os, write I/Os 528// ===================== 529// 530// These values increment when an I/O request completes. 531// 532// read merges, write merges 533// ========================= 534// 535// These values increment when an I/O request is merged with an 536// already-queued I/O request. 537// 538// read sectors, write sectors 539// =========================== 540// 541// These values count the number of sectors read from or written to this 542// block device. The "sectors" in question are the standard UNIX 512-byte 543// sectors, not any device- or filesystem-specific block size. The 544// counters are incremented when the I/O completes. 545#define SECTOR_SIZE 512 546// 547// read ticks, write ticks 548// ======================= 549// 550// These values count the number of milliseconds that I/O requests have 551// waited on this block device. If there are multiple I/O requests waiting, 552// these values will increase at a rate greater than 1000/second; for 553// example, if 60 read requests wait for an average of 30 ms, the read_ticks 554// field will increase by 60*30 = 1800. 555// 556// in_flight 557// ========= 558// 559// This value counts the number of I/O requests that have been issued to 560// the device driver but have not yet completed. It does not include I/O 561// requests that are in the queue but not yet issued to the device driver. 562// 563// io_ticks 564// ======== 565// 566// This value counts the number of milliseconds during which the device has 567// had I/O requests queued. 568// 569// time_in_queue 570// ============= 571// 572// This value counts the number of milliseconds that I/O requests have waited 573// on this block device. If there are multiple I/O requests waiting, this 574// value will increase as the product of the number of milliseconds times the 575// number of requests waiting (see "read ticks" above for an example). 576#define S_TO_MS 1000 577// 578 579static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) { 580 unsigned long long fields[__STAT_NUMBER_FIELD]; 581 bool z; 582 char *cp, *buffer = NULL; 583 size_t i = 0; 584 FILE *fp = fdopen(fd, "rb"); 585 getline(&buffer, &i, fp); 586 fclose(fp); 587 if (!buffer) { 588 return -errno; 589 } 590 i = strlen(buffer); 591 while ((i > 0) && (buffer[i - 1] == '\n')) { 592 buffer[--i] = '\0'; 593 } 594 if (!*buffer) { 595 free(buffer); 596 return 0; 597 } 598 z = true; 599 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) { 600 fields[i] = strtoull(cp, &cp, 10); 601 if (fields[i] != 0) { 602 z = false; 603 } 604 } 605 if (z) { /* never accessed */ 606 free(buffer); 607 return 0; 608 } 609 610 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) { 611 path += sizeof(BLK_DEV_SYS_DIR) - 1; 612 } 613 614 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev", 615 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect", 616 "W-wait", "in-fli", "activ", "T-wait", path, buffer); 617 free(buffer); 618 619 if (fields[__STAT_IO_TICKS]) { 620 unsigned long read_perf = 0; 621 unsigned long read_ios = 0; 622 if (fields[__STAT_READ_TICKS]) { 623 unsigned long long divisor = fields[__STAT_READ_TICKS] 624 * fields[__STAT_IO_TICKS]; 625 read_perf = ((unsigned long long)SECTOR_SIZE 626 * fields[__STAT_READ_SECTORS] 627 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 628 / divisor; 629 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS] 630 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 631 / divisor; 632 } 633 634 unsigned long write_perf = 0; 635 unsigned long write_ios = 0; 636 if (fields[__STAT_WRITE_TICKS]) { 637 unsigned long long divisor = fields[__STAT_WRITE_TICKS] 638 * fields[__STAT_IO_TICKS]; 639 write_perf = ((unsigned long long)SECTOR_SIZE 640 * fields[__STAT_WRITE_SECTORS] 641 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 642 / divisor; 643 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS] 644 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 645 / divisor; 646 } 647 648 unsigned queue = (fields[__STAT_IN_QUEUE] 649 + (fields[__STAT_IO_TICKS] >> 1)) 650 / fields[__STAT_IO_TICKS]; 651 652 if (!write_perf && !write_ios) { 653 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue); 654 } else { 655 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf, 656 read_ios, write_perf, write_ios, queue); 657 } 658 659 /* bugreport timeout factor adjustment */ 660 if ((write_perf > 1) && (write_perf < worst_write_perf)) { 661 worst_write_perf = write_perf; 662 } 663 } 664 return 0; 665} 666 667static const long MINIMUM_LOGCAT_TIMEOUT_MS = 50000; 668 669/* timeout in ms to read a list of buffers */ 670static unsigned long logcat_timeout(const std::vector<std::string>& buffers) { 671 unsigned long timeout_ms = 0; 672 for (const auto& buffer : buffers) { 673 log_id_t id = android_name_to_log_id(buffer.c_str()); 674 unsigned long property_size = __android_logger_get_buffer_size(id); 675 /* Engineering margin is ten-fold our guess */ 676 timeout_ms += 10 * (property_size + worst_write_perf) / worst_write_perf; 677 } 678 return timeout_ms > MINIMUM_LOGCAT_TIMEOUT_MS ? timeout_ms : MINIMUM_LOGCAT_TIMEOUT_MS; 679} 680 681void Dumpstate::PrintHeader() const { 682 std::string build, fingerprint, radio, bootloader, network; 683 char date[80]; 684 685 build = android::base::GetProperty("ro.build.display.id", "(unknown)"); 686 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); 687 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); 688 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); 689 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); 690 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_)); 691 692 printf("========================================================\n"); 693 printf("== dumpstate: %s\n", date); 694 printf("========================================================\n"); 695 696 printf("\n"); 697 printf("Build: %s\n", build.c_str()); 698 // NOTE: fingerprint entry format is important for other tools. 699 printf("Build fingerprint: '%s'\n", fingerprint.c_str()); 700 printf("Bootloader: %s\n", bootloader.c_str()); 701 printf("Radio: %s\n", radio.c_str()); 702 printf("Network: %s\n", network.c_str()); 703 704 printf("Kernel: "); 705 DumpFileToFd(STDOUT_FILENO, "", "/proc/version"); 706 printf("Command line: %s\n", strtok(cmdline_buf, "\n")); 707 printf("Uptime: "); 708 RunCommandToFd(STDOUT_FILENO, "", {"uptime", "-p"}, 709 CommandOptions::WithTimeout(1).Always().Build()); 710 printf("Bugreport format version: %s\n", version_.c_str()); 711 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_, 712 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str()); 713 printf("\n"); 714} 715 716// List of file extensions that can cause a zip file attachment to be rejected by some email 717// service providers. 718static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = { 719 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp", 720 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct", 721 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh" 722}; 723 724status_t Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd, 725 std::chrono::milliseconds timeout = 0ms) { 726 if (!IsZipping()) { 727 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n", 728 entry_name.c_str()); 729 return INVALID_OPERATION; 730 } 731 std::string valid_name = entry_name; 732 733 // Rename extension if necessary. 734 size_t idx = entry_name.rfind('.'); 735 if (idx != std::string::npos) { 736 std::string extension = entry_name.substr(idx); 737 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); 738 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) { 739 valid_name = entry_name + ".renamed"; 740 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str()); 741 } 742 } 743 744 // Logging statement below is useful to time how long each entry takes, but it's too verbose. 745 // MYLOGD("Adding zip entry %s\n", entry_name.c_str()); 746 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress, 747 get_mtime(fd, ds.now_)); 748 if (err != 0) { 749 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(), 750 ZipWriter::ErrorCodeString(err)); 751 return UNKNOWN_ERROR; 752 } 753 auto start = std::chrono::steady_clock::now(); 754 auto end = start + timeout; 755 struct pollfd pfd = {fd, POLLIN}; 756 757 std::vector<uint8_t> buffer(65536); 758 while (1) { 759 if (timeout.count() > 0) { 760 // lambda to recalculate the timeout. 761 auto time_left_ms = [end]() { 762 auto now = std::chrono::steady_clock::now(); 763 auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now); 764 return std::max(diff.count(), 0LL); 765 }; 766 767 int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms())); 768 if (rc < 0) { 769 MYLOGE("Error in poll while adding from fd to zip entry %s:%s", entry_name.c_str(), 770 strerror(errno)); 771 return -errno; 772 } else if (rc == 0) { 773 MYLOGE("Timed out adding from fd to zip entry %s:%s Timeout:%lldms", 774 entry_name.c_str(), strerror(errno), timeout.count()); 775 return TIMED_OUT; 776 } 777 } 778 779 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size())); 780 if (bytes_read == 0) { 781 break; 782 } else if (bytes_read == -1) { 783 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno)); 784 return -errno; 785 } 786 err = zip_writer_->WriteBytes(buffer.data(), bytes_read); 787 if (err) { 788 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err)); 789 return UNKNOWN_ERROR; 790 } 791 } 792 793 err = zip_writer_->FinishEntry(); 794 if (err != 0) { 795 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 796 return UNKNOWN_ERROR; 797 } 798 799 return OK; 800} 801 802bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) { 803 android::base::unique_fd fd( 804 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC))); 805 if (fd == -1) { 806 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno)); 807 return false; 808 } 809 810 return (AddZipEntryFromFd(entry_name, fd.get()) == OK); 811} 812 813/* adds a file to the existing zipped bugreport */ 814static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) { 815 return (ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) == OK) ? 0 : 1; 816} 817 818void Dumpstate::AddDir(const std::string& dir, bool recursive) { 819 if (!IsZipping()) { 820 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str()); 821 return; 822 } 823 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive); 824 DurationReporter duration_reporter(dir, true); 825 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd); 826} 827 828bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) { 829 if (!IsZipping()) { 830 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n", 831 entry_name.c_str()); 832 return false; 833 } 834 MYLOGD("Adding zip text entry %s\n", entry_name.c_str()); 835 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_); 836 if (err != 0) { 837 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(), 838 ZipWriter::ErrorCodeString(err)); 839 return false; 840 } 841 842 err = zip_writer_->WriteBytes(content.c_str(), content.length()); 843 if (err != 0) { 844 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(), 845 ZipWriter::ErrorCodeString(err)); 846 return false; 847 } 848 849 err = zip_writer_->FinishEntry(); 850 if (err != 0) { 851 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 852 return false; 853 } 854 855 return true; 856} 857 858static void DoKmsg() { 859 struct stat st; 860 if (!stat(PSTORE_LAST_KMSG, &st)) { 861 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */ 862 DumpFile("LAST KMSG", PSTORE_LAST_KMSG); 863 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) { 864 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG); 865 } else { 866 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ 867 DumpFile("LAST KMSG", "/proc/last_kmsg"); 868 } 869} 870 871static void DoKernelLogcat() { 872 unsigned long timeout_ms = logcat_timeout({"kernel"}); 873 RunCommand( 874 "KERNEL LOG", 875 {"logcat", "-b", "kernel", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"}, 876 CommandOptions::WithTimeoutInMs(timeout_ms).Build()); 877} 878 879static void DoLogcat() { 880 unsigned long timeout_ms; 881 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags"); 882 // calculate timeout 883 timeout_ms = logcat_timeout({"main", "system", "crash"}); 884 RunCommand("SYSTEM LOG", 885 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"}, 886 CommandOptions::WithTimeoutInMs(timeout_ms).Build()); 887 timeout_ms = logcat_timeout({"events"}); 888 RunCommand( 889 "EVENT LOG", 890 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"}, 891 CommandOptions::WithTimeoutInMs(timeout_ms).Build()); 892 timeout_ms = logcat_timeout({"stats"}); 893 RunCommand( 894 "STATS LOG", 895 {"logcat", "-b", "stats", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"}, 896 CommandOptions::WithTimeoutInMs(timeout_ms).Build()); 897 timeout_ms = logcat_timeout({"radio"}); 898 RunCommand( 899 "RADIO LOG", 900 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", "-d", "*:v"}, 901 CommandOptions::WithTimeoutInMs(timeout_ms).Build()); 902 903 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"}); 904 905 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */ 906 RunCommand("LAST LOGCAT", {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", 907 "-v", "uid", "-d", "*:v"}); 908} 909 910static void DumpIpTablesAsRoot() { 911 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"}); 912 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"}); 913 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"}); 914 /* no ip6 nat */ 915 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"}); 916 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"}); 917 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"}); 918 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); 919} 920 921static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file, 922 const std::string& anr_traces_dir) { 923 std::string dump_traces_dir; 924 925 if (dump_traces_path != nullptr) { 926 if (add_to_zip) { 927 dump_traces_dir = dirname(dump_traces_path); 928 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str()); 929 ds.AddDir(dump_traces_dir, true); 930 } else { 931 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n", 932 dump_traces_path); 933 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path); 934 } 935 } 936 937 938 // Make sure directory is not added twice. 939 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is 940 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system 941 // property - but in reality they're the same path (although the former could be nullptr). 942 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should 943 // be revisited. 944 bool already_dumped = anr_traces_dir == dump_traces_dir; 945 946 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n", 947 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped); 948 949 android::base::unique_fd fd(TEMP_FAILURE_RETRY( 950 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK))); 951 if (fd.get() < 0) { 952 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno)); 953 } else { 954 if (add_to_zip) { 955 if (!already_dumped) { 956 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n", 957 anr_traces_dir.c_str()); 958 ds.AddDir(anr_traces_dir, true); 959 } 960 } else { 961 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n", 962 anr_traces_file.c_str()); 963 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd.get()); 964 } 965 } 966} 967 968static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) { 969 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path, 970 anr_traces_dir.c_str()); 971 972 // If we're here, dump_traces_path will always be a temporary file 973 // (created with mkostemp or similar) that contains dumps taken earlier 974 // on in the process. 975 if (dump_traces_path != nullptr) { 976 if (add_to_zip) { 977 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path); 978 } else { 979 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n", 980 dump_traces_path); 981 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path); 982 } 983 984 const int ret = unlink(dump_traces_path); 985 if (ret == -1) { 986 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path, 987 strerror(errno)); 988 } 989 } 990 991 // Add a specific message for the first ANR Dump. 992 if (ds.anr_data_.size() > 0) { 993 AddDumps(ds.anr_data_.begin(), ds.anr_data_.begin() + 1, 994 "VM TRACES AT LAST ANR", add_to_zip); 995 996 // The "last" ANR will always be included as separate entry in the zip file. In addition, 997 // it will be present in the body of the main entry if |add_to_zip| == false. 998 // 999 // Historical ANRs are always included as separate entries in the bugreport zip file. 1000 AddDumps(ds.anr_data_.begin() + ((add_to_zip) ? 1 : 0), ds.anr_data_.end(), 1001 "HISTORICAL ANR", true /* add_to_zip */); 1002 } else { 1003 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); 1004 } 1005} 1006 1007static void AddAnrTraceFiles() { 1008 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR; 1009 1010 std::string anr_traces_file; 1011 std::string anr_traces_dir; 1012 bool is_global_trace_file = true; 1013 1014 // First check whether the stack-trace-dir property is set. When it's set, 1015 // each ANR trace will be written to a separate file and not to a global 1016 // stack trace file. 1017 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", ""); 1018 if (anr_traces_dir.empty()) { 1019 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", ""); 1020 if (!anr_traces_file.empty()) { 1021 anr_traces_dir = dirname(anr_traces_file.c_str()); 1022 } 1023 } else { 1024 is_global_trace_file = false; 1025 } 1026 1027 // We have neither configured a global trace file nor a trace directory, 1028 // there will be nothing to dump. 1029 if (anr_traces_file.empty() && anr_traces_dir.empty()) { 1030 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); 1031 return; 1032 } 1033 1034 if (is_global_trace_file) { 1035 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir); 1036 } else { 1037 AddAnrTraceDir(add_to_zip, anr_traces_dir); 1038 } 1039 1040 /* slow traces for slow operations */ 1041 struct stat st; 1042 if (!anr_traces_dir.empty()) { 1043 int i = 0; 1044 while (true) { 1045 const std::string slow_trace_path = 1046 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i); 1047 if (stat(slow_trace_path.c_str(), &st)) { 1048 // No traces file at this index, done with the files. 1049 break; 1050 } 1051 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str()); 1052 i++; 1053 } 1054 } 1055} 1056 1057static void DumpBlockStatFiles() { 1058 DurationReporter duration_reporter("DUMP BLOCK STAT"); 1059 1060 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir); 1061 1062 if (dirptr == nullptr) { 1063 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno)); 1064 return; 1065 } 1066 1067 printf("------ DUMP BLOCK STAT ------\n\n"); 1068 while (struct dirent *d = readdir(dirptr.get())) { 1069 if ((d->d_name[0] == '.') 1070 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0')) 1071 || (d->d_name[1] == '\0'))) { 1072 continue; 1073 } 1074 const std::string new_path = 1075 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name); 1076 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str()); 1077 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd); 1078 printf("\n"); 1079 } 1080 return; 1081} 1082 1083static void DumpPacketStats() { 1084 DumpFile("NETWORK DEV INFO", "/proc/net/dev"); 1085 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all"); 1086 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt"); 1087 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl"); 1088 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats"); 1089} 1090 1091static void DumpIpAddrAndRules() { 1092 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */ 1093 RunCommand("NETWORK INTERFACES", {"ip", "link"}); 1094 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"}); 1095 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"}); 1096 RunCommand("IP RULES", {"ip", "rule", "show"}); 1097 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"}); 1098} 1099 1100static void RunDumpsysTextByPriority(const std::string& title, int priority, 1101 std::chrono::milliseconds timeout, 1102 std::chrono::milliseconds service_timeout) { 1103 auto start = std::chrono::steady_clock::now(); 1104 sp<android::IServiceManager> sm = defaultServiceManager(); 1105 Dumpsys dumpsys(sm.get()); 1106 Vector<String16> args; 1107 Dumpsys::setServiceArgs(args, /* asProto = */ false, priority); 1108 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ false); 1109 for (const String16& service : services) { 1110 std::string path(title); 1111 path.append(" - ").append(String8(service).c_str()); 1112 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_); 1113 size_t bytes_written = 0; 1114 status_t status = dumpsys.startDumpThread(service, args); 1115 if (status == OK) { 1116 dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority); 1117 std::chrono::duration<double> elapsed_seconds; 1118 status = dumpsys.writeDump(STDOUT_FILENO, service, service_timeout, 1119 /* as_proto = */ false, elapsed_seconds, bytes_written); 1120 section_reporter.setSize(bytes_written); 1121 dumpsys.writeDumpFooter(STDOUT_FILENO, service, elapsed_seconds); 1122 bool dump_complete = (status == OK); 1123 dumpsys.stopDumpThread(dump_complete); 1124 } 1125 section_reporter.setStatus(status); 1126 1127 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>( 1128 std::chrono::steady_clock::now() - start); 1129 if (elapsed_duration > timeout) { 1130 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(), 1131 elapsed_duration.count()); 1132 break; 1133 } 1134 } 1135} 1136 1137static void RunDumpsysText(const std::string& title, int priority, 1138 std::chrono::milliseconds timeout, 1139 std::chrono::milliseconds service_timeout) { 1140 DurationReporter duration_reporter(title); 1141 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str()); 1142 fsync(STDOUT_FILENO); 1143 RunDumpsysTextByPriority(title, priority, timeout, service_timeout); 1144} 1145 1146/* Dump all services registered with Normal or Default priority. */ 1147static void RunDumpsysTextNormalPriority(const std::string& title, 1148 std::chrono::milliseconds timeout, 1149 std::chrono::milliseconds service_timeout) { 1150 DurationReporter duration_reporter(title); 1151 dprintf(STDOUT_FILENO, "------ %s (/system/bin/dumpsys) ------\n", title.c_str()); 1152 fsync(STDOUT_FILENO); 1153 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, timeout, 1154 service_timeout); 1155 RunDumpsysTextByPriority(title, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT, timeout, 1156 service_timeout); 1157} 1158 1159static void RunDumpsysProto(const std::string& title, int priority, 1160 std::chrono::milliseconds timeout, 1161 std::chrono::milliseconds service_timeout) { 1162 sp<android::IServiceManager> sm = defaultServiceManager(); 1163 Dumpsys dumpsys(sm.get()); 1164 Vector<String16> args; 1165 Dumpsys::setServiceArgs(args, /* asProto = */ true, priority); 1166 DurationReporter duration_reporter(title); 1167 1168 auto start = std::chrono::steady_clock::now(); 1169 Vector<String16> services = dumpsys.listServices(priority, /* supports_proto = */ true); 1170 for (const String16& service : services) { 1171 std::string path(kProtoPath); 1172 path.append(String8(service).c_str()); 1173 if (priority == IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL) { 1174 path.append("_CRITICAL"); 1175 } else if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH) { 1176 path.append("_HIGH"); 1177 } 1178 path.append(kProtoExt); 1179 DumpstateSectionReporter section_reporter(path, ds.listener_, ds.report_section_); 1180 status_t status = dumpsys.startDumpThread(service, args); 1181 if (status == OK) { 1182 status = ds.AddZipEntryFromFd(path, dumpsys.getDumpFd(), service_timeout); 1183 bool dumpTerminated = (status == OK); 1184 dumpsys.stopDumpThread(dumpTerminated); 1185 } 1186 ZipWriter::FileEntry file_entry; 1187 ds.zip_writer_->GetLastEntry(&file_entry); 1188 section_reporter.setSize(file_entry.compressed_size); 1189 section_reporter.setStatus(status); 1190 1191 auto elapsed_duration = std::chrono::duration_cast<std::chrono::milliseconds>( 1192 std::chrono::steady_clock::now() - start); 1193 if (elapsed_duration > timeout) { 1194 MYLOGE("*** command '%s' timed out after %llums\n", title.c_str(), 1195 elapsed_duration.count()); 1196 break; 1197 } 1198 } 1199} 1200 1201// Runs dumpsys on services that must dump first and and will take less than 100ms to dump. 1202static void RunDumpsysCritical() { 1203 RunDumpsysText("DUMPSYS CRITICAL", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, 1204 /* timeout= */ 5s, /* service_timeout= */ 500ms); 1205 RunDumpsysProto("DUMPSYS CRITICAL PROTO", IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL, 1206 /* timeout= */ 5s, /* service_timeout= */ 500ms); 1207} 1208 1209// Runs dumpsys on services that must dump first but can take up to 250ms to dump. 1210static void RunDumpsysHigh() { 1211 // TODO meminfo takes ~10s, connectivity takes ~5sec to dump. They are both 1212 // high priority. Reduce timeout once they are able to dump in a shorter time or 1213 // moved to a parallel task. 1214 RunDumpsysText("DUMPSYS HIGH", IServiceManager::DUMP_FLAG_PRIORITY_HIGH, 1215 /* timeout= */ 90s, /* service_timeout= */ 30s); 1216 RunDumpsysProto("DUMPSYS HIGH PROTO", IServiceManager::DUMP_FLAG_PRIORITY_HIGH, 1217 /* timeout= */ 5s, /* service_timeout= */ 1s); 1218} 1219 1220// Runs dumpsys on services that must dump but can take up to 10s to dump. 1221static void RunDumpsysNormal() { 1222 RunDumpsysTextNormalPriority("DUMPSYS", /* timeout= */ 90s, /* service_timeout= */ 10s); 1223 RunDumpsysProto("DUMPSYS PROTO", IServiceManager::DUMP_FLAG_PRIORITY_NORMAL, 1224 /* timeout= */ 90s, /* service_timeout= */ 10s); 1225} 1226 1227static void DumpHals() { 1228 using android::sp; 1229 using android::hidl::manager::V1_0::IServiceManager; 1230 using android::hardware::defaultServiceManager; 1231 1232 sp<IServiceManager> sm = defaultServiceManager(); 1233 if (sm == nullptr) { 1234 MYLOGE("Could not retrieve hwservicemanager to dump hals.\n"); 1235 return; 1236 } 1237 1238 auto ret = sm->list([&](const auto& interfaces) { 1239 for (const std::string& interface : interfaces) { 1240 std::string cleanName = interface; 1241 std::replace_if(cleanName.begin(), 1242 cleanName.end(), 1243 [](char c) { 1244 return !isalnum(c) && 1245 std::string("@-_:.").find(c) == std::string::npos; 1246 }, '_'); 1247 const std::string path = kDumpstateBoardPath + "lshal_debug_" + cleanName; 1248 1249 { 1250 auto fd = android::base::unique_fd( 1251 TEMP_FAILURE_RETRY(open(path.c_str(), 1252 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 1253 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); 1254 if (fd < 0) { 1255 MYLOGE("Could not open %s to dump additional hal information.\n", path.c_str()); 1256 continue; 1257 } 1258 RunCommandToFd(fd, 1259 "", 1260 {"lshal", "debug", "-E", interface}, 1261 CommandOptions::WithTimeout(2).AsRootIfAvailable().Build()); 1262 1263 bool empty = 0 == lseek(fd, 0, SEEK_END); 1264 if (!empty) { 1265 ds.AddZipEntry("lshal-debug/" + cleanName + ".txt", path); 1266 } 1267 } 1268 1269 unlink(path.c_str()); 1270 } 1271 }); 1272 1273 if (!ret.isOk()) { 1274 MYLOGE("Could not list hals from hwservicemanager.\n"); 1275 } 1276} 1277 1278static void dumpstate() { 1279 DurationReporter duration_reporter("DUMPSTATE"); 1280 1281 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); 1282 RunCommand("UPTIME", {"uptime"}); 1283 DumpBlockStatFiles(); 1284 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd"); 1285 DumpFile("MEMORY INFO", "/proc/meminfo"); 1286 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o", 1287 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"}); 1288 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20); 1289 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat"); 1290 DumpFile("VMALLOC INFO", "/proc/vmallocinfo"); 1291 DumpFile("SLAB INFO", "/proc/slabinfo"); 1292 DumpFile("ZONEINFO", "/proc/zoneinfo"); 1293 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo"); 1294 DumpFile("BUDDYINFO", "/proc/buddyinfo"); 1295 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index"); 1296 1297 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources"); 1298 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); 1299 DumpFile("KERNEL SYNC", "/d/sync"); 1300 1301 RunCommand("PROCESSES AND THREADS", 1302 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy,time"}); 1303 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT); 1304 1305 if (ds.IsZipping()) { 1306 RunCommand("HARDWARE HALS", {"lshal"}, CommandOptions::WithTimeout(2).AsRootIfAvailable().Build()); 1307 DumpHals(); 1308 } else { 1309 RunCommand("HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::WithTimeout(10).AsRootIfAvailable().Build()); 1310 } 1311 1312 RunCommand("PRINTENV", {"printenv"}); 1313 RunCommand("NETSTAT", {"netstat", "-nW"}); 1314 struct stat s; 1315 if (stat("/proc/modules", &s) != 0) { 1316 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n"); 1317 } else { 1318 RunCommand("LSMOD", {"lsmod"}); 1319 } 1320 1321 if (__android_logger_property_get_bool( 1322 "ro.logd.kernel", BOOL_DEFAULT_TRUE | BOOL_DEFAULT_FLAG_ENG | BOOL_DEFAULT_FLAG_SVELTE)) { 1323 DoKernelLogcat(); 1324 } else { 1325 do_dmesg(); 1326 } 1327 1328 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT); 1329 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES"); 1330 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); 1331 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); 1332 1333 /* Dump Bluetooth HCI logs */ 1334 ds.AddDir("/data/misc/bluetooth/logs", true); 1335 1336 if (!ds.do_early_screenshot_) { 1337 MYLOGI("taking late screenshot\n"); 1338 ds.TakeScreenshot(); 1339 } 1340 1341 DoLogcat(); 1342 1343 AddAnrTraceFiles(); 1344 1345 // NOTE: tombstones are always added as separate entries in the zip archive 1346 // and are not interspersed with the main report. 1347 const bool tombstones_dumped = AddDumps(ds.tombstone_data_.begin(), ds.tombstone_data_.end(), 1348 "TOMBSTONE", true /* add_to_zip */); 1349 if (!tombstones_dumped) { 1350 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); 1351 } 1352 1353 DumpPacketStats(); 1354 1355 DoKmsg(); 1356 1357 DumpIpAddrAndRules(); 1358 1359 dump_route_tables(); 1360 1361 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"}); 1362 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"}); 1363 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"}); 1364 1365 RunDumpsysHigh(); 1366 1367 RunCommand("SYSTEM PROPERTIES", {"getprop"}); 1368 1369 RunCommand("STORAGED IO INFO", {"storaged", "-u", "-p"}); 1370 1371 RunCommand("FILESYSTEMS & FREE SPACE", {"df"}); 1372 1373 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"}); 1374 1375 /* Binder state is expensive to look at as it uses a lot of memory. */ 1376 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log"); 1377 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log"); 1378 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions"); 1379 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats"); 1380 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state"); 1381 1382 /* Add window and surface trace files. */ 1383 if (!PropertiesHelper::IsUserBuild()) { 1384 ds.AddDir(WMTRACE_DATA_DIR, false); 1385 } 1386 1387 ds.DumpstateBoard(); 1388 1389 /* Migrate the ril_dumpstate to a device specific dumpstate? */ 1390 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0); 1391 if (rilDumpstateTimeout > 0) { 1392 // su does not exist on user builds, so try running without it. 1393 // This way any implementations of vril-dump that do not require 1394 // root can run on user builds. 1395 CommandOptions::CommandOptionsBuilder options = 1396 CommandOptions::WithTimeout(rilDumpstateTimeout); 1397 if (!PropertiesHelper::IsUserBuild()) { 1398 options.AsRoot(); 1399 } 1400 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build()); 1401 } 1402 1403 printf("========================================================\n"); 1404 printf("== Android Framework Services\n"); 1405 printf("========================================================\n"); 1406 1407 RunDumpsysNormal(); 1408 1409 printf("========================================================\n"); 1410 printf("== Checkins\n"); 1411 printf("========================================================\n"); 1412 1413 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}); 1414 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}); 1415 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}); 1416 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}); 1417 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}); 1418 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}); 1419 1420 printf("========================================================\n"); 1421 printf("== Running Application Activities\n"); 1422 printf("========================================================\n"); 1423 1424 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}); 1425 1426 printf("========================================================\n"); 1427 printf("== Running Application Services\n"); 1428 printf("========================================================\n"); 1429 1430 RunDumpsys("APP SERVICES", {"activity", "service", "all"}); 1431 1432 printf("========================================================\n"); 1433 printf("== Running Application Providers\n"); 1434 printf("========================================================\n"); 1435 1436 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"}); 1437 1438 printf("========================================================\n"); 1439 printf("== Dropbox crashes\n"); 1440 printf("========================================================\n"); 1441 1442 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"}); 1443 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"}); 1444 1445 printf("========================================================\n"); 1446 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(), 1447 ds.progress_->GetMax(), ds.progress_->GetInitialMax()); 1448 printf("========================================================\n"); 1449 printf("== dumpstate: done (id %d)\n", ds.id_); 1450 printf("========================================================\n"); 1451} 1452 1453// This method collects common dumpsys for telephony and wifi 1454static void DumpstateRadioCommon() { 1455 DumpIpTablesAsRoot(); 1456 1457 if (!DropRootUser()) { 1458 return; 1459 } 1460 1461 do_dmesg(); 1462 DoLogcat(); 1463 DumpPacketStats(); 1464 DoKmsg(); 1465 DumpIpAddrAndRules(); 1466 dump_route_tables(); 1467 1468 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"}, 1469 CommandOptions::WithTimeout(10).Build()); 1470} 1471 1472// This method collects dumpsys for telephony debugging only 1473static void DumpstateTelephonyOnly() { 1474 DurationReporter duration_reporter("DUMPSTATE"); 1475 1476 DumpstateRadioCommon(); 1477 1478 RunCommand("SYSTEM PROPERTIES", {"getprop"}); 1479 1480 printf("========================================================\n"); 1481 printf("== Android Framework Services\n"); 1482 printf("========================================================\n"); 1483 1484 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 1485 SEC_TO_MSEC(10)); 1486 RunDumpsys("DUMPSYS", {"carrier_config"}, CommandOptions::WithTimeout(90).Build(), 1487 SEC_TO_MSEC(10)); 1488 1489 printf("========================================================\n"); 1490 printf("== Running Application Services\n"); 1491 printf("========================================================\n"); 1492 1493 RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"}); 1494 1495 printf("========================================================\n"); 1496 printf("== Checkins\n"); 1497 printf("========================================================\n"); 1498 1499 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}); 1500 1501 printf("========================================================\n"); 1502 printf("== dumpstate: done (id %d)\n", ds.id_); 1503 printf("========================================================\n"); 1504} 1505 1506// This method collects dumpsys for wifi debugging only 1507static void DumpstateWifiOnly() { 1508 DurationReporter duration_reporter("DUMPSTATE"); 1509 1510 DumpstateRadioCommon(); 1511 1512 printf("========================================================\n"); 1513 printf("== Android Framework Services\n"); 1514 printf("========================================================\n"); 1515 1516 RunDumpsys("DUMPSYS", {"connectivity"}, CommandOptions::WithTimeout(90).Build(), 1517 SEC_TO_MSEC(10)); 1518 RunDumpsys("DUMPSYS", {"wifi"}, CommandOptions::WithTimeout(90).Build(), 1519 SEC_TO_MSEC(10)); 1520 1521 printf("========================================================\n"); 1522 printf("== dumpstate: done (id %d)\n", ds.id_); 1523 printf("========================================================\n"); 1524} 1525 1526void Dumpstate::DumpstateBoard() { 1527 DurationReporter duration_reporter("dumpstate_board()"); 1528 printf("========================================================\n"); 1529 printf("== Board\n"); 1530 printf("========================================================\n"); 1531 1532 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); 1533 if (dumpstate_device == nullptr) { 1534 MYLOGE("No IDumpstateDevice implementation\n"); 1535 return; 1536 } 1537 1538 if (!IsZipping()) { 1539 MYLOGD("Not dumping board info because it's not a zipped bugreport\n"); 1540 return; 1541 } 1542 1543 std::string path[NUM_OF_DUMPS]; 1544 android::base::unique_fd fd[NUM_OF_DUMPS]; 1545 int numFds = 0; 1546 1547 for (int i = 0; i < NUM_OF_DUMPS; i++) { 1548 path[i] = kDumpstateBoardPath + kDumpstateBoardFiles[i]; 1549 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path[i].c_str()); 1550 1551 fd[i] = android::base::unique_fd( 1552 TEMP_FAILURE_RETRY(open(path[i].c_str(), 1553 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 1554 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))); 1555 if (fd[i] < 0) { 1556 MYLOGE("Could not open file %s: %s\n", path[i].c_str(), strerror(errno)); 1557 return; 1558 } else { 1559 numFds++; 1560 } 1561 } 1562 1563 native_handle_t *handle = native_handle_create(numFds, 0); 1564 if (handle == nullptr) { 1565 MYLOGE("Could not create native_handle\n"); 1566 return; 1567 } 1568 1569 for (int i = 0; i < numFds; i++) { 1570 handle->data[i] = fd[i].release(); 1571 } 1572 1573 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call. 1574 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle); 1575 if (!status.isOk()) { 1576 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str()); 1577 native_handle_close(handle); 1578 native_handle_delete(handle); 1579 return; 1580 } 1581 1582 for (int i = 0; i < numFds; i++) { 1583 struct stat s; 1584 if (fstat(handle->data[i], &s) == -1) { 1585 MYLOGE("Failed to fstat %s: %d\n", kDumpstateBoardFiles[i].c_str(), errno); 1586 } else if (s.st_size > 0) { 1587 AddZipEntry(kDumpstateBoardFiles[i], path[i]); 1588 } else { 1589 MYLOGE("Ignoring empty %s\n", kDumpstateBoardFiles[i].c_str()); 1590 } 1591 } 1592 1593 printf("*** See dumpstate-board.txt entry ***\n"); 1594 1595 native_handle_close(handle); 1596 native_handle_delete(handle); 1597 1598 for (int i = 0; i < numFds; i++) { 1599 if (remove(path[i].c_str()) != 0) { 1600 MYLOGE("Could not remove(%s): %s\n", path[i].c_str(), strerror(errno)); 1601 } 1602 } 1603} 1604 1605static void ShowUsageAndExit(int exitCode = 1) { 1606 fprintf(stderr, 1607 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] " 1608 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n" 1609 " -h: display this help message\n" 1610 " -b: play sound file instead of vibrate, at beginning of job\n" 1611 " -e: play sound file instead of vibrate, at end of job\n" 1612 " -o: write to file (instead of stdout)\n" 1613 " -d: append date to filename (requires -o)\n" 1614 " -p: capture screenshot to filename.png (requires -o)\n" 1615 " -z: generate zipped file (requires -o)\n" 1616 " -s: write output to control socket (for init)\n" 1617 " -S: write file location to control socket (for init; requires -o and -z)\n" 1618 " -q: disable vibrate\n" 1619 " -B: send broadcast when finished (requires -o)\n" 1620 " -P: send broadcast when started and update system properties on " 1621 "progress (requires -o and -B)\n" 1622 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " 1623 "shouldn't be used with -P)\n" 1624 " -v: prints the dumpstate header and exit\n"); 1625 exit(exitCode); 1626} 1627 1628static void ExitOnInvalidArgs() { 1629 fprintf(stderr, "invalid combination of args\n"); 1630 ShowUsageAndExit(); 1631} 1632 1633static void sig_handler(int) { 1634 _exit(EXIT_FAILURE); 1635} 1636 1637static void register_sig_handler() { 1638 struct sigaction sa; 1639 sigemptyset(&sa.sa_mask); 1640 sa.sa_flags = 0; 1641 sa.sa_handler = sig_handler; 1642 sigaction(SIGPIPE, &sa, NULL); // broken pipe 1643 sigaction(SIGSEGV, &sa, NULL); // segment fault 1644 sigaction(SIGINT, &sa, NULL); // ctrl-c 1645 sigaction(SIGTERM, &sa, NULL); // killed 1646 sigaction(SIGQUIT, &sa, NULL); // quit 1647} 1648 1649bool Dumpstate::FinishZipFile() { 1650 std::string entry_name = base_name_ + "-" + name_ + ".txt"; 1651 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(), 1652 tmp_path_.c_str()); 1653 // Final timestamp 1654 char date[80]; 1655 time_t the_real_now_please_stand_up = time(nullptr); 1656 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up)); 1657 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date, 1658 the_real_now_please_stand_up - ds.now_); 1659 1660 if (!ds.AddZipEntry(entry_name, tmp_path_)) { 1661 MYLOGE("Failed to add text entry to .zip file\n"); 1662 return false; 1663 } 1664 if (!AddTextZipEntry("main_entry.txt", entry_name)) { 1665 MYLOGE("Failed to add main_entry.txt to .zip file\n"); 1666 return false; 1667 } 1668 1669 // Add log file (which contains stderr output) to zip... 1670 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n"); 1671 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) { 1672 MYLOGE("Failed to add dumpstate log to .zip file\n"); 1673 return false; 1674 } 1675 // ... and re-opens it for further logging. 1676 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str())); 1677 fprintf(stderr, "\n"); 1678 1679 int32_t err = zip_writer_->Finish(); 1680 if (err != 0) { 1681 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err)); 1682 return false; 1683 } 1684 1685 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor. 1686 ds.zip_file.reset(nullptr); 1687 1688 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str()) 1689 if (remove(tmp_path_.c_str()) != 0) { 1690 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno)); 1691 } 1692 1693 return true; 1694} 1695 1696static std::string SHA256_file_hash(const std::string& filepath) { 1697 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK 1698 | O_CLOEXEC | O_NOFOLLOW))); 1699 if (fd == -1) { 1700 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno)); 1701 return NULL; 1702 } 1703 1704 SHA256_CTX ctx; 1705 SHA256_Init(&ctx); 1706 1707 std::vector<uint8_t> buffer(65536); 1708 while (1) { 1709 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size())); 1710 if (bytes_read == 0) { 1711 break; 1712 } else if (bytes_read == -1) { 1713 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno)); 1714 return NULL; 1715 } 1716 1717 SHA256_Update(&ctx, buffer.data(), bytes_read); 1718 } 1719 1720 uint8_t hash[SHA256_DIGEST_LENGTH]; 1721 SHA256_Final(hash, &ctx); 1722 1723 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1]; 1724 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) { 1725 sprintf(hash_buffer + (i * 2), "%02x", hash[i]); 1726 } 1727 hash_buffer[sizeof(hash_buffer) - 1] = 0; 1728 return std::string(hash_buffer); 1729} 1730 1731static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) { 1732 // clang-format off 1733 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0", 1734 "--receiver-foreground", "--receiver-include-background", "-a", action}; 1735 // clang-format on 1736 1737 am.insert(am.end(), args.begin(), args.end()); 1738 1739 RunCommand("", am, 1740 CommandOptions::WithTimeout(20) 1741 .Log("Sending broadcast: '%s'\n") 1742 .Always() 1743 .DropRoot() 1744 .RedirectStderr() 1745 .Build()); 1746} 1747 1748static void Vibrate(int duration_ms) { 1749 // clang-format off 1750 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"}, 1751 CommandOptions::WithTimeout(10) 1752 .Log("Vibrate: '%s'\n") 1753 .Always() 1754 .Build()); 1755 // clang-format on 1756} 1757 1758/** Main entry point for dumpstate. */ 1759int run_main(int argc, char* argv[]) { 1760 int do_add_date = 0; 1761 int do_zip_file = 0; 1762 int do_vibrate = 1; 1763 char* use_outfile = 0; 1764 int use_socket = 0; 1765 int use_control_socket = 0; 1766 int do_fb = 0; 1767 int do_broadcast = 0; 1768 int is_remote_mode = 0; 1769 bool show_header_only = false; 1770 bool do_start_service = false; 1771 bool telephony_only = false; 1772 bool wifi_only = false; 1773 int dup_stdout_fd; 1774 int dup_stderr_fd; 1775 1776 /* set as high priority, and protect from OOM killer */ 1777 setpriority(PRIO_PROCESS, 0, -20); 1778 1779 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we"); 1780 if (oom_adj) { 1781 fputs("-1000", oom_adj); 1782 fclose(oom_adj); 1783 } else { 1784 /* fallback to kernels <= 2.6.35 */ 1785 oom_adj = fopen("/proc/self/oom_adj", "we"); 1786 if (oom_adj) { 1787 fputs("-17", oom_adj); 1788 fclose(oom_adj); 1789 } 1790 } 1791 1792 /* parse arguments */ 1793 int c; 1794 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) { 1795 switch (c) { 1796 // clang-format off 1797 case 'd': do_add_date = 1; break; 1798 case 'z': do_zip_file = 1; break; 1799 case 'o': use_outfile = optarg; break; 1800 case 's': use_socket = 1; break; 1801 case 'S': use_control_socket = 1; break; 1802 case 'v': show_header_only = true; break; 1803 case 'q': do_vibrate = 0; break; 1804 case 'p': do_fb = 1; break; 1805 case 'P': ds.update_progress_ = true; break; 1806 case 'R': is_remote_mode = 1; break; 1807 case 'B': do_broadcast = 1; break; 1808 case 'V': break; // compatibility no-op 1809 case 'h': 1810 ShowUsageAndExit(0); 1811 break; 1812 default: 1813 fprintf(stderr, "Invalid option: %c\n", c); 1814 ShowUsageAndExit(); 1815 // clang-format on 1816 } 1817 } 1818 1819 // TODO: use helper function to convert argv into a string 1820 for (int i = 0; i < argc; i++) { 1821 ds.args_ += argv[i]; 1822 if (i < argc - 1) { 1823 ds.args_ += " "; 1824 } 1825 } 1826 1827 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); 1828 if (!ds.extra_options_.empty()) { 1829 // Framework uses a system property to override some command-line args. 1830 // Currently, it contains the type of the requested bugreport. 1831 if (ds.extra_options_ == "bugreportplus") { 1832 // Currently, the dumpstate binder is only used by Shell to update progress. 1833 do_start_service = true; 1834 ds.update_progress_ = true; 1835 do_fb = 0; 1836 } else if (ds.extra_options_ == "bugreportremote") { 1837 do_vibrate = 0; 1838 is_remote_mode = 1; 1839 do_fb = 0; 1840 } else if (ds.extra_options_ == "bugreportwear") { 1841 do_start_service = true; 1842 ds.update_progress_ = true; 1843 do_zip_file = 1; 1844 } else if (ds.extra_options_ == "bugreporttelephony") { 1845 telephony_only = true; 1846 } else if (ds.extra_options_ == "bugreportwifi") { 1847 wifi_only = true; 1848 do_zip_file = 1; 1849 } else { 1850 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str()); 1851 } 1852 // Reset the property 1853 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, ""); 1854 } 1855 1856 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, ""); 1857 if (!ds.notification_title.empty()) { 1858 // Reset the property 1859 android::base::SetProperty(PROPERTY_EXTRA_TITLE, ""); 1860 1861 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); 1862 if (!ds.notification_description.empty()) { 1863 // Reset the property 1864 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); 1865 } 1866 MYLOGD("notification (title: %s, description: %s)\n", 1867 ds.notification_title.c_str(), ds.notification_description.c_str()); 1868 } 1869 1870 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) { 1871 ExitOnInvalidArgs(); 1872 } 1873 1874 if (use_control_socket && !do_zip_file) { 1875 ExitOnInvalidArgs(); 1876 } 1877 1878 if (ds.update_progress_ && !do_broadcast) { 1879 ExitOnInvalidArgs(); 1880 } 1881 1882 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) { 1883 ExitOnInvalidArgs(); 1884 } 1885 1886 if (ds.version_ == VERSION_DEFAULT) { 1887 ds.version_ = VERSION_CURRENT; 1888 } 1889 1890 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) { 1891 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n", 1892 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(), 1893 VERSION_SPLIT_ANR.c_str()); 1894 exit(1); 1895 } 1896 1897 if (show_header_only) { 1898 ds.PrintHeader(); 1899 exit(0); 1900 } 1901 1902 /* redirect output if needed */ 1903 bool is_redirecting = !use_socket && use_outfile; 1904 1905 // TODO: temporarily set progress until it's part of the Dumpstate constructor 1906 std::string stats_path = 1907 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile)) 1908 : ""; 1909 ds.progress_.reset(new Progress(stats_path)); 1910 1911 /* gets the sequential id */ 1912 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); 1913 ds.id_ = ++last_id; 1914 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id)); 1915 1916 MYLOGI("begin\n"); 1917 1918 register_sig_handler(); 1919 1920 if (do_start_service) { 1921 MYLOGI("Starting 'dumpstate' service\n"); 1922 android::status_t ret; 1923 if ((ret = android::os::DumpstateService::Start()) != android::OK) { 1924 MYLOGE("Unable to start DumpstateService: %d\n", ret); 1925 } 1926 } 1927 1928 if (PropertiesHelper::IsDryRun()) { 1929 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); 1930 } 1931 1932 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(), 1933 ds.extra_options_.c_str()); 1934 1935 MYLOGI("bugreport format version: %s\n", ds.version_.c_str()); 1936 1937 ds.do_early_screenshot_ = ds.update_progress_; 1938 1939 // If we are going to use a socket, do it as early as possible 1940 // to avoid timeouts from bugreport. 1941 if (use_socket) { 1942 redirect_to_socket(stdout, "dumpstate"); 1943 } 1944 1945 if (use_control_socket) { 1946 MYLOGD("Opening control socket\n"); 1947 ds.control_socket_fd_ = open_socket("dumpstate"); 1948 ds.update_progress_ = 1; 1949 } 1950 1951 if (is_redirecting) { 1952 ds.bugreport_dir_ = dirname(use_outfile); 1953 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); 1954 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); 1955 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile), 1956 device_name.c_str(), build_id.c_str()); 1957 if (do_add_date) { 1958 char date[80]; 1959 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); 1960 ds.name_ = date; 1961 } else { 1962 ds.name_ = "undated"; 1963 } 1964 1965 if (telephony_only) { 1966 ds.base_name_ += "-telephony"; 1967 } else if (wifi_only) { 1968 ds.base_name_ += "-wifi"; 1969 } 1970 1971 if (do_fb) { 1972 ds.screenshot_path_ = ds.GetPath(".png"); 1973 } 1974 ds.tmp_path_ = ds.GetPath(".tmp"); 1975 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt"); 1976 1977 MYLOGD( 1978 "Bugreport dir: %s\n" 1979 "Base name: %s\n" 1980 "Suffix: %s\n" 1981 "Log path: %s\n" 1982 "Temporary path: %s\n" 1983 "Screenshot path: %s\n", 1984 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), 1985 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); 1986 1987 if (do_zip_file) { 1988 ds.path_ = ds.GetPath(".zip"); 1989 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str()); 1990 create_parent_dirs(ds.path_.c_str()); 1991 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb")); 1992 if (ds.zip_file == nullptr) { 1993 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno)); 1994 do_zip_file = 0; 1995 } else { 1996 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get())); 1997 } 1998 ds.AddTextZipEntry("version.txt", ds.version_); 1999 } 2000 2001 if (ds.update_progress_) { 2002 if (do_broadcast) { 2003 // clang-format off 2004 2005 std::vector<std::string> am_args = { 2006 "--receiver-permission", "android.permission.DUMP", 2007 "--es", "android.intent.extra.NAME", ds.name_, 2008 "--ei", "android.intent.extra.ID", std::to_string(ds.id_), 2009 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), 2010 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), 2011 }; 2012 // clang-format on 2013 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args); 2014 } 2015 if (use_control_socket) { 2016 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str()); 2017 } 2018 } 2019 } 2020 2021 /* read /proc/cmdline before dropping root */ 2022 FILE *cmdline = fopen("/proc/cmdline", "re"); 2023 if (cmdline) { 2024 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline); 2025 fclose(cmdline); 2026 } 2027 2028 if (do_vibrate) { 2029 Vibrate(150); 2030 } 2031 2032 if (do_fb && ds.do_early_screenshot_) { 2033 if (ds.screenshot_path_.empty()) { 2034 // should not have happened 2035 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); 2036 } else { 2037 MYLOGI("taking early screenshot\n"); 2038 ds.TakeScreenshot(); 2039 } 2040 } 2041 2042 if (do_zip_file) { 2043 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) { 2044 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(), 2045 strerror(errno)); 2046 } 2047 } 2048 2049 if (is_redirecting) { 2050 TEMP_FAILURE_RETRY(dup_stderr_fd = dup(fileno(stderr))); 2051 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str())); 2052 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) { 2053 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", 2054 ds.log_path_.c_str(), strerror(errno)); 2055 } 2056 TEMP_FAILURE_RETRY(dup_stdout_fd = dup(fileno(stdout))); 2057 /* TODO: rather than generating a text file now and zipping it later, 2058 it would be more efficient to redirect stdout to the zip entry 2059 directly, but the libziparchive doesn't support that option yet. */ 2060 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str())); 2061 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) { 2062 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n", 2063 ds.tmp_path_.c_str(), strerror(errno)); 2064 } 2065 } 2066 2067 // Don't buffer stdout 2068 setvbuf(stdout, nullptr, _IONBF, 0); 2069 2070 // NOTE: there should be no stdout output until now, otherwise it would break the header. 2071 // In particular, DurationReport objects should be created passing 'title, NULL', so their 2072 // duration is logged into MYLOG instead. 2073 ds.PrintHeader(); 2074 2075 if (telephony_only) { 2076 DumpstateTelephonyOnly(); 2077 ds.DumpstateBoard(); 2078 } else if (wifi_only) { 2079 DumpstateWifiOnly(); 2080 } else { 2081 // Dumps systrace right away, otherwise it will be filled with unnecessary events. 2082 // First try to dump anrd trace if the daemon is running. Otherwise, dump 2083 // the raw trace. 2084 if (!dump_anrd_trace()) { 2085 dump_systrace(); 2086 } 2087 2088 // Invoking the following dumpsys calls before dump_traces() to try and 2089 // keep the system stats as close to its initial state as possible. 2090 RunDumpsysCritical(); 2091 2092 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed. 2093 dump_raft(); 2094 2095 /* collect stack traces from Dalvik and native processes (needs root) */ 2096 dump_traces_path = dump_traces(); 2097 2098 /* Run some operations that require root. */ 2099 ds.tombstone_data_ = GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping()); 2100 ds.anr_data_ = GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping()); 2101 2102 ds.AddDir(RECOVERY_DIR, true); 2103 ds.AddDir(RECOVERY_DATA_DIR, true); 2104 ds.AddDir(LOGPERSIST_DATA_DIR, false); 2105 if (!PropertiesHelper::IsUserBuild()) { 2106 ds.AddDir(PROFILE_DATA_DIR_CUR, true); 2107 ds.AddDir(PROFILE_DATA_DIR_REF, true); 2108 } 2109 add_mountinfo(); 2110 DumpIpTablesAsRoot(); 2111 2112 // Capture any IPSec policies in play. No keys are exposed here. 2113 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, 2114 CommandOptions::WithTimeout(10).Build()); 2115 2116 // Run ss as root so we can see socket marks. 2117 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, 2118 CommandOptions::WithTimeout(10).Build()); 2119 2120 // Run iotop as root to show top 100 IO threads 2121 RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"}); 2122 2123 if (!DropRootUser()) { 2124 return -1; 2125 } 2126 2127 dumpstate(); 2128 } 2129 2130 /* close output if needed */ 2131 if (is_redirecting) { 2132 TEMP_FAILURE_RETRY(dup2(dup_stdout_fd, fileno(stdout))); 2133 } 2134 2135 /* rename or zip the (now complete) .tmp file to its final location */ 2136 if (use_outfile) { 2137 2138 /* check if user changed the suffix using system properties */ 2139 std::string name = android::base::GetProperty( 2140 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), ""); 2141 bool change_suffix= false; 2142 if (!name.empty()) { 2143 /* must whitelist which characters are allowed, otherwise it could cross directories */ 2144 std::regex valid_regex("^[-_a-zA-Z0-9]+$"); 2145 if (std::regex_match(name.c_str(), valid_regex)) { 2146 change_suffix = true; 2147 } else { 2148 MYLOGE("invalid suffix provided by user: %s\n", name.c_str()); 2149 } 2150 } 2151 if (change_suffix) { 2152 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); 2153 ds.name_ = name; 2154 if (!ds.screenshot_path_.empty()) { 2155 std::string new_screenshot_path = ds.GetPath(".png"); 2156 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { 2157 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), 2158 new_screenshot_path.c_str(), strerror(errno)); 2159 } else { 2160 ds.screenshot_path_ = new_screenshot_path; 2161 } 2162 } 2163 } 2164 2165 bool do_text_file = true; 2166 if (do_zip_file) { 2167 if (!ds.FinishZipFile()) { 2168 MYLOGE("Failed to finish zip file; sending text bugreport instead\n"); 2169 do_text_file = true; 2170 } else { 2171 do_text_file = false; 2172 // Since zip file is already created, it needs to be renamed. 2173 std::string new_path = ds.GetPath(".zip"); 2174 if (ds.path_ != new_path) { 2175 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); 2176 if (rename(ds.path_.c_str(), new_path.c_str())) { 2177 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(), 2178 strerror(errno)); 2179 } else { 2180 ds.path_ = new_path; 2181 } 2182 } 2183 } 2184 } 2185 if (do_text_file) { 2186 ds.path_ = ds.GetPath(".txt"); 2187 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), 2188 ds.tmp_path_.c_str()); 2189 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) { 2190 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), 2191 strerror(errno)); 2192 ds.path_.clear(); 2193 } 2194 } 2195 if (use_control_socket) { 2196 if (do_text_file) { 2197 dprintf(ds.control_socket_fd_, 2198 "FAIL:could not create zip file, check %s " 2199 "for more details\n", 2200 ds.log_path_.c_str()); 2201 } else { 2202 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str()); 2203 } 2204 } 2205 } 2206 2207 /* vibrate a few but shortly times to let user know it's finished */ 2208 if (do_vibrate) { 2209 for (int i = 0; i < 3; i++) { 2210 Vibrate(75); 2211 usleep((75 + 50) * 1000); 2212 } 2213 } 2214 2215 /* tell activity manager we're done */ 2216 if (do_broadcast) { 2217 if (!ds.path_.empty()) { 2218 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); 2219 // clang-format off 2220 2221 std::vector<std::string> am_args = { 2222 "--receiver-permission", "android.permission.DUMP", 2223 "--ei", "android.intent.extra.ID", std::to_string(ds.id_), 2224 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), 2225 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), 2226 "--es", "android.intent.extra.BUGREPORT", ds.path_, 2227 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ 2228 }; 2229 // clang-format on 2230 if (do_fb) { 2231 am_args.push_back("--es"); 2232 am_args.push_back("android.intent.extra.SCREENSHOT"); 2233 am_args.push_back(ds.screenshot_path_); 2234 } 2235 if (!ds.notification_title.empty()) { 2236 am_args.push_back("--es"); 2237 am_args.push_back("android.intent.extra.TITLE"); 2238 am_args.push_back(ds.notification_title); 2239 if (!ds.notification_description.empty()) { 2240 am_args.push_back("--es"); 2241 am_args.push_back("android.intent.extra.DESCRIPTION"); 2242 am_args.push_back(ds.notification_description); 2243 } 2244 } 2245 if (is_remote_mode) { 2246 am_args.push_back("--es"); 2247 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); 2248 am_args.push_back(SHA256_file_hash(ds.path_)); 2249 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", 2250 am_args); 2251 } else { 2252 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); 2253 } 2254 } else { 2255 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n"); 2256 } 2257 } 2258 2259 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(), 2260 ds.progress_->GetInitialMax()); 2261 ds.progress_->Save(); 2262 MYLOGI("done (id %d)\n", ds.id_); 2263 2264 if (is_redirecting) { 2265 TEMP_FAILURE_RETRY(dup2(dup_stderr_fd, fileno(stderr))); 2266 } 2267 2268 if (use_control_socket && ds.control_socket_fd_ != -1) { 2269 MYLOGD("Closing control socket\n"); 2270 close(ds.control_socket_fd_); 2271 } 2272 2273 ds.tombstone_data_.clear(); 2274 ds.anr_data_.clear(); 2275 2276 return 0; 2277} 2278