Moar C++ refactoring.

- Use std::string on runCommand(), DurationReport, dumpFile() and their
  dependencies.
- Moves runCommand() and dumpFile() to Dumpstate class.

These 2 commands are the only ones currently used on dumpstate_board() implementations.

BUG: 26379932
Test: manual / refactored code

Change-Id: I09072d4e183851f90c07960d1f971a925ea2c801
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 54b939c..1627ba8 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -98,6 +98,18 @@
 
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
+static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+                      const CommandOptions& options = CommandOptions::DEFAULT) {
+    return ds.RunCommand(title, fullCommand, options);
+}
+static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
+                       const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
+                       long dumpsysTimeout = 0) {
+    return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout);
+}
+static int DumpFile(const std::string& title, const std::string& path) {
+    return ds.DumpFile(title, path);
+}
 
 /*
  * List of supported zip format versions.
@@ -167,11 +179,11 @@
 
 void add_mountinfo() {
     if (!zip_writer) return;
-    const char *title = "MOUNT INFO";
+    std::string title = "MOUNT INFO";
     mount_points.clear();
-    DurationReporter duration_reporter(title, NULL);
-    for_each_pid(do_mountinfo, NULL);
-    MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
+    DurationReporter durationReporter(title, nullptr);
+    for_each_pid(do_mountinfo, nullptr);
+    MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size());
 }
 
 static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
@@ -708,7 +720,7 @@
     printf("Network: %s\n", network.c_str());
 
     printf("Kernel: ");
-    DumpFile(nullptr, "/proc/version");
+    DumpFile("", "/proc/version");
     printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
     printf("Bugreport format version: %s\n", version.c_str());
     printf("Dumpstate info: id=%lu pid=%d dryRun=%d args=%s extraOptions=%s\n", ds.id_, getpid(),
@@ -795,14 +807,14 @@
 }
 
 // TODO: move to util.cpp
-void add_dir(const char *dir, bool recursive) {
+void add_dir(const std::string& dir, bool recursive) {
     if (!zip_writer) {
-        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
+        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir.c_str());
         return;
     }
-    MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
-    DurationReporter duration_reporter(dir, NULL);
-    dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
+    MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive);
+    DurationReporter durationReporter(dir, nullptr);
+    dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd);
 }
 
 /* adds a text entry entry to the existing zip file. */
@@ -847,7 +859,7 @@
 }
 
 static void dumpstate(const std::string& screenshot_path, const std::string& version) {
-    DurationReporter duration_reporter("DUMPSTATE");
+    DurationReporter durationReporter("DUMPSTATE");
     unsigned long timeout;
 
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
@@ -1055,15 +1067,15 @@
 
     printf("------ BACKLIGHTS ------\n");
     printf("LCD brightness=");
-    DumpFile(nullptr, "/sys/class/leds/lcd-backlight/brightness");
+    DumpFile("", "/sys/class/leds/lcd-backlight/brightness");
     printf("Button brightness=");
-    DumpFile(nullptr, "/sys/class/leds/button-backlight/brightness");
+    DumpFile("", "/sys/class/leds/button-backlight/brightness");
     printf("Keyboard brightness=");
-    DumpFile(nullptr, "/sys/class/leds/keyboard-backlight/brightness");
+    DumpFile("", "/sys/class/leds/keyboard-backlight/brightness");
     printf("ALS mode=");
-    DumpFile(nullptr, "/sys/class/leds/lcd-backlight/als");
+    DumpFile("", "/sys/class/leds/lcd-backlight/als");
     printf("LCD driver registers:\n");
-    DumpFile(nullptr, "/sys/class/leds/lcd-backlight/registers");
+    DumpFile("", "/sys/class/leds/lcd-backlight/registers");
     printf("\n");
 
     /* Binder state is expensive to look at as it uses a lot of memory. */
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 9236fe3..bfa894e 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -82,8 +82,8 @@
  */
 class DurationReporter {
   public:
-    DurationReporter(const char* title);
-    DurationReporter(const char* title, FILE* out);
+    DurationReporter(const std::string& title);
+    DurationReporter(const std::string& title, FILE* out);
 
     ~DurationReporter();
 
@@ -92,7 +92,7 @@
   private:
     // TODO: use std::string for title, once dump_files() and other places that pass a char* are
     // refactored as well.
-    const char* title_;
+    std::string title_;
     FILE* out_;
     uint64_t started_;
 };
@@ -214,6 +214,43 @@
      */
     bool IsDryRun();
 
+    /*
+     * Forks a command, waits for it to finish, and returns its status.
+     *
+     * |title| description of the command printed on `stdout` (or empty to skip
+     * description).
+     * |full_command| array containing the command (first entry) and its arguments.
+     * Must contain at least one element.
+     * |options| optional argument defining the command's behavior.
+     */
+    int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+                   const CommandOptions& options = CommandOptions::DEFAULT);
+
+    /*
+     * Runs `dumpsys` with the given arguments, automatically setting its timeout
+     * (`-t` argument)
+     * according to the command options.
+     *
+     * |title| description of the command printed on `stdout` (or empty to skip
+     * description).
+     * |dumpsys_args| `dumpsys` arguments (except `-t`).
+     * |options| optional argument defining the command's behavior.
+ * |dumpsysTimeout| when > 0, defines the value passed to `dumpsys -t` (otherwise it uses the
+ * timeout from `options`)
+     */
+    void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
+                    const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
+                    long dumpsysTimeout = 0);
+
+    /*
+     * Prints the contents of a file.
+     *
+     * |title| description of the command printed on `stdout` (or empty to skip
+     * description).
+     * |path| location of the file to be dumped.
+     */
+    int DumpFile(const std::string& title, const std::string& path);
+
     // TODO: fields below should be private once refactor is finished
     // TODO: initialize fields on constructor
 
