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/IDumpstateListener.h> 31 #include <utils/StrongPointer.h> 32 #include <ziparchive/zip_writer.h> 33 34 #include "DumpstateUtil.h" 35 36 // Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to 37 // std::vector<std::string> 38 // TODO: remove once not used 39 #define MAX_ARGS_ARRAY_SIZE 1000 40 41 // TODO: move everything under this namespace 42 // TODO: and then remove explicitly android::os::dumpstate:: prefixes 43 namespace android { 44 namespace os { 45 namespace dumpstate { 46 47 class DumpstateTest; 48 class ProgressTest; 49 50 } // namespace dumpstate 51 } // namespace os 52 } // namespace android 53 54 class ZipWriter; 55 56 // TODO: remove once moved to HAL 57 #ifdef __cplusplus 58 extern "C" { 59 #endif 60 61 /* 62 * Helper class used to report how long it takes for a section to finish. 63 * 64 * Typical usage: 65 * 66 * DurationReporter duration_reporter(title); 67 * 68 */ 69 class DurationReporter { 70 public: 71 DurationReporter(const std::string& title, bool log_only = false); 72 73 ~DurationReporter(); 74 75 private: 76 std::string title_; 77 bool log_only_; 78 uint64_t started_; 79 80 DISALLOW_COPY_AND_ASSIGN(DurationReporter); 81 }; 82 83 /* 84 * Keeps track of current progress and estimated max, saving stats on file to tune up future runs. 85 * 86 * Each `dumpstate` section contributes to the total weight by an individual weight, so the overall 87 * progress can be calculated by dividing the estimate max progress by the current progress. 88 * 89 * The estimated max progress is initially set to a value (`kDefaultMax) defined empirically, but 90 * it's adjusted after each dumpstate run by storing the average duration in a file. 91 * 92 */ 93 class Progress { 94 friend class android::os::dumpstate::ProgressTest; 95 friend class android::os::dumpstate::DumpstateTest; 96 97 public: 98 /* 99 * Default estimation of the max duration of a bugreport generation. 100 * 101 * It does not need to match the exact sum of all sections, but ideally it should to be slight 102 * more than such sum: a value too high will cause the bugreport to finish before the user 103 * expected (for example, jumping from 70% to 100%), while a value too low will cause the 104 * progress to get stuck at an almost-finished value (like 99%) for a while. 105 * 106 * This constant is only used when the average duration from previous runs cannot be used. 107 */ 108 static const int kDefaultMax; 109 110 Progress(const std::string& path = ""); 111 112 // Gets the current progress. 113 int32_t Get() const; 114 115 // Gets the current estimated max progress. 116 int32_t GetMax() const; 117 118 // Gets the initial estimated max progress. 119 int32_t GetInitialMax() const; 120 121 // Increments progress (ignored if not positive). 122 // Returns `true` if the max progress increased as well. 123 bool Inc(int32_t delta); 124 125 // Persist the stats. 126 void Save(); 127 128 void Dump(int fd, const std::string& prefix) const; 129 130 private: 131 Progress(int32_t initial_max, float growth_factor, 132 const std::string& path = ""); // Used by test cases. 133 Progress(int32_t initial_max, int32_t progress, float growth_factor); // Used by test cases. 134 void Load(); 135 int32_t initial_max_; 136 int32_t progress_; 137 int32_t max_; 138 float growth_factor_; 139 int32_t n_runs_; 140 int32_t average_max_; 141 const std::string& path_; 142 }; 143 144 /* 145 * List of supported zip format versions. 146 * 147 * See bugreport-format.md for more info. 148 */ 149 static std::string VERSION_CURRENT = "2.0"; 150 151 /* 152 * Temporary version that adds a anr-traces.txt entry. Once tools support it, the current version 153 * will be bumped to 3.0. 154 */ 155 static std::string VERSION_SPLIT_ANR = "3.0-dev-split-anr"; 156 157 /* 158 * "Alias" for the current version. 159 */ 160 static std::string VERSION_DEFAULT = "default"; 161 162 /* 163 * Structure that contains the information of an open dump file. 164 */ 165 struct DumpData { 166 // Path of the file. 167 std::string name; 168 169 // Open file descriptor for the file. 170 android::base::unique_fd fd; 171 172 // Modification time of the file. 173 time_t mtime; 174 }; 175 176 /* 177 * Main class driving a bugreport generation. 178 * 179 * Currently, it only contains variables that are accessed externally, but gradually the functions 180 * that are spread accross utils.cpp and dumpstate.cpp will be moved to it. 181 */ 182 class Dumpstate { 183 friend class DumpstateTest; 184 185 public: 186 static android::os::dumpstate::CommandOptions DEFAULT_DUMPSYS; 187 188 static Dumpstate& GetInstance(); 189 190 /* Checkes whether dumpstate is generating a zipped bugreport. */ 191 bool IsZipping() const; 192 193 /* 194 * Forks a command, waits for it to finish, and returns its status. 195 * 196 * |title| description of the command printed on `stdout` (or empty to skip 197 * description). 198 * |full_command| array containing the command (first entry) and its arguments. 199 * Must contain at least one element. 200 * |options| optional argument defining the command's behavior. 201 */ 202 int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, 203 const android::os::dumpstate::CommandOptions& options = 204 android::os::dumpstate::CommandOptions::DEFAULT); 205 206 /* 207 * Runs `dumpsys` with the given arguments, automatically setting its timeout 208 * (`-T` argument) 209 * according to the command options. 210 * 211 * |title| description of the command printed on `stdout` (or empty to skip 212 * description). 213 * |dumpsys_args| `dumpsys` arguments (except `-t`). 214 * |options| optional argument defining the command's behavior. 215 * |dumpsys_timeout| when > 0, defines the value passed to `dumpsys -T` (otherwise it uses the 216 * timeout from `options`) 217 */ 218 void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsys_args, 219 const android::os::dumpstate::CommandOptions& options = DEFAULT_DUMPSYS, 220 long dumpsys_timeout_ms = 0); 221 222 /* 223 * Prints the contents of a file. 224 * 225 * |title| description of the command printed on `stdout` (or empty to skip 226 * description). 227 * |path| location of the file to be dumped. 228 */ 229 int DumpFile(const std::string& title, const std::string& path); 230 231 /* 232 * Adds a new entry to the existing zip file. 233 * */ 234 bool AddZipEntry(const std::string& entry_name, const std::string& entry_path); 235 236 /* 237 * Adds a new entry to the existing zip file. 238 * 239 * |entry_name| destination path of the new entry. 240 * |fd| file descriptor to read from. 241 * |timeout| timeout to terminate the read if not completed. Set 242 * value of 0s (default) to disable timeout. 243 */ 244 android::status_t AddZipEntryFromFd(const std::string& entry_name, int fd, 245 std::chrono::milliseconds timeout); 246 247 /* 248 * Adds a text entry entry to the existing zip file. 249 */ 250 bool AddTextZipEntry(const std::string& entry_name, const std::string& content); 251 252 /* 253 * Adds all files from a directory to the zipped bugreport file. 254 */ 255 void AddDir(const std::string& dir, bool recursive); 256 257 /* 258 * Takes a screenshot and save it to the given `path`. 259 * 260 * If `path` is empty, uses a standard path based on the bugreport name. 261 */ 262 void TakeScreenshot(const std::string& path = ""); 263 264 ///////////////////////////////////////////////////////////////////// 265 // TODO: members below should be private once refactor is finished // 266 ///////////////////////////////////////////////////////////////////// 267 268 // TODO: temporary method until Dumpstate object is properly set 269 void SetProgress(std::unique_ptr<Progress> progress); 270 271 void DumpstateBoard(); 272 273 /* 274 * Updates the overall progress of the bugreport generation by the given weight increment. 275 */ 276 void UpdateProgress(int32_t delta); 277 278 /* Prints the dumpstate header on `stdout`. */ 279 void PrintHeader() const; 280 281 /* 282 * Adds the temporary report to the existing .zip file, closes the .zip file, and removes the 283 * temporary file. 284 */ 285 bool FinishZipFile(); 286 287 /* Gets the path of a bugreport file with the given suffix. */ 288 std::string GetPath(const std::string& suffix) const; 289 290 /* Returns true if the current version supports priority dump feature. */ 291 bool CurrentVersionSupportsPriorityDumps() const; 292 293 // TODO: initialize fields on constructor 294 295 // dumpstate id - unique after each device reboot. 296 uint32_t id_; 297 298 // dumpstate pid 299 pid_t pid_; 300 301 // Whether progress updates should be published. 302 bool update_progress_ = false; 303 304 // How frequently the progess should be updated;the listener will only be notificated when the 305 // delta from the previous update is more than the threshold. 306 int32_t update_progress_threshold_ = 100; 307 308 // Last progress that triggered a listener updated 309 int32_t last_updated_progress_; 310 311 // Whether it should take an screenshot earlier in the process. 312 bool do_early_screenshot_ = false; 313 314 std::unique_ptr<Progress> progress_; 315 316 // When set, defines a socket file-descriptor use to report progress to bugreportz. 317 int control_socket_fd_ = -1; 318 319 // Bugreport format version; 320 std::string version_ = VERSION_CURRENT; 321 322 // Command-line arguments as string 323 std::string args_; 324 325 // Extra options passed as system property. 326 std::string extra_options_; 327 328 // Full path of the directory where the bugreport files will be written. 329 std::string bugreport_dir_; 330 331 // Full path of the temporary file containing the screenshot (when requested). 332 std::string screenshot_path_; 333 334 time_t now_; 335 336 // Base name (without suffix or extensions) of the bugreport files, typically 337 // `bugreport-BUILD_ID`. 338 std::string base_name_; 339 340 // Name is the suffix part of the bugreport files - it's typically the date (when invoked with 341 // `-d`), but it could be changed by the user.. 342 std::string name_; 343 344 // Full path of the temporary file containing the bugreport. 345 std::string tmp_path_; 346 347 // Full path of the file containing the dumpstate logs. 348 std::string log_path_; 349 350 // Pointer to the actual path, be it zip or text. 351 std::string path_; 352 353 // Pointer to the zipped file. 354 std::unique_ptr<FILE, int (*)(FILE*)> zip_file{nullptr, fclose}; 355 356 // Pointer to the zip structure. 357 std::unique_ptr<ZipWriter> zip_writer_; 358 359 // Binder object listening to progress. 360 android::sp<android::os::IDumpstateListener> listener_; 361 std::string listener_name_; 362 bool report_section_; 363 364 // Notification title and description 365 std::string notification_title; 366 std::string notification_description; 367 368 // List of open tombstone dump files. 369 std::vector<DumpData> tombstone_data_; 370 371 // List of open ANR dump files. 372 std::vector<DumpData> anr_data_; 373 374 private: 375 // Used by GetInstance() only. 376 Dumpstate(const std::string& version = VERSION_CURRENT); 377 378 DISALLOW_COPY_AND_ASSIGN(Dumpstate); 379 }; 380 381 // for_each_pid_func = void (*)(int, const char*); 382 // for_each_tid_func = void (*)(int, int, const char*); 383 384 typedef void(for_each_pid_func)(int, const char*); 385 typedef void(for_each_tid_func)(int, int, const char*); 386 387 /* saves the the contents of a file as a long */ 388 int read_file_as_long(const char *path, long int *output); 389 390 /* prints the contents of the fd 391 * fd must have been opened with the flag O_NONBLOCK. 392 */ 393 int dump_file_from_fd(const char *title, const char *path, int fd); 394 395 /* calls skip to gate calling dump_from_fd recursively 396 * in the specified directory. dump_from_fd defaults to 397 * dump_file_from_fd above when set to NULL. skip defaults 398 * to false when set to NULL. dump_from_fd will always be 399 * called with title NULL. 400 */ 401 int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path), 402 int (*dump_from_fd)(const char* title, const char* path, int fd)); 403 404 /** opens a socket and returns its file descriptor */ 405 int open_socket(const char *service); 406 407 /* redirect output to a service control socket */ 408 void redirect_to_socket(FILE *redirect, const char *service); 409 410 /* redirect output to a new file */ 411 void redirect_to_file(FILE *redirect, char *path); 412 413 /* redirect output to an existing file */ 414 void redirect_to_existing_file(FILE *redirect, char *path); 415 416 /* create leading directories, if necessary */ 417 void create_parent_dirs(const char *path); 418 419 /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */ 420 const char *dump_traces(); 421 422 /* for each process in the system, run the specified function */ 423 void for_each_pid(for_each_pid_func func, const char *header); 424 425 /* for each thread in the system, run the specified function */ 426 void for_each_tid(for_each_tid_func func, const char *header); 427 428 /* Displays a blocked processes in-kernel wait channel */ 429 void show_wchan(int pid, int tid, const char *name); 430 431 /* Displays a processes times */ 432 void show_showtime(int pid, const char *name); 433 434 /* Runs "showmap" for a process */ 435 void do_showmap(int pid, const char *name); 436 437 /* Gets the dmesg output for the kernel */ 438 void do_dmesg(); 439 440 /* Prints the contents of all the routing tables, both IPv4 and IPv6. */ 441 void dump_route_tables(); 442 443 /* Play a sound via Stagefright */ 444 void play_sound(const char *path); 445 446 /* Checks if a given path is a directory. */ 447 bool is_dir(const char* pathname); 448 449 /** Gets the last modification time of a file, or default time if file is not found. */ 450 time_t get_mtime(int fd, time_t default_mtime); 451 452 /* Dumps eMMC Extended CSD data. */ 453 void dump_emmc_ecsd(const char *ext_csd_path); 454 455 /** Gets command-line arguments. */ 456 void format_args(int argc, const char *argv[], std::string *args); 457 458 /** Main entry point for dumpstate. */ 459 int run_main(int argc, char* argv[]); 460 461 #ifdef __cplusplus 462 } 463 #endif 464 465 #endif /* FRAMEWORK_NATIVE_CMD_DUMPSTATE_H_ */ 466