Revert "Revert "Tie vr flinger to persistent vr mode""

This reverts commit 7480c060cb3466d97ec3125d61bbace153f534c8.

Transfer display control to vr flinger when persistent vr mode is
entered, rather than when vr mode is entered. This allows cardboard
apps, which will invoke vr mode but not persistent vr mode, to work as
in N.

This activates vr flinger at device boot for Daydream ready devices,
which fixes an issue where an app would attempt to create a surface
before vr flinger was running, which would hang indefinitely.

The VrManager listener for persistent vr mode is put in vr flinger
instead of surface flinger. This is cleaner since the vr interaction
with the rest of the device is now consolidated in vr flinger.

While testing I encountered a problem where vr flinger was given control
of the display but vsync was turned off, causing vr flinger's post
thread to hang. I changed the vr flinger logic to give control over
vsync and other display settings to the post thread, and took the
opportunity to further simplify and improve vr flinger's thread
interactions.

Bug: 35885165

Test: Manually confirmed that when persistent vr mode is not invoked we
get the N-based render implementation, and when persistent vr mode is
invoked we get vr flinger.

Change-Id: I3b5ad599cc0748e38b861c714c4cc3118f854acf
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index e2a8b90..2d3d78b 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -176,6 +176,12 @@
 
 // HardwareComposer encapsulates the hardware composer HAL, exposing a
 // simplified API to post buffers to the display.
+//
+// HardwareComposer is accessed by both the vr flinger dispatcher thread and the
+// surface flinger main thread, in addition to internally running a separate
+// thread for compositing/EDS and posting layers to the HAL. When changing how
+// variables are used or adding new state think carefully about which threads
+// will access the state and whether it needs to be synchronized.
 class HardwareComposer {
  public:
   // Type for vsync callback.
@@ -193,8 +199,12 @@
 
   bool IsInitialized() const { return initialized_; }
 
-  bool Suspend();
-  bool Resume();
+  // Start the post thread if there's work to do (i.e. visible layers). This
+  // should only be called from surface flinger's main thread.
+  void Enable();
+  // Pause the post thread, blocking until the post thread has signaled that
+  // it's paused. This should only be called from surface flinger's main thread.
+  void Disable();
 
   // Get the HMD display metrics for the current display.
   DisplayMetrics GetHmdDisplayMetrics() const;
@@ -219,12 +229,9 @@
     return native_display_metrics_;
   }
 
-  std::shared_ptr<IonBuffer> framebuffer_target() const {
-    return framebuffer_target_;
-  }
-
   // Set the display surface stack to compose to the display each frame.
-  int SetDisplaySurfaces(std::vector<std::shared_ptr<DisplaySurface>> surfaces);
+  void SetDisplaySurfaces(
+      std::vector<std::shared_ptr<DisplaySurface>> surfaces);
 
   Compositor* GetCompositor() { return &compositor_; }
 
@@ -266,8 +273,21 @@
   void PostLayers(bool is_geometry_changed);
   void PostThread();
 
+  // Check to see if we have a value written to post_thread_interrupt_event_fd_,
+  // indicating a control thread interrupted the post thread. This clears the
+  // post_thread_interrupt_event_fd_ state in the process. Returns true if an
+  // interrupt was requested.
+  bool CheckPostThreadInterruptEventFd();
+  // Blocks until either event_fd becomes readable, or we're interrupted by a
+  // control thread. Any errors are returned as negative errno values. If we're
+  // interrupted, kPostThreadInterrupted will be returned.
+  int PostThreadPollInterruptible(int event_fd);
+
+  // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
+  // on the post thread that can be interrupted by a control thread. If
+  // interrupted, these calls return kPostThreadInterrupted.
   int ReadWaitPPState();
-  int BlockUntilVSync(/*out*/ bool* suspend_requested);
+  int BlockUntilVSync();
   int ReadVSyncTimestamp(int64_t* timestamp);
   int WaitForVSync(int64_t* timestamp);
   int SleepUntil(int64_t wakeup_timestamp);
@@ -275,12 +295,18 @@
   bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
 
   // Returns true if the layer config changed, false otherwise
-  bool UpdateLayerConfig(
-      std::vector<std::shared_ptr<DisplaySurface>>* compositor_surfaces);
-  void PostCompositorBuffers(
-      const std::vector<std::shared_ptr<DisplaySurface>>& compositor_surfaces);
+  bool UpdateLayerConfig();
+  void PostCompositorBuffers();
 
