OSDN Git Service

Revert "Tie vr flinger to persistent vr mode"
authorJin Qian <jinqian@google.com>
Tue, 21 Mar 2017 00:04:15 +0000 (00:04 +0000)
committerJin Qian <jinqian@google.com>
Tue, 21 Mar 2017 00:04:15 +0000 (00:04 +0000)
This reverts commit f43d13e4e35ae7d3cdafc4b97c819669d42cef78.

Change-Id: Ib67db8e51b7ea2dbbe6faccce36962bf5b44a6e2

18 files changed:
include/vr/vr_manager/vr_manager.h
libs/vr/libdisplay/display_client.cpp
libs/vr/libdisplay/include/private/dvr/display_client.h
libs/vr/libdisplay/include/private/dvr/display_rpc.h
libs/vr/libvr_manager/vr_manager.cpp
libs/vr/libvrflinger/display_service.cpp
libs/vr/libvrflinger/display_service.h
libs/vr/libvrflinger/hardware_composer.cpp
libs/vr/libvrflinger/hardware_composer.h
libs/vr/libvrflinger/include/dvr/vr_flinger.h
libs/vr/libvrflinger/vr_flinger.cpp
services/surfaceflinger/Android.mk
services/surfaceflinger/SurfaceFlinger.cpp
services/surfaceflinger/SurfaceFlinger.h
services/surfaceflinger/VrStateCallbacks.cpp [new file with mode: 0644]
services/surfaceflinger/VrStateCallbacks.h [new file with mode: 0644]
services/vr/vr_window_manager/application.cpp
services/vr/vr_window_manager/application.h

index 9df2c6b..0c5da19 100644 (file)
@@ -41,28 +41,6 @@ public:
 };
 
 
