1 /* 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 */ 16 17 #ifndef FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_ 18 #define FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_ 19 20 #include <time.h> 21 #include <unistd.h> 22 #include <stdbool.h> 23 #include <stdio.h> 24 25 #include <string> 26 #include <vector> 27 28 #include <aidl/android/hardware/dumpstate/IDumpstateDevice.h> 29 #include <android-base/macros.h> 30 #include <android-base/unique_fd.h> 31 #include <android/hardware/dumpstate/1.1/types.h> 32 #include <android/os/BnIncidentAuthListener.h> 33 #include <android/os/IDumpstate.h> 34 #include <android/os/IDumpstateListener.h> 35 #include <utils/StrongPointer.h> 36 #include <ziparchive/zip_writer.h> 37 38 #include "DumpstateUtil.h" 39 #include "DumpPool.h" 40 #include "TaskQueue.h" 41 42 // TODO: move everything under this namespace 43 // TODO: and then remove explicitly android::os::dumpstate:: prefixes 44 namespace android { 45 namespace os { 46 47 struct DumpstateOptions; 48 49 namespace dumpstate { 50 51 class DumpstateTest; 52 class ProgressTest; 53 class ZippedBugReportStreamTest; 54 55 } // namespace dumpstate 56 } // namespace os 57 } // namespace android 58 59 class ZipWriter; 60 61 // TODO: remove once moved to HAL 62 #ifdef __cplusplus 63 extern "C" { 64 #endif 65 66 /* 67 * Helper class used to report how long it takes for a section to finish. 68 * 69 * Typical usage: 70 * 71 * DurationReporter duration_reporter(title); 72 * 73 */ 74 class DurationReporter { 75 public: 76 explicit DurationReporter(const std::string& title, bool logcat_only = false, 77 bool verbose = false, int duration_fd = STDOUT_FILENO); 78 79 ~DurationReporter(); 80 81 private: 82 std::string title_; 83 bool logcat_only_; 84 bool verbose_; 85 uint64_t started_; 86 int duration_fd_; 87 88 DISALLOW_COPY_AND_ASSIGN(DurationReporter); 89 }; 90 91 /* 92 * Keeps track of current progress and estimated max, saving stats on file to tune up future runs. 93 * 94 * Each `dumpstate` section contributes to the total weight by an individual weight, so the overall 95 * progress can be calculated by dividing the estimate max progress by the current progress. 96 * 97 * The estimated max progress is initially set to a value (`kDefaultMax) defined empirically, but 98 * it's adjusted after each dumpstate run by storing the average duration in a file. 99 * 100 */ 101 class Progress { 102 friend class android::os::dumpstate::ProgressTest; 103 friend class android::os::dumpstate::DumpstateTest; 104 105 public: 106 /* 107 * Default estimation of the max duration of a bugreport generation. 108 * 109 * It does not need to match the exact sum of all sections, but ideally it should to be slight 110 * more than such sum: a value too high will cause the bugreport to finish before the user 111 * expected (for example, jumping from 70% to 100%), while a value too low will cause the 112 * progress to get stuck at an almost-finished value (like 99%) for a while. 113 * 114 * This constant is only used when the average duration from previous runs cannot be used. 115 */ 116 static const int kDefaultMax; 117 118 explicit Progress(const std::string& path = ""); 119 120 // Gets the current progress. 121 int32_t Get() const; 122 123 // Gets the current estimated max progress. 124 int32_t GetMax() const; 125 126 // Gets the initial estimated max progress. 127 int32_t GetInitialMax() const; 128 129 // Increments progress (ignored if not positive). 130 // Returns `true` if the max progress increased as well. 131 bool Inc(int32_t delta); 132 133 // Persist the stats. 134 void Save(); 135 136 void Dump(int fd, const std::string& prefix) const; 137 138 private: 139 Progress(int32_t initial_max, float growth_factor, 140 const std::string& path = ""); // Used by test cases. 141 Progress(int32_t initial_max, int32_t progress, float growth_factor); // Used by test cases. 142 void Load(); 143 int32_t initial_max_; 144 int32_t progress_; 145 int32_t max_; 146 float growth_factor_; 147 int32_t n_runs_; 148 int32_t average_max_; 149 std::string path_; 150 }; 151 152 /* 153 * List of supported zip format versions. 154 * 155 * See bugreport-format.md for more info. 156 */ 157 static std::string VERSION_CURRENT = "2.0"; 158 159 /* 160 * "Alias" for the current version. 161 */ 162 static std::string VERSION_DEFAULT = "default"; 163 164 /* 165 * Directory used by Dumpstate binary to keep its local files. 166 */ 167 static const std::string DUMPSTATE_DIRECTORY = "/bugreports"; 168 169 /* 170 * Structure that contains the information of an open dump file. 171 */ 172 struct DumpData { 173 // Path of the file. 174 std::string name; 175 176 // Open file descriptor for the file. 177 android::base::unique_fd fd; 178 179 // Modification time of the file. 180 time_t mtime; 181 }; 182 183 /* 184 * Main class driving a bugreport generation. 185 * 186 * Currently, it only contains variables that are accessed externally, but gradually the functions 187 * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. 188 */ 189 class Dumpstate { 190 friend class android::os::dumpstate::DumpstateTest; 191 friend class android::os::dumpstate::ZippedBugReportStreamTest; 192 193 public: 194 enum RunStatus { OK, HELP, INVALID_INPUT, ERROR, USER_CONSENT_DENIED, USER_CONSENT_TIMED_OUT }; 195 196 // The mode under which the bugreport should be run. Each mode encapsulates a few options. 197 enum BugreportMode { 198 BUGREPORT_FULL = android::os::IDumpstate::BUGREPORT_MODE_FULL, 199 BUGREPORT_INTERACTIVE = android::os::IDumpstate::BUGREPORT_MODE_INTERACTIVE, 200 BUGREPORT_REMOTE = android::os::IDumpstate::BUGREPORT_MODE_REMOTE, 201 BUGREPORT_WEAR = android::os::IDumpstate::BUGREPORT_MODE_WEAR, 202 BUGREPORT_TELEPHONY = android::os::IDumpstate::BUGREPORT_MODE_TELEPHONY, 203 BUGREPORT_WIFI = android::os::IDumpstate::BUGREPORT_MODE_WIFI, 204 BUGREPORT_DEFAULT = android::os::IDumpstate::BUGREPORT_MODE_DEFAULT 205 }; 206 207 static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS; 208 209 static Dumpstate& GetInstance(); 210 211 /* Initialize dumpstate fields before starting bugreport generation */ 212 void Initialize(); 213 214 /* 215 * Forks a command, waits for it to finish, and returns its status. 216 * 217 * |title| description of the command printed on `stdout` (or empty to skip 218 * description). 219 * |full_command| array containing the command (first entry) and its arguments. 220 * Must contain at least one element. 221 * |options| optional argument defining the command's behavior. 222 * |out_fd| A fd to support the DumpPool to output results to a temporary 223 * file. Using STDOUT_FILENO if it's not running in the parallel task. 224 */ 225 int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, 226 const android::os::dumpstate::CommandOptions& options = 227 android::os::dumpstate::CommandOptions::DEFAULT, 228 bool verbose_duration = false, int out_fd = STDOUT_FILENO); 229 230 /* 231 * Runs `dumpsys` with the given arguments, automatically setting its timeout 232 * (`-T` argument) 233 * according to the command options. 234 * 235 * |title| description of the command printed on `stdout` (or empty to skip 236 * description). 237 * |dumpsys_args| `dumpsys` arguments (except `-t`). 238 * |options| optional argument defining the command's behavior. 239 * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -T` (otherwise it uses the 240 * timeout from `options`) 241 * |out_fd| A fd to support the DumpPool to output results to a temporary 242 * file. Using STDOUT_FILENO if it's not running in the parallel task. 243 */ 244 void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args, 245 const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS, 246 long dumpsys_timeout_ms = 0, int out_fd = STDOUT_FILENO); 247 248 /* 249 * Prints the contents of a file. 250 * 251 * |title| description of the command printed on `stdout` (or empty to skip 252 * description). 253 * |path| location of the file to be dumped. 254 */ 255 int DumpFile(const std::string& title, const std::string& path); 256 257 /* 258 * Adds a new entry to the existing zip file. 259 * */ 260 bool AddZipEntry(const std::string& entry_name, const std::string& entry_path); 261 262 /* 263 * Adds a new entry to the existing zip file. 264 * 265 * |entry_name| destination path of the new entry. 266 * |fd| file descriptor to read from. 267 * |timeout| timeout to terminate the read if not completed. Set 268 * value of 0s (default) to disable timeout. 269 */ 270 android::status_t AddZipEntryFromFd(const std::string& entry_name, int fd, 271 std::chrono::milliseconds timeout); 272 273 /* 274 * Adds a text entry to the existing zip file. 275 */ 276 bool AddTextZipEntry(const std::string& entry_name, const std::string& content); 277 278 /* 279 * Adds all files from a directory to the zipped bugreport file. 280 */ 281 void AddDir(const std::string& dir, bool recursive); 282 283 /* 284 * Takes a screenshot and save it to the given `path`. 285 * 286 * If `path` is empty, uses a standard path based on the bugreport name. 287 */ 288 void TakeScreenshot(const std::string& path = ""); 289 290 ///////////////////////////////////////////////////////////////////// 291 // TODO: members below should be private once refactor is finished // 292 ///////////////////////////////////////////////////////////////////// 293 294 // TODO: temporary method until Dumpstate object is properly set 295 void SetProgress(std::unique_ptr<Progress> progress); 296 297 // Dumps Dalvik and native stack traces, sets the trace file location to path 298 // if it succeeded. 299 // Note that it returns early if user consent is denied with status USER_CONSENT_DENIED. 300 // Returns OK in all other cases. 301 RunStatus DumpTraces(const char** path); 302 303 /* 304 * |out_fd| A fd to support the DumpPool to output results to a temporary file. 305 * Dumpstate can pick up later and output to the bugreport. Using STDOUT_FILENO 306 * if it's not running in the parallel task. 307 */ 308 void DumpstateBoard(int out_fd = STDOUT_FILENO); 309 310 /* 311 * Updates the overall progress of the bugreport generation by the given weight increment. 312 */ 313 void UpdateProgress(int32_t delta); 314 315 /* Prints the dumpstate header on `stdout`. */ 316 void PrintHeader() const; 317 318 /* 319 * Adds the temporary report to the existing .zip file, closes the .zip file, and removes the 320 * temporary file. 321 */ 322 bool FinishZipFile(); 323 324 /* Constructs a full path inside directory with file name formatted using the given suffix. */ 325 std::string GetPath(const std::string& directory, const std::string& suffix) const; 326 327 /* Constructs a full path inside bugreport_internal_dir_ with file name formatted using the 328 * given suffix. */ 329 std::string GetPath(const std::string& suffix) const; 330 331 /* Returns true if the current version supports priority dump feature. */ 332 bool CurrentVersionSupportsPriorityDumps() const; 333 334 struct DumpOptions; 335 336 /* 337 * Main entry point for running a complete bugreport. 338 * 339 * Initialize() dumpstate before calling this method. 340 * 341 */ 342 RunStatus Run(int32_t calling_uid, const std::string& calling_package); 343 344 RunStatus ParseCommandlineAndRun(int argc, char* argv[]); 345 346 /* Deletes in-progress files */ 347 void Cancel(); 348 349 /* Sets runtime options. */ 350 void SetOptions(std::unique_ptr<DumpOptions> options); 351 352 /* 353 * Returns true if user consent is necessary and has been denied. 354 * Consent is only necessary if the caller has asked to copy over the bugreport to a file they 355 * provided. 356 */ 357 bool IsUserConsentDenied() const; 358 359 /* 360 * Returns true if dumpstate is called by bugreporting API 361 */ 362 bool CalledByApi() const; 363 364 /* 365 * Enqueues a task to the dumpstate's TaskQueue if the parallel run is enabled, 366 * otherwise invokes it immediately. The task adds file at path entry_path 367 * as a zip file entry with name entry_name. Unlinks entry_path when done. 368 * 369 * All enqueued tasks will be executed in the dumpstate's FinishZipFile method 370 * before the zip file is finished. Tasks will be cancelled in dumpstate's 371 * ShutdownDumpPool method if they have never been called. 372 */ 373 void EnqueueAddZipEntryAndCleanupIfNeeded(const std::string& entry_name, 374 const std::string& entry_path); 375 376 /* 377 * Structure to hold options that determine the behavior of dumpstate. 378 */ 379 struct DumpOptions { 380 bool do_vibrate = true; 381 // Writes bugreport zipped file to a socket. 382 bool stream_to_socket = false; 383 // Writes generation progress updates to a socket. 384 bool progress_updates_to_socket = false; 385 bool do_screenshot = false; 386 bool is_screenshot_copied = false; 387 bool is_remote_mode = false; 388 bool show_header_only = false; 389 bool telephony_only = false; 390 bool wifi_only = false; 391 // Trimmed-down version of dumpstate to only include whitelisted logs. 392 bool limited_only = false; 393 // Whether progress updates should be published. 394 bool do_progress_updates = false; 395 // this is used to derive dumpstate HAL bug report mode 396 // TODO(b/148168577) get rid of the AIDL values, replace them with the HAL values instead. 397 // The HAL is actually an API surface that can be validated, while the AIDL is not (@hide). 398 BugreportMode bugreport_mode = Dumpstate::BugreportMode::BUGREPORT_DEFAULT; 399 // File descriptor to output zip file. Takes precedence over out_dir. 400 android::base::unique_fd bugreport_fd; 401 // File descriptor to screenshot file. 402 android::base::unique_fd screenshot_fd; 403 // Custom output directory. 404 std::string out_dir; 405 // Bugreport mode of the bugreport as a string 406 std::string bugreport_mode_string; 407 // Command-line arguments as string 408 std::string args; 409 // Notification title and description 410 std::string notification_title; 411 std::string notification_description; 412 413 /* Initializes options from commandline arguments. */ 414 RunStatus Initialize(int argc, char* argv[]); 415 416 /* Initializes options from the requested mode. */ 417 void Initialize(BugreportMode bugreport_mode, const android::base::unique_fd& bugreport_fd, 418 const android::base::unique_fd& screenshot_fd, 419 bool is_screenshot_requested); 420 421 /* Returns true if the options set so far are consistent. */ 422 bool ValidateOptions() const; 423 424 /* Returns if options specified require writing to custom file location */ OutputToCustomFileDumpOptions425 bool OutputToCustomFile() { 426 // Custom location is only honored in limited mode. 427 return limited_only && !out_dir.empty() && bugreport_fd.get() == -1; 428 } 429 }; 430 431 // TODO: initialize fields on constructor 432 // dumpstate id - unique after each device reboot. 433 uint32_t id_; 434 435 // dumpstate pid 436 pid_t pid_; 437 438 // Runtime options. 439 std::unique_ptr<DumpOptions> options_; 440 441 // Last progress that was sent to the listener [0-100]. 442 int last_reported_percent_progress_ = 0; 443 444 // Whether it should take an screenshot earlier in the process. 445 bool do_early_screenshot_ = false; 446 447 // This is set to true when the trace snapshot request in the early call to 448 // MaybeSnapshotSystemTrace(). When this is true, the later stages of 449 // dumpstate will append the trace to the zip archive. 450 bool has_system_trace_ = false; 451 452 std::unique_ptr<Progress> progress_; 453 454 // When set, defines a socket file-descriptor use to report progress to bugreportz 455 // or to stream the zipped file to. 456 int control_socket_fd_ = -1; 457 458 // Bugreport format version; 459 std::string version_ = VERSION_CURRENT; 460 461 time_t now_; 462 463 // Base name (without suffix or extensions) of the bugreport files, typically 464 // `bugreport-BUILD_ID`. 465 std::string base_name_; 466 467 // Name is the suffix part of the bugreport files - it's typically the date, 468 // but it could be changed by the user.. 469 std::string name_; 470 471 std::string bugreport_internal_dir_ = DUMPSTATE_DIRECTORY; 472 473 // Full path of the temporary file containing the bugreport, inside bugreport_internal_dir_. 474 // At the very end this file is pulled into the zip file. 475 std::string tmp_path_; 476 477 // Full path of the file containing the dumpstate logs, inside bugreport_internal_dir_. 478 // This is useful for debugging. 479 std::string log_path_; 480 481 // Full path of the bugreport zip file inside bugreport_internal_dir_. 482 std::string path_; 483 484 // Full path of the file containing the screenshot (when requested). 485 std::string screenshot_path_; 486 487 // Pointer to the zipped file. 488 std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; 489 490 // Pointer to the zip structure. 491 std::unique_ptr<ZipWriter> zip_writer_; 492 493 // Binder object listening to progress. 494 android::sp<android::os::IDumpstateListener> listener_; 495 496 // List of open tombstone dump files. 497 std::vector<DumpData> tombstone_data_; 498 499 // List of open ANR dump files. 500 std::vector<DumpData> anr_data_; 501 502 // A thread pool to execute dump tasks simultaneously if the parallel run is enabled. 503 std::unique_ptr<android::os::dumpstate::DumpPool> dump_pool_; 504 505 // A task queue to collect adding zip entry tasks inside dump tasks if the 506 // parallel run is enabled. 507 std::unique_ptr<android::os::dumpstate::TaskQueue> zip_entry_tasks_; 508 509 // A callback to IncidentCompanion service, which checks user consent for sharing the 510 // bugreport with the calling app. If the user has not responded yet to the dialog it will 511 // be neither confirmed nor denied. 512 class ConsentCallback : public android::os::BnIncidentAuthListener { 513 public: 514 ConsentCallback(); 515 android::binder::Status onReportApproved() override; 516 android::binder::Status onReportDenied() override; 517 518 enum ConsentResult { APPROVED, DENIED, UNAVAILABLE }; 519 520 ConsentResult getResult(); 521 522 // Returns the time since creating this listener 523 uint64_t getElapsedTimeMs() const; 524 525 private: 526 ConsentResult result_; 527 uint64_t start_time_; 528 std::mutex lock_; 529 }; 530 531 private: 532 RunStatus RunInternal(int32_t calling_uid, const std::string& calling_package); 533 534 RunStatus DumpstateDefaultAfterCritical(); 535 536 void MaybeTakeEarlyScreenshot(); 537 void MaybeSnapshotSystemTrace(); 538 void MaybeSnapshotWinTrace(); 539 540 void onUiIntensiveBugreportDumpsFinished(int32_t calling_uid); 541 542 void MaybeCheckUserConsent(int32_t calling_uid, const std::string& calling_package); 543 544 // Removes the in progress files output files (tmp file, zip/txt file, screenshot), 545 // but leaves the log file alone. 546 void CleanupTmpFiles(); 547 548 // Create the thread pool to enable the parallel run function. 549 void EnableParallelRunIfNeeded(); 550 void ShutdownDumpPool(); 551 552 RunStatus HandleUserConsentDenied(); 553 554 // Copies bugreport artifacts over to the caller's directories provided there is user consent or 555 // called by Shell. 556 RunStatus CopyBugreportIfUserConsented(int32_t calling_uid); 557 558 std::function<int(const char *)> open_socket_fn_; 559 560 // Used by GetInstance() only. 561 explicit Dumpstate(const std::string& version = VERSION_CURRENT); 562 563 android::sp<ConsentCallback> consent_callback_; 564 565 std::recursive_mutex mutex_; 566 567 DISALLOW_COPY_AND_ASSIGN(Dumpstate); 568 }; 569 570 // for_each_pid_func = void (*)(int, const char*); 571 // for_each_tid_func = void (*)(int, int, const char*); 572 573 typedef void(for_each_pid_func)(int, const char*); 574 typedef void(for_each_tid_func)(int, int, const char*); 575 576 /* saves the the contents of a file as a long */ 577 int read_file_as_long(const char *path, long int *output); 578 579 /* prints the contents of the fd 580 * fd must have been opened with the flag O_NONBLOCK. 581 */ 582 int dump_file_from_fd(const char *title, const char *path, int fd); 583 584 /* calls skip to gate calling dump_from_fd recursively 585 * in the specified directory. dump_from_fd defaults to 586 * dump_file_from_fd above when set to NULL. skip defaults 587 * to false when set to NULL. dump_from_fd will always be 588 * called with title NULL. 589 */ 590 int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path), 591 int (*dump_from_fd)(const char* title, const char* path, int fd)); 592 593 /* 594 * Redirects 'redirect' to a file indicated by 'path', truncating it. 595 * 596 * Returns true if redirect succeeds. 597 */ 598 bool redirect_to_file(FILE* redirect, char* path); 599 600 /* 601 * Redirects 'redirect' to an existing file indicated by 'path', appending it. 602 * 603 * Returns true if redirect succeeds. 604 */ 605 bool redirect_to_existing_file(FILE* redirect, char* path); 606 607 /* create leading directories, if necessary */ 608 void create_parent_dirs(const char *path); 609 610 /* for each process in the system, run the specified function */ 611 void for_each_pid(for_each_pid_func func, const char *header); 612 613 /* for each thread in the system, run the specified function */ 614 void for_each_tid(for_each_tid_func func, const char *header); 615 616 /* Displays a blocked processes in-kernel wait channel */ 617 void show_wchan(int pid, int tid, const char *name); 618 619 /* Displays a processes times */ 620 void show_showtime(int pid, const char *name); 621 622 /* Runs "showmap" for a process */ 623 void do_showmap(int pid, const char *name); 624 625 /* Gets the dmesg output for the kernel */ 626 void do_dmesg(); 627 628 /* Prints the contents of all the routing tables, both IPv4 and IPv6. */ 629 void dump_route_tables(); 630 631 /* Dump subdirectories of cgroupfs if the corresponding process is frozen */ 632 void dump_frozen_cgroupfs(); 633 634 /* Play a sound via Stagefright */ 635 void play_sound(const char *path); 636 637 /* Checks if a given path is a directory. */ 638 bool is_dir(const char* pathname); 639 640 /** Gets the last modification time of a file, or default time if file is not found. */ 641 time_t get_mtime(int fd, time_t default_mtime); 642 643 /** Gets command-line arguments. */ 644 void format_args(int argc, const char *argv[], std::string *args); 645 646 /** Main entry point for dumpstate. */ 647 int run_main(int argc, char* argv[]); 648 649 #ifdef __cplusplus 650 } 651 #endif 652 653 #endif /* FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_ */ 654