Home | History | Annotate | Download | only in dumpstate
      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