-// Must be kept in sync with interface defined in
-// IPersistentVrStateCallbacks.aidl.
-
-class IPersistentVrStateCallbacks : public IInterface {
-public:
-    DECLARE_META_INTERFACE(PersistentVrStateCallbacks)
-
-    virtual void onPersistentVrStateChanged(bool enabled) = 0;
-};
-
-enum PersistentVrStateCallbacksTransaction {
-    ON_PERSISTENT_VR_STATE_CHANGED = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BnPersistentVrStateCallbacks
-        : public BnInterface<IPersistentVrStateCallbacks> {
-public:
-    status_t onTransact(uint32_t code, const Parcel& data,
-                        Parcel* reply, uint32_t flags = 0) override;
-};
-
-
 // Must be kept in sync with interface defined in IVrManager.aidl.
 
 class IVrManager : public IInterface {
@@ -71,18 +49,12 @@ public:
 
     virtual void registerListener(const sp<IVrStateCallbacks>& cb) = 0;
     virtual void unregisterListener(const sp<IVrStateCallbacks>& cb) = 0;
-    virtual void registerPersistentVrStateListener(
-        const sp<IPersistentVrStateCallbacks>& cb) = 0;
-    virtual void unregisterPersistentVrStateListener(
-        const sp<IPersistentVrStateCallbacks>& cb) = 0;
     virtual bool getVrModeState() = 0;
 };
 
 enum VrManagerTransaction {
     REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
     UNREGISTER_LISTENER,
-    REGISTER_PERSISTENT_VR_STATE_LISTENER,
-    UNREGISTER_PERSISTENT_VR_STATE_LISTENER,
     GET_VR_MODE_STATE,
 };
 
index 9a3edef..dcdd994 100644 (file)
@@ -248,6 +248,29 @@ int DisplayClient::GetLastFrameEdsTransform(LateLatchOutput* ll_out) {
   return 0;
 }
 
+int DisplayClient::EnterVrMode() {
+  auto status = InvokeRemoteMethod<DisplayRPC::EnterVrMode>();
+  if (!status) {
+    ALOGE(
+        "DisplayClient::EnterVrMode: Failed to set display service to Vr mode");
+    return -status.error();
+  }
+
+  return 0;
+}
+
+int DisplayClient::ExitVrMode() {
+  auto status = InvokeRemoteMethod<DisplayRPC::ExitVrMode>();
+  if (!status) {
+    ALOGE(
+        "DisplayClient::ExitVrMode: Failed to revert display service from Vr "
+        "mode");
+    return -status.error();
+  }
+
+  return 0;
+}
+
 std::unique_ptr<DisplaySurfaceClient> DisplayClient::CreateDisplaySurface(
     int width, int height, int format, int usage, int flags) {
   return DisplaySurfaceClient::Create(width, height, format, usage, flags);
index 3a6e3b6..e1471c3 100644 (file)
@@ -105,6 +105,9 @@ class DisplayClient : public pdx::ClientBase<DisplayClient> {
   // Pull the latest eds pose data from the display service renderer
   int GetLastFrameEdsTransform(LateLatchOutput* ll_out);
 
+  int EnterVrMode();
+  int ExitVrMode();
+
   std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
       int width, int height, int format, int usage, int flags);
 
index 2d1bbd8..465fbae 100644 (file)
@@ -217,6 +217,8 @@ struct DisplayRPC {
     kOpGetMetadataBuffer,
     kOpCreateVideoMeshSurface,
     kOpVideoMeshSurfaceCreateProducerQueue,
+    kOpEnterVrMode,
+    kOpExitVrMode,
     kOpSetViewerParams
   };
 
@@ -243,6 +245,8 @@ struct DisplayRPC {
   PDX_REMOTE_METHOD(VideoMeshSurfaceCreateProducerQueue,
                     kOpVideoMeshSurfaceCreateProducerQueue,
                     LocalChannelHandle(Void));
+  PDX_REMOTE_METHOD(EnterVrMode, kOpEnterVrMode, int(Void));
+  PDX_REMOTE_METHOD(ExitVrMode, kOpExitVrMode, int(Void));
   PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
                     void(const ViewerParams& viewer_params));
 };
index 5cfc22e..d24cbb5 100644 (file)
@@ -53,40 +53,6 @@ status_t BnVrStateCallbacks::onTransact(uint32_t code, const Parcel& data,
   return BBinder::onTransact(code, data, reply, flags);
 }
 
-// Must be kept in sync with interface defined in
-// IPersistentVrStateCallbacks.aidl.
-
-class BpPersistentVrStateCallbacks
-    : public BpInterface<IPersistentVrStateCallbacks> {
- public:
-  explicit BpPersistentVrStateCallbacks(const sp<IBinder>& impl)
-      : BpInterface<IPersistentVrStateCallbacks>(impl) {}
-
-  void onPersistentVrStateChanged(bool enabled) {
-    Parcel data, reply;
-    data.writeInterfaceToken(
-        IPersistentVrStateCallbacks::getInterfaceDescriptor());
-    data.writeBool(enabled);
-    remote()->transact(ON_PERSISTENT_VR_STATE_CHANGED,
-                       data, &reply, IBinder::FLAG_ONEWAY);
-  }
-};
-
-IMPLEMENT_META_INTERFACE(PersistentVrStateCallbacks,
-                         "android.service.vr.IPersistentVrStateCallbacks");
-
-status_t BnPersistentVrStateCallbacks::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
-  switch(code) {
-    case ON_PERSISTENT_VR_STATE_CHANGED: {
-      CHECK_INTERFACE(IPersistentVrStateCallbacks, data, reply);
-      onPersistentVrStateChanged(data.readBool());
-      return OK;
-    }
-  }
-  return BBinder::onTransact(code, data, reply, flags);
-}
-
 // Must be kept in sync with interface defined in IVrManager.aidl.
 
 class BpVrManager : public BpInterface<IVrManager> {
@@ -108,22 +74,6 @@ class BpVrManager : public BpInterface<IVrManager> {
     remote()->transact(UNREGISTER_LISTENER, data, NULL);
   }
 
-  void registerPersistentVrStateListener(
-      const sp<IPersistentVrStateCallbacks>& cb) override {
-    Parcel data;
-    data.writeInterfaceToken(IVrManager::getInterfaceDescriptor());
-    data.writeStrongBinder(IInterface::asBinder(cb));
-    remote()->transact(REGISTER_PERSISTENT_VR_STATE_LISTENER, data, NULL);
-  }
-
-  void unregisterPersistentVrStateListener(
-      const sp<IPersistentVrStateCallbacks>& cb) override {
-    Parcel data;
-    data.writeInterfaceToken(IVrManager::getInterfaceDescriptor());
-    data.writeStrongBinder(IInterface::asBinder(cb));
-    remote()->transact(UNREGISTER_PERSISTENT_VR_STATE_LISTENER, data, NULL);
-  }
-
   bool getVrModeState() override {
     Parcel data, reply;
     data.writeInterfaceToken(IVrManager::getInterfaceDescriptor());
index b5210c9..fdb84c5 100644 (file)
@@ -21,8 +21,7 @@ using android::pdx::rpc::WrapBuffer;
 namespace android {
 namespace dvr {
 
-DisplayService::DisplayService()
-    : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
 
 DisplayService::DisplayService(Hwc2::Composer* hidl)
     : BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -75,6 +74,16 @@ int DisplayService::HandleMessage(pdx::Message& message) {
           *this, &DisplayService::OnCreateSurface, message);
       return 0;
 
+    case DisplayRPC::EnterVrMode::Opcode:
+      DispatchRemoteMethod<DisplayRPC::EnterVrMode>(
+          *this, &DisplayService::OnEnterVrMode, message);
+      return 0;
+
+    case DisplayRPC::ExitVrMode::Opcode:
+      DispatchRemoteMethod<DisplayRPC::ExitVrMode>(
+          *this, &DisplayService::OnExitVrMode, message);
+      return 0;
+
     case DisplayRPC::SetViewerParams::Opcode:
       DispatchRemoteMethod<DisplayRPC::SetViewerParams>(
           *this, &DisplayService::OnSetViewerParams, message);
@@ -173,6 +182,16 @@ DisplayRPC::ByteBuffer DisplayService::OnGetEdsCapture(pdx::Message& message) {
   return WrapBuffer(std::move(buffer));
 }
 
+int DisplayService::OnEnterVrMode(pdx::Message& /*message*/) {
+  hardware_composer_.Resume();
+  return 0;
+}
+
+int DisplayService::OnExitVrMode(pdx::Message& /*message*/) {
+  hardware_composer_.Suspend();
+  return 0;
+}
+
 void DisplayService::OnSetViewerParams(pdx::Message& message,
                                        const ViewerParams& view_params) {
   Compositor* compositor = hardware_composer_.GetCompositor();
@@ -271,7 +290,7 @@ DisplayService::GetVisibleDisplaySurfaces() const {
   return visible_surfaces;
 }
 
-void DisplayService::UpdateActiveDisplaySurfaces() {
+int DisplayService::UpdateActiveDisplaySurfaces() {
   auto visible_surfaces = GetVisibleDisplaySurfaces();
 
   // Sort the surfaces based on manager z order first, then client z order.
@@ -302,8 +321,7 @@ void DisplayService::UpdateActiveDisplaySurfaces() {
     if (surface->client_blur_behind())
       blur_requested = true;
   }
-
-  hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
+  return hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
 }
 
 void DisplayService::OnHardwareComposerRefresh() {
index c93488a..9d116c1 100644 (file)
@@ -36,7 +36,7 @@ class DisplayService : public pdx::ServiceBase<DisplayService> {
 
   // Updates the list of actively displayed surfaces. This must be called after
   // any change to client/manager attributes that affect visibility or z order.
-  void UpdateActiveDisplaySurfaces();
+  int UpdateActiveDisplaySurfaces();
 
   template <class A>
   void ForEachDisplaySurface(A action) const {
@@ -60,8 +60,13 @@ class DisplayService : public pdx::ServiceBase<DisplayService> {
     return hardware_composer_.display_metrics();
   }
 
-  void GrantDisplayOwnership() { hardware_composer_.Enable(); }
-  void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
+  void SetActive(bool activated) {
+    if (activated) {
+      hardware_composer_.Resume();
+    } else {
+      hardware_composer_.Suspend();
+    }
+  }
 
   void OnHardwareComposerRefresh();
 
@@ -80,6 +85,8 @@ class DisplayService : public pdx::ServiceBase<DisplayService> {
 
   DisplayRPC::ByteBuffer OnGetEdsCapture(pdx::Message& message);
 
+  int OnEnterVrMode(pdx::Message& message);
+  int OnExitVrMode(pdx::Message& message);
   void OnSetViewerParams(pdx::Message& message, const ViewerParams& view_params);
 
   // Called by DisplaySurface to signal that a surface property has changed and
index da45859..53c2ac2 100644 (file)
@@ -103,13 +103,12 @@ HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
     : initialized_(false),
       hwc2_hidl_(hwc2_hidl),
       display_transform_(HWC_TRANSFORM_NONE),
-      active_surfaces_updated_(false),
+      display_surfaces_updated_(false),
+      hardware_layers_need_update_(false),
       active_layer_count_(0),
       gpu_layer_(nullptr),
-      post_thread_enabled_(false),
-      post_thread_running_(false),
-      post_thread_quit_requested_(false),
-      post_thread_interrupt_event_fd_(-1),
+      post_thread_state_(PostThreadState::kPaused),
+      terminate_post_thread_event_fd_(-1),
       backlight_brightness_fd_(-1),
       primary_display_vsync_event_fd_(-1),
       primary_display_wait_pp_fd_(-1),
@@ -125,12 +124,7 @@ HardwareComposer::HardwareComposer(Hwc2::Composer* hwc2_hidl)
 }
 
 HardwareComposer::~HardwareComposer(void) {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  if (post_thread_.joinable()) {
-    post_thread_quit_requested_ = true;
-    post_thread_cond_var_.notify_all();
-    post_thread_.join();
-  }
+  Suspend();
 }
 
 bool HardwareComposer::Initialize() {
@@ -173,56 +167,24 @@ bool HardwareComposer::Initialize() {
   display_transform_ = HWC_TRANSFORM_NONE;
   display_metrics_ = native_display_metrics_;
 
-  post_thread_interrupt_event_fd_.Reset(
-      eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
-  LOG_ALWAYS_FATAL_IF(
-      !post_thread_interrupt_event_fd_,
-      "HardwareComposer: Failed to create interrupt event fd : %s",
-      strerror(errno));
-
-  post_thread_ = std::thread(&HardwareComposer::PostThread, this);
-
   initialized_ = true;
 
   return initialized_;
 }
 
-void HardwareComposer::Enable() {
-  std::lock_guard<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = true;
-  post_thread_cond_var_.notify_all();
-}
-
-void HardwareComposer::Disable() {
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  post_thread_enabled_ = false;
-  if (post_thread_running_) {
-    // Write to the interrupt fd to get fast interrupt of the post thread
-    int error = eventfd_write(post_thread_interrupt_event_fd_.Get(), 1);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not write post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
-
-    post_thread_cond_var_.wait(lock, [this] { return !post_thread_running_; });
-
-    // Read the interrupt fd to clear its state
-    uint64_t interrupt_count= 0;
-    error = eventfd_read(post_thread_interrupt_event_fd_.Get(),
-                         &interrupt_count);
-    ALOGW_IF(error,
-             "HardwareComposer::Disable: could not read post "
-             "thread interrupt event fd : %s",
-             strerror(errno));
+bool HardwareComposer::Resume() {
+  std::lock_guard<std::mutex> post_thread_lock(post_thread_state_mutex_);
+  if (post_thread_state_ == PostThreadState::kRunning) {
+    return false;
   }
-}
 
-bool HardwareComposer::PostThreadHasWork() {
-  return !display_surfaces_.empty() ||
-      (active_surfaces_updated_ && !active_surfaces_.empty());
-}
+  std::lock_guard<std::mutex> layer_lock(layer_mutex_);
+
+  int32_t ret = HWC2_ERROR_NONE;
+
+  // Always turn off vsync when we start.
+  EnableVsync(false);
 
-void HardwareComposer::OnPostThreadResumed() {
   constexpr int format = HAL_PIXEL_FORMAT_RGBA_8888;
   constexpr int usage =
       GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER;
@@ -236,33 +198,97 @@ void HardwareComposer::OnPostThreadResumed() {
     layer->Initialize(hwc2_hidl_.get(), &native_display_metrics_);
   }
 
+#if ENABLE_BACKLIGHT_BRIGHTNESS
+  // TODO(hendrikw): This isn't required at the moment. It's possible that there
+  //                 is another method to access this when needed.
+  // Open the backlight brightness control sysfs node.
+  backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
+  ALOGW_IF(!backlight_brightness_fd_,
+           "HardwareComposer: Failed to open backlight brightness control: %s",
+           strerror(errno));
+#endif // ENABLE_BACKLIGHT_BRIGHTNESS
+
+  // Open the vsync event node for the primary display.
+  // TODO(eieio): Move this into a platform-specific class.
+  primary_display_vsync_event_fd_ =
+      LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
+  ALOGE_IF(!primary_display_vsync_event_fd_,
+           "HardwareComposer: Failed to open vsync event node for primary "
+           "display: %s",
+           strerror(errno));
+
+  // Open the wait pingpong status node for the primary display.
+  // TODO(eieio): Move this into a platform-specific class.
+  primary_display_wait_pp_fd_ =
+      LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
+  ALOGE_IF(
+      !primary_display_wait_pp_fd_,
+      "HardwareComposer: Failed to open wait_pp node for primary display: %s",
+      strerror(errno));
+
+  // Create a timerfd based on CLOCK_MONOTINIC.
+  vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
+  LOG_ALWAYS_FATAL_IF(
+      !vsync_sleep_timer_fd_,
+      "HardwareComposer: Failed to create vsync sleep timerfd: %s",
+      strerror(errno));
+
   // Connect to pose service.
   pose_client_ = dvrPoseCreate();
   ALOGE_IF(!pose_client_, "HardwareComposer: Failed to create pose client");
 
-  EnableVsync(true);
+  terminate_post_thread_event_fd_.Reset(
+      eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  LOG_ALWAYS_FATAL_IF(
+      !terminate_post_thread_event_fd_,
+      "HardwareComposer: Failed to create terminate PostThread event fd : %s",
+      strerror(errno));
 
-  // TODO(skiazyk): We need to do something about accessing this directly,
-  // supposedly there is a backlight service on the way.
-  // TODO(steventhomas): When we change the backlight setting, will surface
-  // flinger (or something else) set it back to its original value once we give
-  // control of the display back to surface flinger?
-  SetBacklightBrightness(255);
+  post_thread_state_ = PostThreadState::kRunning;
+  post_thread_state_cond_var_.notify_all();
 
-  // Initialize the GPU compositor.
-  LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()),
-                      "Failed to initialize the compositor");
+  // If get_id() is the default thread::id object, it has not been created yet
+  if (post_thread_.get_id() == std::thread::id()) {
+    post_thread_ = std::thread(&HardwareComposer::PostThread, this);
+  } else {
+    UpdateDisplayState();
+  }
 
-  // Trigger target-specific performance mode change.
-  property_set(kDvrPerformanceProperty, "performance");
+  return true;
 }
 
-void HardwareComposer::OnPostThreadPaused() {
+bool HardwareComposer::Suspend() {
+  std::unique_lock<std::mutex> post_thread_lock(post_thread_state_mutex_);
+  if (post_thread_state_ == PostThreadState::kPaused) {
+    return false;
+  }
+
+  post_thread_state_ = PostThreadState::kPauseRequested;
+
+  int error = eventfd_write(terminate_post_thread_event_fd_.Get(), 1);
+  ALOGE_IF(error,
+           "HardwareComposer::Suspend: could not write post "
+           "thread termination event fd : %d",
+           error);
+
+  post_thread_state_cond_var_.wait(
+      post_thread_lock,
+      [this] { return post_thread_state_ == PostThreadState::kPaused; });
+  terminate_post_thread_event_fd_.Close();
+
+  // Wait for any pending layer operations to finish
+  std::lock_guard<std::mutex> layer_lock(layer_mutex_);
+
+  EnableVsync(false);
+
+  backlight_brightness_fd_.Close();
+  primary_display_vsync_event_fd_.Close();
+  primary_display_wait_pp_fd_.Close();
+  vsync_sleep_timer_fd_.Close();
   retire_fence_fds_.clear();
   gpu_layer_ = nullptr;
 
-  // We have to destroy the layers to fully clear hwc device state before
-  // handing off back to surface flinger
+  // We have to destroy the layers before we close the hwc device
   for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
     layers_[i]->Reset();
   }
@@ -271,26 +297,12 @@ void HardwareComposer::OnPostThreadPaused() {
 
   framebuffer_target_.reset();
 
-  display_surfaces_.clear();
-  compositor_surfaces_.clear();
-
-  // Since we're clearing display_surfaces_ we'll need an update.
-  active_surfaces_updated_ = true;
+  //hwc2_hidl_.reset();
 
-  if (pose_client_) {
+  if (pose_client_)
     dvrPoseDestroy(pose_client_);
-    pose_client_ = nullptr;
-  }
-
-  EnableVsync(false);
-
-  frame_time_history_.ResetWithSeed(GuessFrameTime(0));
-  frame_time_backlog_.clear();
-
-  compositor_.Shutdown();
 
-  // Trigger target-specific performance mode change.
-  property_set(kDvrPerformanceProperty, "idle");
+  return true;
 }
 
 DisplayMetrics HardwareComposer::GetHmdDisplayMetrics() const {
@@ -507,48 +519,82 @@ void HardwareComposer::PostLayers(bool /*is_geometry_changed*/) {
   }
 }
 
-void HardwareComposer::SetDisplaySurfaces(
+// TODO(skiazyk): This is a work-around for the fact that we currently do not
+// handle the case when new surfaces are introduced when displayd is not
+// in an active state. A proper-solution will require re-structuring
+// displayd a little, but hopefully this is sufficient for now.
+// For example, could this be handled in |UpdateLayerSettings| instead?
+void HardwareComposer::UpdateDisplayState() {
+  const bool has_display_surfaces = display_surfaces_.size() > 0;
+
+  if (has_display_surfaces) {
+    EnableVsync(true);
+  }
+
+  // TODO(skiazyk): We need to do something about accessing this directly,
+  // supposedly there is a backlight service on the way.
+  SetBacklightBrightness(255);
+
+  // Trigger target-specific performance mode change.
+  property_set(kDvrPerformanceProperty, has_display_surfaces ? "performance" : "idle");
+}
+
+int HardwareComposer::SetDisplaySurfaces(
     std::vector<std::shared_ptr<DisplaySurface>> surfaces) {
+  // The double lock is necessary because we access both the display surfaces
+  // and post_thread_state_.
+  std::lock_guard<std::mutex> post_thread_state_lock(post_thread_state_mutex_);
+  std::lock_guard<std::mutex> layer_lock(layer_mutex_);
+
   ALOGI("HardwareComposer::SetDisplaySurfaces: surface count=%zd",
         surfaces.size());
-  std::unique_lock<std::mutex> lock(post_thread_mutex_);
-  active_surfaces_ = std::move(surfaces);
-  active_surfaces_updated_ = true;
-  if (post_thread_enabled_)
-    post_thread_cond_var_.notify_all();
-}
 
-int HardwareComposer::PostThreadPollInterruptible(int event_fd) {
-  pollfd pfd[2] = {
-      {
-          .fd = event_fd, .events = POLLPRI | POLLIN, .revents = 0,
-      },
-      {
-          .fd = post_thread_interrupt_event_fd_.Get(),
-          .events = POLLPRI | POLLIN,
-          .revents = 0,
-      },
-  };
-  int ret, error;
-  do {
-    ret = poll(pfd, 2, -1);
-    error = errno;
-    ALOGW_IF(ret < 0,
-             "HardwareComposer::PostThreadPollInterruptible: Error during "
-             "poll(): %s (%d)",
-             strerror(error), error);
-  } while (ret < 0 && error == EINTR);
+  // Figure out whether we need to update hardware layers. If this surface
+  // change does not add or remove hardware layers we can avoid display hiccups
+  // by gracefully updating only the GPU compositor layers.
+  // hardware_layers_need_update_ is reset to false by the Post thread.
+  int old_gpu_layer_count = 0;
+  int new_gpu_layer_count = 0;
+  // Look for new hardware layers and count new GPU layers.
+  for (const auto& surface : surfaces) {
+    if (!(surface->flags() &
+          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
+      ++new_gpu_layer_count;
+    else if (std::find(display_surfaces_.begin(), display_surfaces_.end(),
+                       surface) == display_surfaces_.end())
+      // This is a new hardware layer, we need to update.
+      hardware_layers_need_update_ = true;
+  }
+  // Look for deleted hardware layers or compositor layers.
+  for (const auto& surface : display_surfaces_) {
+    if (!(surface->flags() &
+          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
+      ++old_gpu_layer_count;
+    else if (std::find(surfaces.begin(), surfaces.end(), surface) ==
+             surfaces.end())
+      // This is a deleted hardware layer, we need to update.
+      hardware_layers_need_update_ = true;
+  }
+  // Check for compositor hardware layer transition.
+  if ((!old_gpu_layer_count && new_gpu_layer_count) ||
+      (old_gpu_layer_count && !new_gpu_layer_count))
+    hardware_layers_need_update_ = true;
 
-  if (ret < 0) {
-    return -error;
-  } else if (pfd[0].revents != 0) {
-    return 0;
-  } else if (pfd[1].revents != 0) {
-    ALOGI("VrHwcPost thread interrupted");
-    return kPostThreadInterrupted;
-  } else {
-    return 0;
+  display_surfaces_ = std::move(surfaces);
+  display_surfaces_updated_ = true;
+
+  // Set the chosen layer order for all surfaces.
+  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
+    display_surfaces_[i]->SetLayerOrder(static_cast<int>(i));
   }
+
+  // TODO(skiazyk): fix this so that it is handled seamlessly with dormant/non-
+  // dormant state.
+  if (post_thread_state_ == PostThreadState::kRunning) {
+    UpdateDisplayState();
+  }
+
+  return 0;
 }
 
 // Reads the value of the display driver wait_pingpong state. Returns 0 or 1
@@ -644,8 +690,35 @@ int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
 // Blocks until the next vsync event is signaled by the display driver.
 // TODO(eieio): This is pretty driver specific, this should be moved to a
 // separate class eventually.
-int HardwareComposer::BlockUntilVSync() {
-  return PostThreadPollInterruptible(primary_display_vsync_event_fd_.Get());
+int HardwareComposer::BlockUntilVSync(/*out*/ bool* suspend_requested) {
+  *suspend_requested = false;
+  const int event_fd = primary_display_vsync_event_fd_.Get();
+  pollfd pfd[2] = {
+      {
+          .fd = event_fd, .events = POLLPRI, .revents = 0,
+      },
+      // This extra event fd is to ensure that we can break out of this loop to
+      // pause the thread even when vsync is disabled, and thus no events on the
+      // vsync fd are being generated.
+      {
+          .fd = terminate_post_thread_event_fd_.Get(),
+          .events = POLLPRI | POLLIN,
+          .revents = 0,
+      },
+  };
+  int ret, error;
+  do {
+    ret = poll(pfd, 2, -1);
+    error = errno;
+    ALOGW_IF(ret < 0,
+             "HardwareComposer::BlockUntilVSync: Error while waiting for vsync "
+             "event: %s (%d)",
+             strerror(error), error);
+  } while (ret < 0 && error == EINTR);
+
+  if (ret >= 0 && pfd[1].revents != 0)
+    *suspend_requested = true;
+  return ret < 0 ? -error : 0;
 }
 
 // Waits for the next vsync and returns the timestamp of the vsync event. If
@@ -667,8 +740,9 @@ int HardwareComposer::WaitForVSync(int64_t* timestamp) {
 
     if (error == -EAGAIN) {
       // Vsync was turned off, wait for the next vsync event.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
+      bool suspend_requested = false;
+      error = BlockUntilVSync(&suspend_requested);
+      if (error < 0 || suspend_requested)
         return error;
 
       // Try again to get the timestamp for this new vsync interval.
@@ -691,14 +765,13 @@ int HardwareComposer::WaitForVSync(int64_t* timestamp) {
 
     if (distance_to_vsync_est > threshold_ns) {
       // Wait for vsync event notification.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
+      bool suspend_requested = false;
+      error = BlockUntilVSync(&suspend_requested);
+      if (error < 0 || suspend_requested)
         return error;
     } else {
-      // Sleep for a short time (1 millisecond) before retrying.
-      error = SleepUntil(GetSystemClockNs() + 1000000);
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
+      // Sleep for a short time before retrying.
+      std::this_thread::sleep_for(std::chrono::milliseconds(1));
     }
   }
 }
@@ -718,12 +791,21 @@ int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
     return -error;
   }
 
-  return PostThreadPollInterruptible(timer_fd);
+  // Wait for the timer by reading the expiration count.
+  uint64_t expiration_count;
+  ret = read(timer_fd, &expiration_count, sizeof(expiration_count));
+  if (ret < 0) {
+    ALOGE("HardwareComposer::SleepUntil: Failed to wait for timerfd: %s",
+          strerror(error));
+    return -error;
+  }
+
+  return 0;
 }
 
 void HardwareComposer::PostThread() {
   // NOLINTNEXTLINE(runtime/int)
-  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrHwcPost"), 0, 0, 0);
+  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("PostThread"), 0, 0, 0);
 
   // Set the scheduler to SCHED_FIFO with high priority.
   int error = dvrSetSchedulerClass(0, "graphics:high");
@@ -737,40 +819,12 @@ void HardwareComposer::PostThread() {
       "HardwareComposer::PostThread: Failed to set cpu partition: %s",
       strerror(-error));
 
-#if ENABLE_BACKLIGHT_BRIGHTNESS
-  // TODO(hendrikw): This isn't required at the moment. It's possible that there
-  //                 is another method to access this when needed.
-  // Open the backlight brightness control sysfs node.
-  backlight_brightness_fd_ = LocalHandle(kBacklightBrightnessSysFile, O_RDWR);
-  ALOGW_IF(!backlight_brightness_fd_,
-           "HardwareComposer: Failed to open backlight brightness control: %s",
-           strerror(errno));
-#endif // ENABLE_BACKLIGHT_BRIGHTNESS
-
-  // Open the vsync event node for the primary display.
-  // TODO(eieio): Move this into a platform-specific class.
-  primary_display_vsync_event_fd_ =
-      LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
-  ALOGE_IF(!primary_display_vsync_event_fd_,
-           "HardwareComposer: Failed to open vsync event node for primary "
-           "display: %s",
-           strerror(errno));
-
-  // Open the wait pingpong status node for the primary display.
-  // TODO(eieio): Move this into a platform-specific class.
-  primary_display_wait_pp_fd_ =
-      LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
-  ALOGW_IF(
-      !primary_display_wait_pp_fd_,
-      "HardwareComposer: Failed to open wait_pp node for primary display: %s",
-      strerror(errno));
+  // Force the layers to be setup at least once.
+  display_surfaces_updated_ = true;
 
-  // Create a timerfd based on CLOCK_MONOTINIC.
-  vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
-  LOG_ALWAYS_FATAL_IF(
-      !vsync_sleep_timer_fd_,
-      "HardwareComposer: Failed to create vsync sleep timerfd: %s",
-      strerror(errno));
+  // Initialize the GPU compositor.
+  LOG_ALWAYS_FATAL_IF(!compositor_.Initialize(GetHmdDisplayMetrics()),
+                      "Failed to initialize the compositor");
 
   const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
   const int64_t photon_offset_ns = GetPosePredictionTimeOffset(ns_per_frame);
@@ -784,48 +838,41 @@ void HardwareComposer::PostThread() {
   right_eye_photon_offset_ns =
       property_get_int64(kRightEyeOffsetProperty, right_eye_photon_offset_ns);
 
-  compositor_surfaces_.reserve(2);
+  // The list of surfaces the compositor should attempt to render. This is set
+  // at the start of each frame.
+  std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces;
+  compositor_surfaces.reserve(2);
 
+  // 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;
   constexpr int kFrameTimeBacklogMax = 2;
-  frame_time_backlog_.reserve(kFrameTimeBacklogMax);
+  frame_time_backlog.reserve(kFrameTimeBacklogMax);
 
   // Storage for retrieving fence info.
   FenceInfoBuffer fence_info_buffer;
 
-  bool was_running = false;
-
   while (1) {
     ATRACE_NAME("HardwareComposer::PostThread");
 
     {
-      std::unique_lock<std::mutex> lock(post_thread_mutex_);
-      while (!post_thread_enabled_ || post_thread_quit_requested_ ||
-             !PostThreadHasWork()) {
-        if (was_running) {
-          const char* pause_reason = "unknown";
-          if (!post_thread_enabled_)
-            pause_reason = "disabled";
-          else if (post_thread_quit_requested_)
-            pause_reason = "quit requested";
-          else if (!PostThreadHasWork())
-            pause_reason = "no work";
-          ALOGI("VrHwcPost thread paused. Reason: %s.", pause_reason);
-          OnPostThreadPaused();
-          was_running = false;
-        }
-        post_thread_running_ = false;
-        post_thread_cond_var_.notify_all();
-        if (post_thread_quit_requested_)
-          return;
-        post_thread_cond_var_.wait(lock);
+      std::unique_lock<std::mutex> post_thread_lock(post_thread_state_mutex_);
+      if (post_thread_state_ == PostThreadState::kPauseRequested) {
+        ALOGI("HardwareComposer::PostThread: Post thread pause requested.");
+        post_thread_state_ = PostThreadState::kPaused;
+        post_thread_state_cond_var_.notify_all();
+        post_thread_state_cond_var_.wait(
+            post_thread_lock,
+            [this] { return post_thread_state_ == PostThreadState::kRunning; });
+        // The layers will need to be updated since they were deleted previously
+        display_surfaces_updated_ = true;
+        hardware_layers_need_update_ = true;
       }
-      post_thread_running_ = true;
-    }
-
-    if (!was_running) {
-      ALOGI("VrHwcPost thread resumed");
-      OnPostThreadResumed();
-      was_running = true;
     }
 
     int64_t vsync_timestamp = 0;
@@ -840,13 +887,22 @@ void HardwareComposer::PostThread() {
           error < 0,
           "HardwareComposer::PostThread: Failed to wait for vsync event: %s",
           strerror(-error));
+
       // Don't bother processing this frame if a pause was requested
-      if (error == kPostThreadInterrupted)
+      std::lock_guard<std::mutex> post_thread_lock(post_thread_state_mutex_);
+      if (post_thread_state_ == PostThreadState::kPauseRequested) {
         continue;
+      }
     }
 
     ++vsync_count_;
 
+    static double last_print_time = -1;
+    double current_time = GetSystemClockSec();
+    if (last_print_time < 0 || current_time - last_print_time > 3) {
+      last_print_time = current_time;
+    }
+
     if (pose_client_) {
       // Signal the pose service with vsync info.
       // Display timestamp is in the middle of scanout.
@@ -855,24 +911,24 @@ void HardwareComposer::PostThread() {
                                 ns_per_frame, right_eye_photon_offset_ns);
     }
 
-    bool layer_config_changed = UpdateLayerConfig();
+    bool layer_config_changed = UpdateLayerConfig(&compositor_surfaces);
 
-    if (!was_running || layer_config_changed) {
-      frame_time_history_.ResetWithSeed(
-          GuessFrameTime(compositor_surfaces_.size()));
-      frame_time_backlog_.clear();
+    if (layer_config_changed) {
+      frame_time_history.ResetWithSeed(
+          GuessFrameTime(compositor_surfaces.size()));
+      frame_time_backlog.clear();
     } else {
-      UpdateFrameTimeHistory(&frame_time_backlog_, kFrameTimeBacklogMax,
-                             &fence_info_buffer, &frame_time_history_);
+      UpdateFrameTimeHistory(&frame_time_backlog, kFrameTimeBacklogMax,
+                             &fence_info_buffer, &frame_time_history);
     }
 
     // Get our current best estimate at how long the next frame will take to
     // render, based on how long previous frames took to render. Use this
     // estimate to decide when to wake up for EDS.
     int64_t frame_time_estimate =
-        frame_time_history_.GetSampleCount() == 0
-            ? GuessFrameTime(compositor_surfaces_.size())
-            : frame_time_history_.GetAverage();
+        frame_time_history.GetSampleCount() == 0
+            ? GuessFrameTime(compositor_surfaces.size())
+            : frame_time_history.GetAverage();
     frame_time_estimate = std::max(frame_time_estimate, kFrameTimeEstimateMin);
     DebugHudData::data.hwc_latency = frame_time_estimate;
 
@@ -902,9 +958,9 @@ void HardwareComposer::PostThread() {
 
         // There are several reasons we might skip a frame, but one possibility
         // is we mispredicted the frame time. Clear out the frame time history.
-        frame_time_history_.ResetWithSeed(
-            GuessFrameTime(compositor_surfaces_.size()));
-        frame_time_backlog_.clear();
+        frame_time_history.ResetWithSeed(
+            GuessFrameTime(compositor_surfaces.size()));
+        frame_time_backlog.clear();
         DebugHudData::data.hwc_frame_stats.SkipFrame();
 
         continue;
@@ -918,8 +974,6 @@ void HardwareComposer::PostThread() {
         error = SleepUntil(display_time_est - frame_time_estimate);
         ALOGE_IF(error < 0, "HardwareComposer::PostThread: Failed to sleep: %s",
                  strerror(-error));
-        if (error == kPostThreadInterrupted)
-          continue;
       }
     }
 
@@ -938,7 +992,7 @@ void HardwareComposer::PostThread() {
     // permanently backed up.
     PostLayers(layer_config_changed);
 
-    PostCompositorBuffers();
+    PostCompositorBuffers(compositor_surfaces);
 
     if (gpu_layer_ != nullptr) {
       // Note, with scanline racing, this draw is timed along with the post
@@ -946,88 +1000,55 @@ void HardwareComposer::PostThread() {
       LocalHandle frame_fence_fd;
       compositor_.DrawFrame(vsync_count_ + 1, &frame_fence_fd);
       if (frame_fence_fd) {
-        LOG_ALWAYS_FATAL_IF(frame_time_backlog_.size() >= kFrameTimeBacklogMax,
+        LOG_ALWAYS_FATAL_IF(frame_time_backlog.size() >= kFrameTimeBacklogMax,
                             "Frame time backlog exceeds capacity");
-        frame_time_backlog_.push_back(
+        frame_time_backlog.push_back(
             {frame_start_time, std::move(frame_fence_fd)});
       }
     } else if (!layer_config_changed) {
-      frame_time_history_.AddSample(GetSystemClockNs() - frame_start_time);
+      frame_time_history.AddSample(GetSystemClockNs() - frame_start_time);
     }
 
     HandlePendingScreenshots();
   }
+
+  // TODO(skiazyk): Currently the compositor is not fully releasing its EGL
+  // context, which seems to prevent the thread from exiting properly.
+  // This shouldn't be too hard to address, I just don't have time right now.
+  compositor_.Shutdown();
 }
 
-bool HardwareComposer::UpdateLayerConfig() {
-  std::vector<std::shared_ptr<DisplaySurface>> old_display_surfaces;
-  {
-    std::lock_guard<std::mutex> lock(post_thread_mutex_);
-    if (!active_surfaces_updated_)
-      return false;
-    old_display_surfaces = display_surfaces_;
-    display_surfaces_ = active_surfaces_;
-    active_surfaces_updated_ = false;
-  }
+bool HardwareComposer::UpdateLayerConfig(
+    std::vector<std::shared_ptr<DisplaySurface>>* compositor_surfaces) {
+  std::lock_guard<std::mutex> layer_lock(layer_mutex_);
 
-  DebugHudData::data.ResetLayers();
-
-  // Figure out whether we need to update hardware layers. If this surface
-  // change does not add or remove hardware layers we can avoid display hiccups
-  // by gracefully updating only the GPU compositor layers.
-  int old_gpu_layer_count = 0;
-  int new_gpu_layer_count = 0;
-  bool hardware_layers_need_update = false;
-  // Look for new hardware layers and count new GPU layers.
-  for (const auto& surface : display_surfaces_) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++new_gpu_layer_count;
-    else if (std::find(old_display_surfaces.begin(), old_display_surfaces.end(),
-                       surface) == old_display_surfaces.end())
-      // This is a new hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Look for deleted hardware layers or compositor layers.
-  for (const auto& surface : old_display_surfaces) {
-    if (!(surface->flags() &
-          DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION))
-      ++old_gpu_layer_count;
-    else if (std::find(display_surfaces_.begin(), display_surfaces_.end(),
-                       surface) == display_surfaces_.end())
-      // This is a deleted hardware layer, we need to update.
-      hardware_layers_need_update = true;
-  }
-  // Check for compositor hardware layer transition.
-  if ((!old_gpu_layer_count && new_gpu_layer_count) ||
-      (old_gpu_layer_count && !new_gpu_layer_count))
-    hardware_layers_need_update = true;
+  if (!display_surfaces_updated_)
+    return false;
 
-  // Set the chosen layer order for all surfaces.
-  for (size_t i = 0; i < display_surfaces_.size(); ++i) {
-    display_surfaces_[i]->SetLayerOrder(static_cast<int>(i));
-  }
+  display_surfaces_updated_ = false;
+  DebugHudData::data.ResetLayers();
 
   // Update compositor layers.
   {
     ATRACE_NAME("UpdateLayerConfig_GpuLayers");
     compositor_.UpdateSurfaces(display_surfaces_);
-    compositor_surfaces_.clear();
+    compositor_surfaces->clear();
     for (size_t i = 0; i < display_surfaces_.size(); ++i) {
       const auto& surface = display_surfaces_[i];
       if (!(surface->flags() &
             DVR_DISPLAY_SURFACE_FLAGS_DISABLE_SYSTEM_DISTORTION)) {
-        compositor_surfaces_.push_back(surface);
+        compositor_surfaces->push_back(surface);
       }
     }
   }
 
-  if (!hardware_layers_need_update)
+  if (!hardware_layers_need_update_)
     return true;
 
   // Update hardware layers.
 
   ATRACE_NAME("UpdateLayerConfig_HwLayers");
+  hardware_layers_need_update_ = false;
 
   // Update the display layers in a non-destructive fashion.
 
@@ -1158,9 +1179,10 @@ bool HardwareComposer::UpdateLayerConfig() {
   return true;
 }
 
-void HardwareComposer::PostCompositorBuffers() {
+void HardwareComposer::PostCompositorBuffers(
+    const std::vector<std::shared_ptr<DisplaySurface>>& compositor_surfaces) {
   ATRACE_NAME("PostCompositorBuffers");
-  for (const auto& surface : compositor_surfaces_) {
+  for (const auto& surface : compositor_surfaces) {
     compositor_.PostBuffer(surface);
   }
 }
index 2d3d78b..e2a8b90 100644 (file)
@@ -176,12 +176,6 @@ class Layer {
 
 // 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.
@@ -199,12 +193,8 @@ class HardwareComposer {
 
   bool IsInitialized() const { return initialized_; }
 
-  // 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();
+  bool Suspend();
+  bool Resume();
 
   // Get the HMD display metrics for the current display.
   DisplayMetrics GetHmdDisplayMetrics() const;
@@ -229,9 +219,12 @@ class HardwareComposer {
     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.
-  void SetDisplaySurfaces(
-      std::vector<std::shared_ptr<DisplaySurface>> surfaces);
+  int SetDisplaySurfaces(std::vector<std::shared_ptr<DisplaySurface>> surfaces);
 
   Compositor* GetCompositor() { return &compositor_; }
 
@@ -273,21 +266,8 @@ class HardwareComposer {
   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();
+  int BlockUntilVSync(/*out*/ bool* suspend_requested);
   int ReadVSyncTimestamp(int64_t* timestamp);
   int WaitForVSync(int64_t* timestamp);
   int SleepUntil(int64_t wakeup_timestamp);
@@ -295,18 +275,12 @@ class HardwareComposer {
   bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
 
   // Returns true if the layer config changed, false otherwise
-  bool UpdateLayerConfig();
-  void PostCompositorBuffers();
-
-  // 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();
+  bool UpdateLayerConfig(
+      std::vector<std::shared_ptr<DisplaySurface>>* compositor_surfaces);
+  void PostCompositorBuffers(
+      const std::vector<std::shared_ptr<DisplaySurface>>& compositor_surfaces);
 
-  // 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();
+  void UpdateDisplayState();
 
   struct FrameTimeMeasurementRecord {
     int64_t start_time;
@@ -350,28 +324,14 @@ class HardwareComposer {
   // Buffer for the background layer required by hardware composer.
   std::shared_ptr<IonBuffer> framebuffer_target_;
 
-  // 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_;
-
-  // 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_;
+  // Protects access to the display surfaces and logical layers.
+  std::mutex layer_mutex_;
 
-  // The surfaces rendered by the compositor. Used exclusively by the post
-  // thread.
-  std::vector<std::shared_ptr<DisplaySurface>> compositor_surfaces_;
+  // Active display surfaces configured by the display manager.
+  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_;
 
   // Layer array for handling buffer flow into hardware composer layers.
   // Note that the first array is the actual storage for the layer objects,
@@ -392,22 +352,31 @@ class HardwareComposer {
   // hand buffers to post processing and the results to hardware composer.
   std::thread post_thread_;
 
-  // 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_;
+  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_;
   // Used to communicate between the control thread and the post thread.
-  std::condition_variable post_thread_cond_var_;
+  std::condition_variable post_thread_state_cond_var_;
 
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
@@ -441,17 +410,6 @@ class HardwareComposer {
   // 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);
index 145852e..17dce96 100644 (file)
@@ -4,9 +4,6 @@
 #include <thread>
 #include <memory>
 
-#include <pdx/default_transport/service_dispatcher.h>
-#include <vr/vr_manager/vr_manager.h>
-
 namespace android {
 
 namespace Hwc2 {
@@ -19,39 +16,16 @@ class DisplayService;
 
 class VrFlinger {
  public:
-  using RequestDisplayCallback = std::function<void(bool)>;
-  static std::unique_ptr<VrFlinger> Create(
-      Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback);
-  ~VrFlinger();
-
-  // These functions are all called on surface flinger's main thread.
-  void OnBootFinished();
-  void GrantDisplayOwnership();
-  void SeizeDisplayOwnership();
+  VrFlinger();
+  int Run(Hwc2::Composer* hidl);
 
-  // Called on a binder thread.
+  void EnterVrMode();
+  void ExitVrMode();
   void OnHardwareComposerRefresh();
 
  private:
-  VrFlinger();
-  bool Init(Hwc2::Composer* hidl,
-            RequestDisplayCallback request_display_callback);
-
-  // Needs to be a separate class for binder's ref counting
-  class PersistentVrStateCallback : public BnPersistentVrStateCallbacks {
-   public:
-    PersistentVrStateCallback(RequestDisplayCallback request_display_callback)
-        : request_display_callback_(request_display_callback) {}
-    void onPersistentVrStateChanged(bool enabled) override;
-   private:
-    RequestDisplayCallback request_display_callback_;
-  };
-
-  std::thread dispatcher_thread_;
-  std::unique_ptr<android::pdx::ServiceDispatcher> dispatcher_;
+  std::thread displayd_thread_;
   std::shared_ptr<android::dvr::DisplayService> display_service_;
-  sp<PersistentVrStateCallback> persistent_vr_state_callback_;
-  RequestDisplayCallback request_display_callback_;
 };
 
 } // namespace dvr
index 21226db..9163e71 100644 (file)
@@ -9,13 +9,11 @@
 #include <unistd.h>
 #include <memory>
 
-#include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
 #include <log/log.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
 #include <private/dvr/display_client.h>
-#include <sys/prctl.h>
 #include <sys/resource.h>
 
 #include <pdx/default_transport/service_dispatcher.h>
 namespace android {
 namespace dvr {
 
-std::unique_ptr<VrFlinger> VrFlinger::Create(
-    Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
-  std::unique_ptr<VrFlinger> vr_flinger(new VrFlinger);
-  if (vr_flinger->Init(hidl, request_display_callback))
-    return vr_flinger;
-  else
-    return nullptr;
-}
-
 VrFlinger::VrFlinger() {}
 
-VrFlinger::~VrFlinger() {
-  if (persistent_vr_state_callback_.get()) {
-    sp<IVrManager> vr_manager = interface_cast<IVrManager>(
-        defaultServiceManager()->checkService(String16("vrmanager")));
-    if (vr_manager.get()) {
-      vr_manager->unregisterPersistentVrStateListener(
-          persistent_vr_state_callback_);
-    }
-  }
-
-  if (dispatcher_)
-    dispatcher_->SetCanceled(true);
-  if (dispatcher_thread_.joinable())
-    dispatcher_thread_.join();
-}
-
-bool VrFlinger::Init(Hwc2::Composer* hidl,
-                     RequestDisplayCallback request_display_callback) {
-  if (!hidl || !request_display_callback)
-    return false;
+int VrFlinger::Run(Hwc2::Composer* hidl) {
+  if (!hidl)
+    return EINVAL;
 
   std::shared_ptr<android::pdx::Service> service;
 
@@ -75,27 +47,25 @@ bool VrFlinger::Init(Hwc2::Composer* hidl,
 
   android::ProcessState::self()->startThreadPool();
 
-  request_display_callback_ = request_display_callback;
-
-  dispatcher_ =
+  std::shared_ptr<android::pdx::ServiceDispatcher> dispatcher =
       android::pdx::default_transport::ServiceDispatcher::Create();
-  CHECK_ERROR(!dispatcher_, error, "Failed to create service dispatcher.");
+  CHECK_ERROR(!dispatcher, error, "Failed to create service dispatcher.");
 
   display_service_ = android::dvr::DisplayService::Create(hidl);
   CHECK_ERROR(!display_service_, error, "Failed to create display service.");
-  dispatcher_->AddService(display_service_);
+  dispatcher->AddService(display_service_);
 
   service = android::dvr::DisplayManagerService::Create(display_service_);
   CHECK_ERROR(!service, error, "Failed to create display manager service.");
-  dispatcher_->AddService(service);
+  dispatcher->AddService(service);
 
   service = android::dvr::ScreenshotService::Create();
   CHECK_ERROR(!service, error, "Failed to create screenshot service.");
-  dispatcher_->AddService(service);
+  dispatcher->AddService(service);
 
   service = android::dvr::VSyncService::Create();
   CHECK_ERROR(!service, error, "Failed to create vsync service.");
-  dispatcher_->AddService(service);
+  dispatcher->AddService(service);
 
   display_service_->SetVSyncCallback(
       std::bind(&android::dvr::VSyncService::VSyncEvent,
@@ -103,51 +73,45 @@ bool VrFlinger::Init(Hwc2::Composer* hidl,
                 std::placeholders::_1, std::placeholders::_2,
                 std::placeholders::_3, std::placeholders::_4));
 
-  dispatcher_thread_ = std::thread([this]() {
-    prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
+  displayd_thread_ = std::thread([this, dispatcher]() {
     ALOGI("Entering message loop.");
 
-    int ret = dispatcher_->EnterDispatchLoop();
+    int ret = dispatcher->EnterDispatchLoop();
     if (ret < 0) {
       ALOGE("Dispatch loop exited because: %s\n", strerror(-ret));
     }
   });
 
-  return true;
+  return NO_ERROR;
 
 error:
-  return false;
+  display_service_.reset();
+
+  return -1;
 }
 
-void VrFlinger::OnBootFinished() {
-  sp<IVrManager> vr_manager = interface_cast<IVrManager>(
-      defaultServiceManager()->checkService(String16("vrmanager")));
-  if (vr_manager.get()) {
-    persistent_vr_state_callback_ =
-        new PersistentVrStateCallback(request_display_callback_);
-    vr_manager->registerPersistentVrStateListener(
-        persistent_vr_state_callback_);
+void VrFlinger::EnterVrMode() {
+  if (display_service_) {
+    display_service_->SetActive(true);
   } else {
-    ALOGE("Unable to register vr flinger for persistent vr mode changes");
+    ALOGE("Failed to enter VR mode : Display service is not started.");
   }
 }
 
-void VrFlinger::GrantDisplayOwnership() {
-  display_service_->GrantDisplayOwnership();
-}
-
-void VrFlinger::SeizeDisplayOwnership() {
-  display_service_->SeizeDisplayOwnership();
+void VrFlinger::ExitVrMode() {
+  if (display_service_) {
+    display_service_->SetActive(false);
+  } else {
+    ALOGE("Failed to exit VR mode : Display service is not started.");
+  }
 }
 
 void VrFlinger::OnHardwareComposerRefresh() {
-  display_service_->OnHardwareComposerRefresh();
-}
-
-void VrFlinger::PersistentVrStateCallback::onPersistentVrStateChanged(
-    bool enabled) {
-  ALOGV("Notified persistent vr mode is %s", enabled ? "on" : "off");
-  request_display_callback_(enabled);
+  if (display_service_) {
+    display_service_->OnHardwareComposerRefresh();
+  } else {
+    ALOGE("OnHardwareComposerRefresh failed : Display service is not started.");
+  }
 }
 
 }  // namespace dvr
index c87a8d9..a6ea750 100644 (file)
@@ -53,6 +53,7 @@ ifeq ($(TARGET_USES_HWC2),true)
     LOCAL_CFLAGS += -DUSE_HWC2
     LOCAL_SRC_FILES += \
         SurfaceFlinger.cpp \
+        VrStateCallbacks.cpp \
         DisplayHardware/HWComposer.cpp
     ifeq ($(TARGET_USES_HWC2ON1ADAPTER), true)
         LOCAL_CFLAGS += -DBYPASS_IHWC
index 0aaab0c..06dd903 100644 (file)
@@ -73,6 +73,7 @@
 #include "LayerDim.h"
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
+#include "VrStateCallbacks.h"
 
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
@@ -117,7 +118,6 @@ int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
 bool SurfaceFlinger::useHwcForRgbToYuv;
 uint64_t SurfaceFlinger::maxVirtualDisplaySize;
 bool SurfaceFlinger::hasSyncFramework;
-bool SurfaceFlinger::useVrFlinger;
 
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(),
@@ -136,6 +136,7 @@ SurfaceFlinger::SurfaceFlinger()
         mVisibleRegionsDirty(false),
         mGeometryInvalid(false),
         mAnimCompositionPending(false),
+        mVrModeSupported(0),
         mDebugRegion(0),
         mDebugDDMS(0),
         mDebugDisableHWC(0),
@@ -155,8 +156,10 @@ SurfaceFlinger::SurfaceFlinger()
         mFrameBuckets(),
         mTotalTime(0),
         mLastSwapTime(0),
-        mNumLayers(0),
-        mVrFlingerRequestsDisplay(false)
+        mNumLayers(0)
+#ifdef USE_HWC2
+        ,mEnterVrMode(false)
+#endif
 {
     ALOGI("SurfaceFlinger is starting");
 
@@ -181,13 +184,13 @@ SurfaceFlinger::SurfaceFlinger()
     maxVirtualDisplaySize = getUInt64<ISurfaceFlingerConfigs,
             &ISurfaceFlingerConfigs::maxVirtualDisplaySize>(0);
 
-    // Vr flinger is only enabled on Daydream ready devices.
-    useVrFlinger = getBool< ISurfaceFlingerConfigs,
-            &ISurfaceFlingerConfigs::useVrFlinger>(false);
-
     // debugging stuff...
     char value[PROPERTY_VALUE_MAX];
 
+    // TODO (urbanus): remove once b/35319396 is fixed.
+    property_get("ro.boot.vr", value, "0");
+    mVrModeSupported = atoi(value);
+
     property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
     mGpuToCpuSupported = !atoi(value);
 
@@ -228,6 +231,14 @@ SurfaceFlinger::~SurfaceFlinger()
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(display);
+
+    if (mVrStateCallbacks.get()) {
+        sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+            defaultServiceManager()->checkService(String16("vrmanager")));
+        if (vrManagerService.get()) {
+            vrManagerService->unregisterListener(mVrStateCallbacks);
+        }
+    }
 }
 
 void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
@@ -354,10 +365,6 @@ void SurfaceFlinger::bootFinished()
         window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
     }
 
-    if (mVrFlinger) {
-      mVrFlinger->OnBootFinished();
-    }
-
     // stop boot animation
     // formerly we would just kill the process, but we now ask it to exit so it
     // can choose where to stop the animation.
@@ -366,6 +373,13 @@ void SurfaceFlinger::bootFinished()
     const int LOGTAG_SF_STOP_BOOTANIM = 60110;
     LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
                    ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+
+    sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
+        defaultServiceManager()->checkService(String16("vrmanager")));
+    if (vrManagerService.get()) {
+        mVrStateCallbacks = new VrStateCallbacks(*this);
+        vrManagerService->registerListener(mVrStateCallbacks);
+    }
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -561,26 +575,13 @@ void SurfaceFlinger::init() {
     // Drop the state lock while we initialize the hardware composer. We drop
     // the lock because on creation, it will call back into SurfaceFlinger to
     // initialize the primary display.
-    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
-        "Starting with vr flinger active is not currently supported.");
+    LOG_ALWAYS_FATAL_IF(mEnterVrMode, "Starting in vr mode is not currently supported.");
     mRealHwc = new HWComposer(false);
     mHwc = mRealHwc;
     mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
 
     Mutex::Autolock _l(mStateLock);
 
-    if (useVrFlinger) {
-        auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
-            mVrFlingerRequestsDisplay = requestDisplay;
-            signalTransaction();
-        };
-        mVrFlinger = dvr::VrFlinger::Create(mHwc->getComposer(),
-                                            vrFlingerRequestDisplayCallback);
-        if (!mVrFlinger) {
-            ALOGE("Failed to start vrflinger");
-        }
-    }
-
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
 
@@ -1212,17 +1213,14 @@ void SurfaceFlinger::resetHwc() {
     // transition.
     mDrawingState.displays.clear();
     mDisplays.clear();
-    initializeDisplays();
 }
 
-void SurfaceFlinger::updateVrFlinger() {
-    if (!mVrFlinger)
-        return;
-    bool vrFlingerRequestsDisplay = mVrFlingerRequestsDisplay;
-    if (vrFlingerRequestsDisplay == mHwc->isUsingVrComposer()) {
+void SurfaceFlinger::updateVrMode() {
+    bool enteringVrMode = mEnterVrMode;
+    if (enteringVrMode == mHwc->isUsingVrComposer()) {
         return;
     }
-    if (vrFlingerRequestsDisplay && !mVrHwc) {
+    if (enteringVrMode && !mVrHwc) {
         // Construct new HWComposer without holding any locks.
         mVrHwc = new HWComposer(true);
         ALOGV("Vr HWC created");
@@ -1230,13 +1228,25 @@ void SurfaceFlinger::updateVrFlinger() {
     {
         Mutex::Autolock _l(mStateLock);
 
-        if (vrFlingerRequestsDisplay) {
+        if (enteringVrMode) {
+            // Start vrflinger thread, if it hasn't been started already.
+            if (!mVrFlinger) {
+                mVrFlinger = std::make_unique<dvr::VrFlinger>();
+                int err = mVrFlinger->Run(mHwc->getComposer());
+                if (err != NO_ERROR) {
+                    ALOGE("Failed to run vrflinger: %s (%d)", strerror(-err), err);
+                    mVrFlinger.reset();
+                    mEnterVrMode = false;
+                    return;
+                }
+            }
+
             resetHwc();
 
             mHwc = mVrHwc;
-            mVrFlinger->GrantDisplayOwnership();
+            mVrFlinger->EnterVrMode();
         } else {
-            mVrFlinger->SeizeDisplayOwnership();
+            mVrFlinger->ExitVrMode();
 
             resetHwc();
 
@@ -1258,6 +1268,12 @@ void SurfaceFlinger::onMessageReceived(int32_t what) {
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
+            // TODO(eieio): Tied to a conditional until SELinux issues
+            // are resolved.
+            if (mVrModeSupported) {
+                updateVrMode();
+            }
+
             bool frameMissed = !mHadClientComposition &&
                     mPreviousPresentFence != Fence::NO_FENCE &&
                     (mPreviousPresentFence->getSignalTime() ==
@@ -1269,11 +1285,6 @@ void SurfaceFlinger::onMessageReceived(int32_t what) {
                 break;
             }
 
-            // Now that we're going to make it to the handleMessageTransaction()
-            // call below it's safe to call updateVrFlinger(), which will
-            // potentially trigger a display handoff.
-            updateVrFlinger();
-
             bool refreshNeeded = handleMessageTransaction();
             refreshNeeded |= handleMessageInvalidate();
             refreshNeeded |= mRepaintEverything;
index e3637f5..921ecf6 100644 (file)
@@ -84,6 +84,7 @@ class RenderEngine;
 class EventControlThread;
 class VSyncSource;
 class InjectVSyncSource;
+class VrStateCallbacks;
 
 namespace dvr {
 class VrFlinger;
@@ -210,6 +211,7 @@ private:
     friend class EventThread;
     friend class Layer;
     friend class MonitoredProducer;
+    friend class VrStateCallbacks;
 
     // This value is specified in number of frames.  Log frame stats at most
     // every half hour.
@@ -530,8 +532,9 @@ private:
     void clearHwcLayers(const LayerVector& layers);
     void resetHwc();
 
-    // Check to see if we should handoff to vr flinger.
-    void updateVrFlinger();
+    // Check to see if we should change to or from vr mode, and if so, perform
+    // the handoff.
+    void updateVrMode();
 #endif
 
     /* ------------------------------------------------------------------------
@@ -601,6 +604,7 @@ private:
     DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
 
     // don't use a lock for these, we don't care
+    int mVrModeSupported;
     int mDebugRegion;
     int mDebugDDMS;
     int mDebugDisableHWC;
@@ -697,8 +701,9 @@ private:
     status_t CheckTransactCodeCredentials(uint32_t code);
 
 #ifdef USE_HWC2
-    std::atomic<bool> mVrFlingerRequestsDisplay;
-    static bool useVrFlinger;
+    sp<VrStateCallbacks> mVrStateCallbacks;
+
+    std::atomic<bool> mEnterVrMode;
 #endif
     };
 }; // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.cpp b/services/surfaceflinger/VrStateCallbacks.cpp
new file mode 100644 (file)
index 0000000..a924def
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VrStateCallbacks.h"
+#include "SurfaceFlinger.h"
+
+namespace android {
+
+VrStateCallbacks::VrStateCallbacks(SurfaceFlinger& flinger)
+    : mFlinger(flinger) {}
+
+void VrStateCallbacks::onVrStateChanged(bool enabled) {
+    mFlinger.mEnterVrMode = enabled;
+    mFlinger.signalTransaction();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/VrStateCallbacks.h b/services/surfaceflinger/VrStateCallbacks.h
new file mode 100644 (file)
index 0000000..4e655d3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_VR_STATE_CALLBACKS_H
+#define ANDROID_VR_STATE_CALLBACKS_H
+
+#include <vr/vr_manager/vr_manager.h>
+
+namespace android {
+
+class SurfaceFlinger;
+
+class VrStateCallbacks : public BnVrStateCallbacks {
+public:
+    VrStateCallbacks(SurfaceFlinger& flinger);
+    void onVrStateChanged(bool enabled) override;
+
+private:
+    SurfaceFlinger& mFlinger;
+};
+
+} // namespace android
+
+#endif // ANDROID_VR_STATE_CALLBACKS_H
index 3dfd9f1..eb9f407 100644 (file)
@@ -25,7 +25,7 @@ Application::~Application() {
   sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
       defaultServiceManager()->getService(String16("vrmanager")));
   if (vrManagerService.get()) {
-    vrManagerService->unregisterPersistentVrStateListener(vr_mode_listener_);
+    vrManagerService->unregisterListener(vr_mode_listener_);
   }
 }
 
@@ -39,7 +39,7 @@ int Application::Initialize() {
   sp<IVrManager> vrManagerService = interface_cast<IVrManager>(
       defaultServiceManager()->getService(String16("vrmanager")));
   if (vrManagerService.get()) {
-    vrManagerService->registerPersistentVrStateListener(vr_mode_listener_);
+    vrManagerService->registerListener(vr_mode_listener_);
   }
   return 0;
 }
@@ -315,7 +315,7 @@ void Application::QueueTask(MainThreadTask task) {
   wake_up_init_and_render_.notify_one();
 }
 
-void Application::VrModeListener::onPersistentVrStateChanged(bool enabled) {
+void Application::VrModeListener::onVrStateChanged(bool enabled) {
   if (!enabled)
     app_->QueueTask(MainThreadTask::ExitingVrMode);
 }
index 4b36ecc..6215561 100644 (file)
@@ -44,10 +44,10 @@ class Application {
     Show,
   };
 
-  class VrModeListener : public BnPersistentVrStateCallbacks {
+  class VrModeListener : public BnVrStateCallbacks {
    public:
     VrModeListener(Application *app) : app_(app) {}
-    void onPersistentVrStateChanged(bool enabled) override;
+    void onVrStateChanged(bool enabled) override;
 
    private:
     Application *app_;