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