Refactored run_command functions.

Back in the day, dumpstate.c had a simple run_command() function. Then on
Android N, dumpstate.c became dumpstate.cpp and that function multiplied into:

- run_command()
- run_command_as_shell()
- run_command_always()

Not only these 3 commands were pretty much copy-and-pasted, but they
didn't take advantage of C++ features (such as std::vector and
std::string).

This CL refactor them into a single runCommand() function that takes an
optional CommandOptions argument to set its behavior. Examples:

// Run as shell
   runCommand("DUMPSYS MEMINFO", {"meminfo", "-a"},
              CommandOptions::WithTimeout(90).DropRoot().Build());

// Run always, as shell
   runCommand(nullptr, am, CommandOptions::WithTimeout(20).Build());

The legacy run_command() is still available since it's used by
device-specific dumpstate_board() implementations, but it will
eventually go away as well.

This change also:
- Refactored run_dumpsys() into runDumpsys().
- Added a .clang-format file (initially equals to dumpsys's).
- Renamed the variable names on those commands according to the style guide.

BUG: 26379932
Test: manual

Change-Id: Ie045eb2fb825e68088d231129044c59e61450d99
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 11b0c3e..978abb8 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -33,19 +33,151 @@
 #include <unistd.h>
 #include <stdbool.h>
 #include <stdio.h>
+
+#include <string>
 #include <vector>
 
 #define SU_PATH "/system/xbin/su"
 
 // Workaround for const char *args[MAX_ARGS_ARRAY_SIZE] variables until they're converted to
 // std::vector<std::string>
+// TODO: remove once not used
 #define MAX_ARGS_ARRAY_SIZE 1000
 
-
+// TODO: remove once moved to HAL
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/*
+ * Defines the Linux user that should be executing a command.
+ */
+enum RootMode {
+    /* Explicitly change the `uid` and `gid` to be `shell`.*/
+    DROP_ROOT,
+    /* Don't change the `uid` and `gid`. */
+    DONT_DROP_ROOT,
+    /* Prefix the command with `/PATH/TO/su root`. Won't work non user builds. */
+    SU_ROOT
+};
+
+/*
+ * Defines what should happen with the `stdout` stream of a command.
+ */
+enum StdoutMode {
+    /* Don't change `stdout`. */
+    NORMAL_STDOUT,
+    /* Redirect `stdout` to `stderr`. */
+    REDIRECT_TO_STDERR
+};
+
+/*
+ * Helper class used to report how long it takes for a section to finish.
+ *
+ * Typical usage:
+ *
+ *    DurationReporter duration_reporter(title);
+ *
+ */
+class DurationReporter {
+  public:
+    DurationReporter(const char* title);
+    DurationReporter(const char* title, FILE* out);
+
+    ~DurationReporter();
+
+    static uint64_t nanotime();
+
+  private:
+    // TODO: use std::string for title, once dump_files() and other places that pass a char* are
+    // refactored as well.
+    const char* mTitle;
+    FILE* mOut;
+    uint64_t mStarted;
+};
+
+/*
+ * Value object used to set command options.
+ *
+ * Typically constructed using a builder with chained setters. Examples:
+ *
+ *  CommandOptions::WithTimeout(20).AsRoot().Build();
+ *  CommandOptions::WithTimeout(10).Always().RedirectStderr().Build();
+ *
+ * Although the builder could be used to dynamically set values. Example:
+ *
+ *  CommandOptions::CommandOptionsBuilder options =
+ *  CommandOptions::WithTimeout(10);
+ *  if (!is_user_build()) {
+ *    options.AsRoot();
+ *  }
+ *  runCommand("command", {"args"}, options.Build());
+ */
+class CommandOptions {
+  private:
+    class CommandOptionsValues {
+      private:
+        CommandOptionsValues(long timeout);
+
+        long mTimeout;
+        bool mAlways;
+        RootMode mRootMode;
+        StdoutMode mStdoutMode;
+        std::string mLoggingMessage;
+
+        friend class CommandOptions;
+        friend class CommandOptionsBuilder;
+    };
+
+    CommandOptions(const CommandOptionsValues& values);
+
+    const CommandOptionsValues mValues;
+
+  public:
+    class CommandOptionsBuilder {
+      public:
+        /* Sets the command to always run, even on `dry-run` mode. */
+        CommandOptionsBuilder& Always();
+        /* Sets the command's RootMode as `SU_ROOT` */
+        CommandOptionsBuilder& AsRoot();
+        /* Sets the command's RootMode as `DROP_ROOT` */
+        CommandOptionsBuilder& DropRoot();
+        /* Sets the command's StdoutMode `REDIRECT_TO_STDERR` */
+        CommandOptionsBuilder& RedirectStderr();
+        /* When not empty, logs a message before executing the command.
+         * Must contain a `%s`, which will be replaced by the full command line, and end on `\n`. */
+        CommandOptionsBuilder& Log(const std::string& message);
+        /* Builds the command options. */
+        CommandOptions Build();
+
+      private:
+        CommandOptionsBuilder(long timeout);
+        CommandOptionsValues mValues;
+        friend class CommandOptions;
+    };
+
+    /** Gets the command timeout, in seconds. */
+    long Timeout() const;
+    /* Checks whether the command should always be run, even on dry-run mode. */
+    bool Always() const;
+    /** Gets the RootMode of the command. */
+    RootMode RootMode() const;
+    /** Gets the StdoutMode of the command. */
+    StdoutMode StdoutMode() const;
+    /** Gets the logging message header, it any. */
+    std::string LoggingMessage() const;
+
+    /** Creates a builder with the requied timeout. */
+    static CommandOptionsBuilder WithTimeout(long timeout);
+
+    // Common options.
+    static CommandOptions DEFAULT;
+    static CommandOptions DEFAULT_DUMPSYS;
+    static CommandOptions AS_ROOT_5;
+    static CommandOptions AS_ROOT_10;
+    static CommandOptions AS_ROOT_20;
+};
+
 typedef void (for_each_pid_func)(int, const char *);
 typedef void (for_each_tid_func)(int, int, const char *);
 
@@ -110,21 +242,35 @@
         bool (*skip)(const char *path),
         int (*dump_from_fd)(const char *title, const char *path, int fd));
 