-  void UpdateDisplayState();
+  // Return true if the post thread has work to do (i.e. there are visible
+  // surfaces to post to the screen). Must be called with post_thread_mutex_
+  // locked. Called only from the post thread.
+  bool PostThreadHasWork();
+
+  // Called on the post thread when the post thread is resumed.
+  void OnPostThreadResumed();
+  // Called on the post thread when the post thread is paused or quits.
+  void OnPostThreadPaused();
 
   struct FrameTimeMeasurementRecord {
     int64_t start_time;
@@ -324,14 +350,28 @@
   // Buffer for the background layer required by hardware composer.
   std::shared_ptr<IonBuffer> framebuffer_target_;
 
-  // Protects access to the display surfaces and logical layers.
-  std::mutex layer_mutex_;
+  // Protects access to variables used by the post thread and one of the control
+  // threads (either the vr flinger dispatcher thread or the surface flinger
+  // main thread). This includes active_surfaces_, active_surfaces_updated_,
+  // post_thread_enabled_, post_thread_running_, and
+  // post_thread_quit_requested_.
+  std::mutex post_thread_mutex_;
 
-  // Active display surfaces configured by the display manager.
+  // Surfaces configured by the display manager. Written by the vr flinger
+  // dispatcher thread, read by the post thread.
+  std::vector<std::shared_ptr<DisplaySurface>> active_surfaces_;
+  // active_surfaces_updated_ is set to true by the vr flinger dispatcher thread
+  // when the list of active surfaces changes. active_surfaces_updated_ will be
+  // set back to false by the post thread when it processes the update.
+  bool active_surfaces_updated_;
+
+  // The surfaces displayed by the post thread. Used exclusively by the post
+  // thread.
   std::vector<std::shared_ptr<DisplaySurface>> display_surfaces_;
-  std::vector<std::shared_ptr<DisplaySurface>> added_display_surfaces_;
-  bool display_surfaces_updated_;
-  bool hardware_layers_need_update_;
+
+  // The surfaces rendered by the compositor. Used exclusively by the post
+  // thread.
+  std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces_;
 
   // Layer array for handling buffer flow into hardware composer layers.
   // Note that the first array is the actual storage for the layer objects,
@@ -352,31 +392,22 @@
   // hand buffers to post processing and the results to hardware composer.
   std::thread post_thread_;
 
-  enum class PostThreadState {
-    // post_thread_state_ starts off paused. When suspending, the control thread
-    // will block until post_thread_state_ == kPaused, indicating the post
-    // thread has completed the transition to paused (most importantly: no more
-    // hardware composer calls).
-    kPaused,
-    // post_thread_state_ is set to kRunning by the control thread (either
-    // surface flinger's main thread or the vr flinger dispatcher thread). The
-    // post thread blocks until post_thread_state_ == kRunning.
-    kRunning,
-    // Set by the control thread to indicate the post thread should pause. The
-    // post thread will change post_thread_state_ from kPauseRequested to
-    // kPaused when it stops.
-    kPauseRequested
-  };
-  // Control variables to control the state of the post thread
-  PostThreadState post_thread_state_;
-  // Used to wake the post thread up while it's waiting for vsync, for faster
-  // transition to the paused state.
-  pdx::LocalHandle terminate_post_thread_event_fd_;
-  // post_thread_state_mutex_ should be held before checking or modifying
-  // post_thread_state_.
-  std::mutex post_thread_state_mutex_;
+  // Set to true if the post thread is allowed to run. Surface flinger and vr
+  // flinger share access to the display, and vr flinger shouldn't use the
+  // display while surface flinger is using it. While surface flinger owns the
+  // display, post_thread_enabled_ will be set to false to indicate the post
+  // thread shouldn't run.
+  bool post_thread_enabled_;
+  // Set to true by the post thread if it's currently running.
+  bool post_thread_running_;
+  // Set to true if the post thread should quit. Only set when destroying the
+  // HardwareComposer instance.
+  bool post_thread_quit_requested_;
+  // Used to wake the post thread up while it's waiting for vsync or sleeping
+  // until EDS preemption, for faster transition to the paused state.
+  pdx::LocalHandle post_thread_interrupt_event_fd_;
   // Used to communicate between the control thread and the post thread.
-  std::condition_variable post_thread_state_cond_var_;
+  std::condition_variable post_thread_cond_var_;
 
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
@@ -410,6 +441,17 @@
   // out to display frame boundaries, so we need to tell it about vsyncs.
   DvrPose* pose_client_;
 
+  // Our history of frame times. This is used to get a better estimate of how
+  // long the next frame will take, to set a schedule for EDS.
+  FrameTimeHistory frame_time_history_;
+
+  // The backlog is used to allow us to start rendering the next frame before
+  // the previous frame has finished, and still get an accurate measurement of
+  // frame duration.
+  std::vector<FrameTimeMeasurementRecord> frame_time_backlog_;
+
+  static constexpr int kPostThreadInterrupted = 1;
+
   static void HwcRefresh(hwc2_callback_data_t data, hwc2_display_t display);
   static void HwcVSync(hwc2_callback_data_t data, hwc2_display_t display,
                        int64_t timestamp);