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