Create thread in passthrough objects lazily.

Also, moved SynchronizedQueue to not be exported
becaue it's not used outside of the library.

Notice, it would be cleaner to add variables to TaskRunner
and then use those to determine if it's initialized or not.
However, the ABI of TaskRunner is tied up in HIDL clients.
Perhaps in the future, we can consider renaming
SynchronizedQueue to be called TaskRunnerImpl.

Bug: 38039413
Test: boot + hidl_test

Change-Id: Id5dbffe0196447c7798ba89df0ff8c69b6796210
diff --git a/base/include/hidl/TaskRunner.h b/base/include/hidl/TaskRunner.h
index 28ea01c..6a79ebf 100644
--- a/base/include/hidl/TaskRunner.h
+++ b/base/include/hidl/TaskRunner.h
@@ -16,7 +16,6 @@
 #ifndef ANDROID_HIDL_TASK_RUNNER_H
 #define ANDROID_HIDL_TASK_RUNNER_H
 
-#include "SynchronizedQueue.h"
 #include <memory>
 #include <thread>
 
@@ -24,13 +23,17 @@
 namespace hardware {
 namespace details {
 
+using Task = std::function<void(void)>;
+
+template <typename T>
+struct SynchronizedQueue;
+
 /*
  * A background infinite loop that runs the Tasks push()'ed.
  * Equivalent to a simple single-threaded Looper.
  */
 class TaskRunner {
 public:
-    using Task = std::function<void(void)>;
 
     /* Create an empty task runner. Nothing will be done until start() is called. */
     TaskRunner();
@@ -44,7 +47,9 @@
 
     /*
      * Sets the queue limit. Fails the push operation once the limit is reached.
-     * Then kicks off the loop.
+     * This function is named start for legacy reasons and to maintain ABI
+     * stability, but the underlying thread running tasks isn't started until
+     * the first task is pushed.
      */
     void start(size_t limit);