@@ -256,17 +293,13 @@
 bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
 
 /* adds all files from a directory to the zipped bugreport file */
-void add_dir(const char *dir, bool recursive);
+void add_dir(const std::string& dir, bool recursive);
 
 /* prints the contents of a file
  * DEPRECATED: will be removed once device-specific implementations use
  * dumpFile */
 int dump_file(const char *title, const char *path);
 
-/* Prints the contents of a file. */
-// TODO: use std::string for title once other char* title references are refactored.
-int DumpFile(const char* title, const std::string& path);
-
 /* saves the the contents of a file as a long */
 int read_file_as_long(const char *path, long int *output);
 
@@ -281,43 +314,14 @@
  * to false when set to NULL. dump_from_fd will always be
  * called with title NULL.
  */
-int dump_files(const char *title, const char *dir,
-        bool (*skip)(const char *path),
-        int (*dump_from_fd)(const char *title, const char *path, int fd));
+int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
+               int (*dump_from_fd)(const char* title, const char* path, int fd));
 
 /* forks a command and waits for it to finish -- terminate args with NULL
  * DEPRECATED: will be removed once device-specific implementations use
- * runCommand */
+ * RunCommand */
 int run_command(const char *title, int timeout_seconds, const char *command, ...);
 
-/*
- * Forks a command, waits for it to finish, and returns its status.
- *
- * |title| description of the command printed on `stdout` (or `nullptr` to skip
- * description).
- * |full_command| array containing the command (first entry) and its arguments.
- * Must contain at least one element.
- * |options| optional argument defining the command's behavior.
- */
-// TODO: use std::string for title once other char* title references are refactored.
-int RunCommand(const char* title, const std::vector<std::string>& fullCommand,
-               const CommandOptions& options = CommandOptions::DEFAULT);
-
-/*
- * Runs `dumpsys` with the given arguments, automatically setting its timeout
- * (`-t` argument)
- * according to the command options.
- *
- * |title| description of the command printed on `stdout`.
- * |dumpsys_args| `dumpsys` arguments (except `-t`).
- * |options| optional argument defining the command's behavior.
- * |dumpsysTimeout| when > 0, defines the value passed to `dumpsys -t` (otherwise it uses the
- * timeout from `options`)
- */
-void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
-                const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS,
-                long dumpsysTimeout = 0);
-
 /* switch to non-root user and group */
 bool drop_root_user();
 
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
index 641d80c..e036dfa 100644
--- a/cmds/dumpstate/utils.cpp
+++ b/cmds/dumpstate/utils.cpp
@@ -56,6 +56,10 @@
 
 // TODO: temporary variables and functions used during C++ refactoring
 static Dumpstate& ds = Dumpstate::GetInstance();
