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