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