+static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+                      const CommandOptions& options = CommandOptions::DEFAULT) {
+    return ds.RunCommand(title, fullCommand, options);
+}
 
 /* list of native processes to include in the native dumps */
 // This matches the /proc/pid/exe link instead of /proc/pid/cmdline.
@@ -158,25 +162,24 @@
     return sSingleton;
 }
 
-DurationReporter::DurationReporter(const char *title) : DurationReporter(title, stdout) {}
+DurationReporter::DurationReporter(const std::string& title) : DurationReporter(title, stdout) {
+}
 
-DurationReporter::DurationReporter(const char *title, FILE *out) {
-    title_ = title;
-    if (title != nullptr) {
+DurationReporter::DurationReporter(const std::string& title, FILE* out) : title_(title), out_(out) {
+    if (!title_.empty()) {
         started_ = DurationReporter::Nanotime();
     }
-    out_ = out;
 }
 
 DurationReporter::~DurationReporter() {
-    if (title_ != nullptr) {
+    if (!title_.empty()) {
         uint64_t elapsed = DurationReporter::Nanotime() - started_;
         // Use "Yoda grammar" to make it easier to grep|sort sections.
         if (out_ != nullptr) {
             fprintf(out_, "------ %.3fs was the duration of '%s' ------\n",
-                    (float)elapsed / NANOS_PER_SEC, title_);
+                    (float)elapsed / NANOS_PER_SEC, title_.c_str());
         } else {
-            MYLOGD("Duration of '%s': %.3fs\n", title_, (float)elapsed / NANOS_PER_SEC);
+            MYLOGD("Duration of '%s': %.3fs\n", title_.c_str(), (float)elapsed / NANOS_PER_SEC);
         }
     }
 }
@@ -505,9 +508,9 @@
     RunCommand(title, {"showmap", "-q", arg}, CommandOptions::AS_ROOT_10);
 }
 
-static int _dump_file_from_fd(const char *title, const char *path, int fd) {
-    if (title) {
-        printf("------ %s (%s", title, path);
+static int _dump_file_from_fd(const std::string& title, const char* path, int fd) {
+    if (!title.empty()) {
+        printf("------ %s (%s", title.c_str(), path);
 
         struct stat st;
         // Only show the modification time of non-device files.
@@ -569,21 +572,22 @@
     close(fd);
 
     if (!newline) printf("\n");
-    if (title) printf("\n");
+    if (!title.empty()) printf("\n");
     return 0;
 }
 
+// DEPRECATED: will be removed once device-specific implementations use dumpFile
 int dump_file(const char *title, const char *path) {
-    return DumpFile(title, path);
+    return ds.DumpFile(title, path);
 }
 
-int DumpFile(const char* title, const std::string& path) {
+int Dumpstate::DumpFile(const std::string& title, const std::string& path) {
     DurationReporter durationReporter(title);
     int fd = TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC));
     if (fd < 0) {
         int err = errno;
         printf("*** %s: %s\n", path.c_str(), strerror(err));
-        if (title != nullptr) printf("\n");
+        if (!title.empty()) printf("\n");
         return -1;
     }
     return _dump_file_from_fd(title, path.c_str(), fd);
@@ -616,9 +620,8 @@
  * to false when set to NULL. dump_from_fd will always be
  * called with title NULL.
  */
-int dump_files(const char *title, const char *dir,
-        bool (*skip)(const char *path),
-        int (*dump_from_fd)(const char *title, const char *path, int fd)) {
+int dump_files(const std::string& title, const char* dir, bool (*skip)(const char* path),
+               int (*dump_from_fd)(const char* title, const char* path, int fd)) {
     DurationReporter duration_reporter(title);
     DIR *dirp;
     struct dirent *d;
@@ -626,8 +629,8 @@
     const char *slash = "/";
     int fd, retval = 0;
 
-    if (title) {
-        printf("------ %s (%s) ------\n", title, dir);
+    if (!title.empty()) {
+        printf("------ %s (%s) ------\n", title.c_str(), dir);
     }
     if (is_dry_run()) return 0;
 
@@ -660,7 +663,7 @@
             continue;
         }
         if (d->d_type == DT_DIR) {
-            int ret = dump_files(NULL, newpath, skip, dump_from_fd);
+            int ret = dump_files("", newpath, skip, dump_from_fd);
             if (ret < 0) {
                 retval = ret;
             }
@@ -675,7 +678,7 @@
         (*dump_from_fd)(NULL, newpath, fd);
     }
     closedir(dirp);
-    if (title) {
+    if (!title.empty()) {
         printf("\n");
     }
     return retval;
@@ -745,6 +748,7 @@
     return true;
 }
 
+// DEPRECATED: will be removed once device-specific implementations use RunCommand
 int run_command(const char* title, int timeout_seconds, const char* command, ...) {
     std::vector<std::string> fullCommand = {command};
     size_t arg;
@@ -759,13 +763,13 @@
     }
     va_end(ap);
 
-    return RunCommand(title, fullCommand, CommandOptions::WithTimeout(timeout_seconds).Build());
+    return ds.RunCommand(title, fullCommand, CommandOptions::WithTimeout(timeout_seconds).Build());
 }
 
-int RunCommand(const char* title, const std::vector<std::string>& fullCommand,
-               const CommandOptions& options) {
+int Dumpstate::RunCommand(const std::string& title, const std::vector<std::string>& fullCommand,
+                          const CommandOptions& options) {
     if (fullCommand.empty()) {
-        MYLOGE("No arguments on command '%s'\n", title);
+        MYLOGE("No arguments on command '%s'\n", title.c_str());
         return -1;
     }
     DurationReporter durationReporter(title);
@@ -777,8 +781,8 @@
 
     const char* args[size];
 
-    if (title) {
-        printf("------ %s (", title);
+    if (!title.empty()) {
+        printf("------ %s (", title.c_str());
     }
 
     std::string commandString;
@@ -800,7 +804,7 @@
     const char* path = args[0];
     const char* command = commandString.c_str();
 
-    if (title) {
+    if (!title.empty()) {
         printf("%s) ------\n", command);
     }
 
@@ -912,12 +916,12 @@
     return status;
 }
 
-void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
-                const CommandOptions& options, long dumpsysTimeout) {
+void Dumpstate::RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
+                           const CommandOptions& options, long dumpsysTimeout) {
     long timeout = dumpsysTimeout > 0 ? dumpsysTimeout : options.Timeout();
     std::vector<std::string> dumpsys = {"/system/bin/dumpsys", "-t", std::to_string(timeout)};
     dumpsys.insert(dumpsys.end(), dumpsysArgs.begin(), dumpsysArgs.end());
-    RunCommand(title.c_str(), dumpsys, options);
+    RunCommand(title, dumpsys, options);
 }
 
 bool drop_root_user() {
@@ -974,12 +978,12 @@
 
     am.insert(am.end(), args.begin(), args.end());
 
-    RunCommand(nullptr, am, CommandOptions::WithTimeout(20)
-                                .Log("Sending broadcast: '%s'\n")
-                                .Always()
-                                .DropRoot()
-                                .RedirectStderr()
-                                .Build());
+    RunCommand("", am, CommandOptions::WithTimeout(20)
+                           .Log("Sending broadcast: '%s'\n")
+                           .Always()
+                           .DropRoot()
+                           .RedirectStderr()
+                           .Build());
 }
 
 size_t num_props = 0;
@@ -1328,7 +1332,7 @@
 }
 
 void take_screenshot(const std::string& path) {
-    RunCommand(nullptr, {"/system/bin/screencap", "-p", path},
+    RunCommand("", {"/system/bin/screencap", "-p", path},
                CommandOptions::WithTimeout(10).Always().RedirectStderr().Build());
 }