-// TODO: need to refactor all those run_command variations; there shold be just one, receiving an
-// optional CommandOptions objects with values such as run_always, drop_root, etc...
-
-/* forks a command and waits for it to finish -- terminate args with NULL */
-int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...);
+/* forks a command and waits for it to finish -- terminate args with NULL
+ * DEPRECATED: will be removed once device-specific implementations use
+ * runCommand */
 int run_command(const char *title, int timeout_seconds, const char *command, ...);
 
-enum RootMode { DROP_ROOT, DONT_DROP_ROOT };
-enum StdoutMode { NORMAL_STDOUT, REDIRECT_TO_STDERR };
+/*
+ * 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);
 
-/* forks a command and waits for it to finish
-   first element of args is the command, and last must be NULL.
-   command is always ran, even when _DUMPSTATE_DRY_RUN_ is defined. */
-int run_command_always(const char *title, RootMode root_mode, StdoutMode stdout_mode,
-        int timeout_seconds, const char *args[]);
+/*
+ * 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.
+ */
+void runDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs,
+                const CommandOptions& options = CommandOptions::DEFAULT_DUMPSYS);
 
 /* switch to non-root user and group */
 bool drop_root_user();
@@ -213,29 +359,6 @@
  */
 bool is_dry_run();
 
-/*
- * Helper class used to report how long it takes for a section to finish.
- *
- * Typical usage:
- *
- *    DurationReporter duration_reporter(title);
- *
- */
-class DurationReporter {
-public:
-    explicit DurationReporter(const char *title);
-    DurationReporter(const char *title, FILE* out);
-
-    ~DurationReporter();
-
-    static uint64_t nanotime();
-
-private:
-    const char* title_;
-    FILE* out_;
-    uint64_t started_;
-};
-
 #ifdef __cplusplus
 }
 #endif