Faster bugreports (2/n)

- Having a system property to disable parallel run function.
- Post 'DumpTraces' to the thread pool. 3% is
  improved compared with single thread run.

Bug: 136262402
Test: atest dumpstate_test
Test: atest dumpstate_smoke_test
Test: Manual enable and disable parallel run
Test: Manual trigger report using hardware key
Test: Manual trigger using bugreport shortcut
Change-Id: I2185cc3e2f429a150605d6268324c52d137db385
diff --git a/cmds/dumpstate/DumpPool.h b/cmds/dumpstate/DumpPool.h
index 266d519..a4ea875 100644
--- a/cmds/dumpstate/DumpPool.h
+++ b/cmds/dumpstate/DumpPool.h
@@ -29,26 +29,32 @@
 namespace os {
 namespace dumpstate {
 
+class DumpPoolTest;
+
 /*
  * A thread pool with the fixed number of threads to execute multiple dump tasks
- * simultaneously for the dumpstate. The dump task is a callable function
- * included a file descriptor as a parameter, and the task could dump results to
- * that fd. For example:
+ * simultaneously for the dumpstate. The dump task is a callable function. It
+ * could include a file descriptor as a parameter to redirect dump results, if
+ * it needs to output results to the bugreport. This can avoid messing up
+ * bugreport's results when multiple dump tasks are running at the same time.
+ * Takes an example below for the usage of the DumpPool:
  *
- * void DumpXXXX(int out_fd) {
+ * void DumpFoo(int out_fd) {
  *     dprintf(out_fd, "Dump result to out_fd ...");
  * }
  * ...
  * DumpPool pool(tmp_root);
- * pool.enqueueTask("TaskName", &DumpXXXX, std::placeholders::_1);
+ * pool.enqueueTaskWithFd("TaskName", &DumpFoo, std::placeholders::_1);
  * ...
  * pool.waitForTask("TaskName");
  *
- * DumpXXXX is a callable function included a out_fd parameter. Using the
- * enqueueTask method in DumpPool to enqueue the task to the pool. The
- * std::placeholders::_1 is placeholder for DumpPool to pass a fd argument.
+ * DumpFoo is a callable function included a out_fd parameter. Using the
+ * enqueueTaskWithFd method in DumpPool to enqueue the task to the pool. The
+ * std::placeholders::_1 is a placeholder for DumpPool to pass a fd argument.
  */
 class DumpPool {
+  friend class android::os::dumpstate::DumpPoolTest;
+
   public:
     /*
      * Creates a thread pool.
@@ -72,17 +78,40 @@
     void shutdown();
 
     /*
-     * Adds a task with a task name into the queue of the thread pool.
+     * Adds a task into the queue of the thread pool.
      *
-     * |task_name| The name of the task.
-     * |f| Callable function to execute the task. This function must
-     *     include a parameter of file descriptor to output dump result.
+     * |task_name| The name of the task. It's also the title of the
+     * DurationReporter log.
+     * |f| Callable function to execute the task.
      * |args| A list of arguments.
+     *
+     * TODO(b/164369078): remove this api to have just one enqueueTask for consistency.
      */
-    template<class F, class... Args> void enqueueTask(const std::string& task_name,
-            F&& f, Args&&... args) {
-        auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
-        futures_map_[task_name] = post(func);
+    template<class F, class... Args> void enqueueTask(const std::string& task_name, F&& f,
+            Args&&... args) {
+        std::function<void(void)> func = std::bind(std::forward<F>(f),
+                std::forward<Args>(args)...);
+        futures_map_[task_name] = post(task_name, func);
+        if (threads_.empty()) {
+            start();
+        }
+    }
+
+    /*
+     * Adds a task into the queue of the thread pool. The task takes a file
+     * descriptor as a parameter to redirect dump results to a temporary file.
+     *
+     * |task_name| The name of the task. It's also the title of the
+     * DurationReporter log.
+     * |f| Callable function to execute the task.
+     * |args| A list of arguments. A placeholder std::placeholders::_1 as a fd
+     * argument needs to be included here.
+     */
+    template<class F, class... Args> void enqueueTaskWithFd(const std::string& task_name, F&& f,
+            Args&&... args) {
+        std::function<void(int)> func = std::bind(std::forward<F>(f),
+                std::forward<Args>(args)...);
+        futures_map_[task_name] = post(task_name, func);
         if (threads_.empty()) {
             start();
         }
@@ -111,13 +140,15 @@
     using Task = std::packaged_task<std::string()>;
     using Future = std::shared_future<std::string>;
 
-    template<class T> Future post(T dump_func) {
+    template<class T> void invokeTask(T dump_func, const std::string& duration_title, int out_fd);
+
+    template<class T> Future post(const std::string& task_name, T dump_func) {
         Task packaged_task([=]() {
             std::unique_ptr<TmpFile> tmp_file_ptr = createTempFile();
             if (!tmp_file_ptr) {
                 return std::string("");
             }
-            std::invoke(dump_func, tmp_file_ptr->fd.get());
+            invokeTask(dump_func, task_name, tmp_file_ptr->fd.get());
             fsync(tmp_file_ptr->fd.get());
             return std::string(tmp_file_ptr->path);
         });
@@ -138,12 +169,21 @@
     void setThreadName(const pthread_t thread, int id);
     void loop();
 
+    /*
+     * For test purpose only. Enables or disables logging duration of the task.
+     *
+     * |log_duration| if true, DurationReporter is initiated to log duration of
+     * the task.
+     */
+    void setLogDuration(bool log_duration);
+
   private:
     static const int MAX_THREAD_COUNT = 4;
 
     /* A path to a temporary folder for threads to create temporary files. */
     std::string tmp_root_;
     bool shutdown_;
+    bool log_duration_; // For test purpose only, the default value is true.
     std::mutex lock_;  // A lock for the tasks_.
     std::condition_variable condition_variable_;