Use a separate hwcomposer hidl instance for vr flinger

Improve robustness of vr flinger <--> surface flinger switching by
having vr flinger use a separate hardware composer hidl instance instead
of sharing the instance with surface flinger. Sharing the hardware
composer instance has proven to be error prone, with situations where
both the vr flinger thread and surface flinger main thread would write
to the composer at the same time, causing hard to diagnose
crashes (b/62925812).

Instead of sharing the hardware composer instance, when switching to vr
flinger we now delete the existing instance, create a new instance
directed to the vr hardware composer shim, and vr flinger creates its
own composer instance connected to the real hardware composer. By
creating a separate composer instance for vr flinger, crashes like the
ones found in b/62925812 are no longer impossible.

Most of the changes in this commit are related to enabling surface
flinger to delete HWComposer instances cleanly. In particular:

- Previously the hardware composer callbacks (which come in on a
  hwbinder thread) would land in HWC2::Device and bubble up to the
  SurfaceFlinger object. But with the new behavior the HWC2::Device
  might be dead or in the process of being destroyed, so instead we have
  SurfaceFlinger receive the composer callbacks directly, and forward
  them to HWComposer and HWC2::Device. We include a composer id field in
  the callbacks so surface flinger can ignore stale callbacks from dead
  composer instances.

- Object ownership for HWC2::Display and HWC2::Layer was shared by
  passing around shared_ptrs to these objects. This was problematic
  because they referenced and used the HWC2::Device, which can now be
  destroyed when switching to vr flinger. Simplify the ownership model
  by having HWC2::Device own (via unique_ptr<>) instances of
  HWC2::Display, which owns (again via unique_ptr<>) instances of
  HWC2::Layer. In cases where we previously passed std::shared_ptr<> to
  HWC2::Display or HWC2::Layer, instead pass non-owning HWC2::Display*
  and HWC2::Layer* pointers. This ensures clean composer instance
  teardown with no stale references to the deleted HWC2::Device.

- When the hardware composer instance is destroyed and the HWC2::Layers
  are removed, notify the android::Layer via a callback, so it can
  remove the HWC2::Layer from its internal table of hardware composer
  layers. This removes the burden to explicitly clear out all hardware
  composer layers when switching to vr flinger, which has been a source
  of bugs.

- We were missing an mStateLock lock in
  SurfaceFlinger::setVsyncEnabled(), which was necessary to ensure we
  were setting vsync on the correct hardware composer instance. Once
  that lock was added, surface flinger would sometimes deadlock when
  transitioning to vr flinger, because the surface flinger main thread
  would acquire mStateLock and then EventControlThread::mMutex, whereas
  the event control thread would acquire the locks in the opposite
  order. The changes in EventControlThread.cpp are to ensure it doesn't
  hold a lock on EventControlThread::mMutex while calling
  setVsyncEnabled(), to avoid the deadlock.

I found that without a composer callback registered in vr flinger the
vsync_event file wasn't getting vsync timestamps written, so vr flinger
would get stuck in an infinite loop trying to parse a vsync
timestamp. Since we need to have a callback anyway I changed the code in
hardware_composer.cpp to get the vsync timestamp from the callback, as
surface flinger does. I confirmed the timestamps are the same with
either method, and this lets us remove some extra code for extracting
the vsync timestamp that (probably) wasn't compatible with all devices
we want to run on anyway. I also added a timeout to the vysnc wait so
we'll see an error message in the log if we fail to wait for vsync,
instead of looping forever.

Bug: 62925812

Test: - Confirmed surface flinger <--> vr flinger switching is robust by
        switching devices on and off hundreds of times and observing no
        hardware composer related issues, surface flinger crashes, or
        hardware composer service crashes.

- Confirmed 2d in vr works as before by going through the OOBE flow on a
  standalone. This also exercises virtual display creation and usage
  through surface flinger.

- Added logs to confirm perfect layer/display cleanup when destroying
  hardware composer instances.

- Tested normal 2d phone usage to confirm basic layer create/destroy
  functionality works as before.

- Monitored surface flinger file descriptor usage across dozens of
  surface flinger <--> vr flinger transitions and observed no file
  descriptor leaks.

- Confirmed the HWC1 code path still compiles.

- Ran the surface flinger tests and confirmed there are no new test
  failures.

- Ran the hardware composer hidl in passthrough mode on a Marlin and
  confirmed it works.

- Ran CTS tests for virtual displays and confirmed they all pass.

- Tested Android Auto and confirmed basic graphics functionality still
  works.

Change-Id: Ibf1dbdf3ec15ca66467697d711f8109dc9e46a47
Merged-In: I17dc0e060bfb5cb447ffbaa573b279fc6d2d8bd1
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 733edc6..f350762 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -40,10 +40,8 @@
 DisplayService::DisplayService(Hwc2::Composer* hidl,
                                RequestDisplayCallback request_display_callback)
     : BASE("DisplayService",
-           Endpoint::Create(display::DisplayProtocol::kClientPath)),
-      hardware_composer_(hidl, request_display_callback),
-      request_display_callback_(request_display_callback) {
-  hardware_composer_.Initialize();
+           Endpoint::Create(display::DisplayProtocol::kClientPath)) {
+  hardware_composer_.Initialize(hidl, request_display_callback);
 }
 
 bool DisplayService::IsInitialized() const {
@@ -398,10 +396,6 @@
   return {0};
 }
 
-void DisplayService::OnHardwareComposerRefresh() {
-  hardware_composer_.OnHardwareComposerRefresh();
-}
-
 void DisplayService::SetDisplayConfigurationUpdateNotifier(
     DisplayConfigurationUpdateNotifier update_notifier) {
   update_notifier_ = update_notifier;
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 6efe264..55e33ab 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -72,8 +72,6 @@
   void GrantDisplayOwnership() { hardware_composer_.Enable(); }
   void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
 
-  void OnHardwareComposerRefresh();
-
  private:
   friend BASE;
   friend DisplaySurface;
@@ -119,7 +117,6 @@
   pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
 
   HardwareComposer hardware_composer_;
-  RequestDisplayCallback request_display_callback_;
   EpollEventDispatcher dispatcher_;
   DisplayConfigurationUpdateNotifier update_notifier_;
 
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 11c1370..f9a5dcd 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -28,6 +28,8 @@
 #include <private/dvr/clock_ns.h>
 #include <private/dvr/ion_buffer.h>
 
+using android::hardware::Return;
+using android::hardware::Void;
 using android::pdx::LocalHandle;
 using android::pdx::rpc::EmptyVariant;
 using android::pdx::rpc::IfAnyOf;
@@ -42,9 +44,6 @@
 const char kBacklightBrightnessSysFile[] =
     "/sys/class/leds/lcd-backlight/brightness";
 
-const char kPrimaryDisplayVSyncEventFile[] =
-    "/sys/class/graphics/fb0/vsync_event";
-
 const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
 
 const char kDvrPerformanceProperty[] = "sys.dvr.performance";
@@ -86,22 +85,11 @@
 
 }  // anonymous namespace
 
-// Layer static data.
-Hwc2::Composer* Layer::hwc2_hidl_;
-const HWCDisplayMetrics* Layer::display_metrics_;
-
 // HardwareComposer static data;
 constexpr size_t HardwareComposer::kMaxHardwareLayers;
 
 HardwareComposer::HardwareComposer()
-    : HardwareComposer(nullptr, RequestDisplayCallback()) {}
-
-HardwareComposer::HardwareComposer(
-    Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
-    : initialized_(false),
-      hwc2_hidl_(hwc2_hidl),
-      request_display_callback_(request_display_callback),
-      callbacks_(new ComposerCallback) {}
+    : initialized_(false), request_display_callback_(nullptr) {}
 
 HardwareComposer::~HardwareComposer(void) {
   UpdatePostThreadState(PostThreadState::Quit, true);
@@ -109,16 +97,19 @@
     post_thread_.join();
 }
 
-bool HardwareComposer::Initialize() {
+bool HardwareComposer::Initialize(
+    Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
   if (initialized_) {
     ALOGE("HardwareComposer::Initialize: already initialized.");
     return false;
   }
 
+  request_display_callback_ = request_display_callback;
+
   HWC::Error error = HWC::Error::None;
 
   Hwc2::Config config;
-  error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+  error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
 
   if (error != HWC::Error::None) {
     ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -126,8 +117,8 @@
     return false;
   }
 
-  error =
-      GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
+  error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config,
+                            &native_display_metrics_);
 
   if (error != HWC::Error::None) {
     ALOGE(
@@ -149,9 +140,6 @@
   display_transform_ = HWC_TRANSFORM_NONE;
   display_metrics_ = native_display_metrics_;
 
-  // Pass hwc instance and metrics to setup globals for Layer.
-  Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
-
   post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
   LOG_ALWAYS_FATAL_IF(
       !post_thread_event_fd_,
@@ -210,15 +198,11 @@
 }
 
 void HardwareComposer::OnPostThreadResumed() {
-  hwc2_hidl_->resetCommands();
+  hidl_.reset(new Hwc2::Composer("default"));
+  hidl_callback_ = new ComposerCallback;
+  hidl_->registerCallback(hidl_callback_);
 
-  // HIDL HWC seems to have an internal race condition. If we submit a frame too
-  // soon after turning on VSync we don't get any VSync signals. Give poor HWC
-  // implementations a chance to enable VSync before we continue.
-  EnableVsync(false);
-  std::this_thread::sleep_for(100ms);
   EnableVsync(true);
-  std::this_thread::sleep_for(100ms);
 
   // TODO(skiazyk): We need to do something about accessing this directly,
   // supposedly there is a backlight service on the way.
@@ -240,9 +224,12 @@
   }
   active_layer_count_ = 0;
 
-  EnableVsync(false);
+  if (hidl_) {
+    EnableVsync(false);
+  }
 
-  hwc2_hidl_->resetCommands();
+  hidl_callback_ = nullptr;
+  hidl_.reset(nullptr);
 
   // Trigger target-specific performance mode change.
   property_set(kDvrPerformanceProperty, "idle");
@@ -252,21 +239,21 @@
   uint32_t num_types;
   uint32_t num_requests;
   HWC::Error error =
-      hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+      hidl_->validateDisplay(display, &num_types, &num_requests);
 
   if (error == HWC2_ERROR_HAS_CHANGES) {
     // TODO(skiazyk): We might need to inspect the requested changes first, but
     // so far it seems like we shouldn't ever hit a bad state.
     // error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
     //                                               display);
-    error = hwc2_hidl_->acceptDisplayChanges(display);
+    error = hidl_->acceptDisplayChanges(display);
   }
 
   return error;
 }
 
-int32_t HardwareComposer::EnableVsync(bool enabled) {
-  return (int32_t)hwc2_hidl_->setVsyncEnabled(
+HWC::Error HardwareComposer::EnableVsync(bool enabled) {
+  return hidl_->setVsyncEnabled(
       HWC_DISPLAY_PRIMARY,
       (Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
                                              : HWC2_VSYNC_DISABLE));
@@ -274,7 +261,7 @@
 
 HWC::Error HardwareComposer::Present(hwc2_display_t display) {
   int32_t present_fence;
-  HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
+  HWC::Error error = hidl_->presentDisplay(display, &present_fence);
 
   // According to the documentation, this fence is signaled at the time of
   // vsync/DMA for physical displays.
@@ -288,20 +275,21 @@
   return error;
 }
 
-HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl,
+                                                 hwc2_display_t display,
                                                  hwc2_config_t config,
                                                  hwc2_attribute_t attribute,
                                                  int32_t* out_value) const {
-  return hwc2_hidl_->getDisplayAttribute(
+  return hidl->getDisplayAttribute(
       display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
 }
 
 HWC::Error HardwareComposer::GetDisplayMetrics(
-    hwc2_display_t display, hwc2_config_t config,
+    Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config,
     HWCDisplayMetrics* out_metrics) const {
   HWC::Error error;
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+  error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH,
                               &out_metrics->width);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -310,7 +298,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+  error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT,
                               &out_metrics->height);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -319,7 +307,8 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+  error = GetDisplayAttribute(hidl, display, config,
+                              HWC2_ATTRIBUTE_VSYNC_PERIOD,
                               &out_metrics->vsync_period_ns);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -328,7 +317,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+  error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X,
                               &out_metrics->dpi.x);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -337,7 +326,7 @@
     return error;
   }
 
-  error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+  error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y,
                               &out_metrics->dpi.y);
   if (error != HWC::Error::None) {
     ALOGE(
@@ -374,7 +363,7 @@
 
   if (post_thread_resumed_) {
     stream << "Hardware Composer Debug Info:" << std::endl;
-    stream << hwc2_hidl_->dumpDebugInfo();
+    stream << hidl_->dumpDebugInfo();
   }
 
   return stream.str();
@@ -446,8 +435,8 @@
 
   std::vector<Hwc2::Layer> out_layers;
   std::vector<int> out_fences;
-  error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
-                                       &out_fences);
+  error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+                                  &out_fences);
   ALOGE_IF(error != HWC::Error::None,
            "HardwareComposer::PostLayers: Failed to get release fences: %s",
            error.to_string().c_str());
@@ -546,7 +535,7 @@
 }
 
 int HardwareComposer::PostThreadPollInterruptible(
-    const pdx::LocalHandle& event_fd, int requested_events) {
+    const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
   pollfd pfd[2] = {
       {
           .fd = event_fd.Get(),
@@ -561,7 +550,7 @@
   };
   int ret, error;
   do {
-    ret = poll(pfd, 2, -1);
+    ret = poll(pfd, 2, timeout_ms);
     error = errno;
     ALOGW_IF(ret < 0,
              "HardwareComposer::PostThreadPollInterruptible: Error during "
@@ -571,6 +560,8 @@
 
   if (ret < 0) {
     return -error;
+  } else if (ret == 0) {
+    return -ETIMEDOUT;
   } else if (pfd[0].revents != 0) {
     return 0;
   } else if (pfd[1].revents != 0) {
@@ -623,114 +614,17 @@
   }
 }
 
-// Reads the timestamp of the last vsync from the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
-  const int event_fd = primary_display_vsync_event_fd_.Get();
-  int ret, error;
-
-  // The driver returns data in the form "VSYNC=<timestamp ns>".
-  std::array<char, 32> data;
-  data.fill('\0');
-
-  // Seek back to the beginning of the event file.
-  ret = lseek(event_fd, 0, SEEK_SET);
-  if (ret < 0) {
-    error = errno;
-    ALOGE(
-        "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  // Read the vsync event timestamp.
-  ret = read(event_fd, data.data(), data.size());
-  if (ret < 0) {
-    error = errno;
-    ALOGE_IF(
-        error != EAGAIN,
-        "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  ret = sscanf(data.data(), "VSYNC=%" PRIu64,
-               reinterpret_cast<uint64_t*>(timestamp));
-  if (ret < 0) {
-    error = errno;
-    ALOGE(
-        "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
-        "%s",
-        strerror(error));
-    return -error;
-  }
-
-  return 0;
-}
-
-// 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() {
-  // Vsync is signaled by POLLPRI on the fb vsync node.
-  return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
-}
-
 // Waits for the next vsync and returns the timestamp of the vsync event. If
 // vsync already passed since the last call, returns the latest vsync timestamp
-// instead of blocking. This method updates the last_vsync_timeout_ in the
-// process.
-//
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
+// instead of blocking.
 int HardwareComposer::WaitForVSync(int64_t* timestamp) {
-  int error;
-
-  // Get the current timestamp and decide what to do.
-  while (true) {
-    int64_t current_vsync_timestamp;
-    error = ReadVSyncTimestamp(&current_vsync_timestamp);
-    if (error < 0 && error != -EAGAIN)
-      return error;
-
-    if (error == -EAGAIN) {
-      // Vsync was turned off, wait for the next vsync event.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-
-      // Try again to get the timestamp for this new vsync interval.
-      continue;
-    }
-
-    // Check that we advanced to a later vsync interval.
-    if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
-      *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
-      return 0;
-    }
-
-    // See how close we are to the next expected vsync. If we're within 1ms,
-    // sleep for 1ms and try again.
-    const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
-    const int64_t threshold_ns = 1000000;  // 1ms
-
-    const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
-    const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
-
-    if (distance_to_vsync_est > threshold_ns) {
-      // Wait for vsync event notification.
-      error = BlockUntilVSync();
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-    } else {
-      // Sleep for a short time (1 millisecond) before retrying.
-      error = SleepUntil(GetSystemClockNs() + threshold_ns);
-      if (error < 0 || error == kPostThreadInterrupted)
-        return error;
-    }
+  int error = PostThreadPollInterruptible(
+      hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000);
+  if (error == kPostThreadInterrupted || error < 0) {
+    return error;
+  } else {
+    *timestamp = hidl_callback_->GetVsyncTime();
+    return 0;
   }
 }
 
@@ -749,7 +643,8 @@
     return -error;
   }
 
-  return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
+  return PostThreadPollInterruptible(
+      vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
 }
 
 void HardwareComposer::PostThread() {
@@ -772,15 +667,6 @@
            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_ =
@@ -951,7 +837,8 @@
     // The bottom layer is opaque, other layers blend.
     HWC::BlendMode blending =
         layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
-    layers_[layer_index].Setup(surfaces[layer_index], blending,
+    layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_,
+                               hidl_.get(), blending,
                                display_transform_, HWC::Composition::Device,
                                layer_index);
     display_surfaces_.push_back(surfaces[layer_index]);
@@ -979,30 +866,6 @@
   vsync_callback_ = callback;
 }
 
-void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
-                                  hwc2_display_t /*display*/) {
-  // TODO(eieio): implement invalidate callbacks.
-}
-
-void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
-                                hwc2_display_t /*display*/,
-                                int64_t /*timestamp*/) {
-  ATRACE_NAME(__PRETTY_FUNCTION__);
-  // Intentionally empty. HWC may require a callback to be set to enable vsync
-  // signals. We bypass this callback thread by monitoring the vsync event
-  // directly, but signals still need to be enabled.
-}
-
-void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
-                                  hwc2_display_t /*display*/,
-                                  hwc2_connection_t /*connected*/) {
-  // TODO(eieio): implement display hotplug callbacks.
-}
-
-void HardwareComposer::OnHardwareComposerRefresh() {
-  // TODO(steventhomas): Handle refresh.
-}
-
 void HardwareComposer::SetBacklightBrightness(int brightness) {
   if (backlight_brightness_fd_) {
     std::array<char, 32> text;
@@ -1011,18 +874,59 @@
   }
 }
 
-void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
-                              const HWCDisplayMetrics* metrics) {
-  hwc2_hidl_ = hwc2_hidl;
-  display_metrics_ = metrics;
+HardwareComposer::ComposerCallback::ComposerCallback() {
+  vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+  LOG_ALWAYS_FATAL_IF(
+      !vsync_event_fd_,
+      "Failed to create vsync event fd : %s",
+      strerror(errno));
+}
+
+Return<void> HardwareComposer::ComposerCallback::onHotplug(
+    Hwc2::Display /*display*/,
+    IComposerCallback::Connection /*conn*/) {
+  return Void();
+}
+
+Return<void> HardwareComposer::ComposerCallback::onRefresh(
+    Hwc2::Display /*display*/) {
+  return hardware::Void();
+}
+
+Return<void> HardwareComposer::ComposerCallback::onVsync(
+    Hwc2::Display display, int64_t timestamp) {
+  if (display == HWC_DISPLAY_PRIMARY) {
+    std::lock_guard<std::mutex> lock(vsync_mutex_);
+    vsync_time_ = timestamp;
+    int error = eventfd_write(vsync_event_fd_.Get(), 1);
+    LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd");
+  }
+  return Void();
+}
+
+const pdx::LocalHandle&
+HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
+  return vsync_event_fd_;
+}
+
+int64_t HardwareComposer::ComposerCallback::GetVsyncTime() {
+  std::lock_guard<std::mutex> lock(vsync_mutex_);
+  eventfd_t event;
+  eventfd_read(vsync_event_fd_.Get(), &event);
+  LOG_ALWAYS_FATAL_IF(vsync_time_ < 0,
+                      "Attempt to read vsync time before vsync event");
+  int64_t return_val = vsync_time_;
+  vsync_time_ = -1;
+  return return_val;
 }
 
 void Layer::Reset() {
-  if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
-    hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+  if (hidl_ != nullptr && hardware_composer_layer_) {
+    hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
     hardware_composer_layer_ = 0;
   }
 
+  hidl_ = nullptr;
   z_order_ = 0;
   blending_ = HWC::BlendMode::None;
   transform_ = HWC::Transform::None;
@@ -1034,29 +938,35 @@
 }
 
 void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
-                  HWC::BlendMode blending, HWC::Transform transform,
-                  HWC::Composition composition_type, size_t z_order) {
+                  const HWCDisplayMetrics& display_metrics,
+                  Hwc2::Composer* hidl, HWC::BlendMode blending,
+                  HWC::Transform transform, HWC::Composition composition_type,
+                  size_t z_order) {
   Reset();
+  hidl_ = hidl;
   z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
   composition_type_ = HWC::Composition::Invalid;
   target_composition_type_ = composition_type;
   source_ = SourceSurface{surface};
-  CommonLayerSetup();
+  CommonLayerSetup(display_metrics);
 }
 
 void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
-                  HWC::BlendMode blending, HWC::Transform transform,
-                  HWC::Composition composition_type, size_t z_order) {
+                  const HWCDisplayMetrics& display_metrics,
+                  Hwc2::Composer* hidl, HWC::BlendMode blending,
+                  HWC::Transform transform, HWC::Composition composition_type,
+                  size_t z_order) {
   Reset();
+  hidl_ = hidl;
   z_order_ = z_order;
   blending_ = blending;
   transform_ = transform;
   composition_type_ = HWC::Composition::Invalid;
   target_composition_type_ = composition_type;
   source_ = SourceBuffer{buffer};
-  CommonLayerSetup();
+  CommonLayerSetup(display_metrics);
 }
 
 void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
@@ -1076,7 +986,7 @@
   return source_.Visit(Visitor{});
 }
 
-void Layer::UpdateLayerSettings() {
+void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) {
   if (!IsLayerSetup()) {
     ALOGE(
         "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
@@ -1087,7 +997,7 @@
   HWC::Error error;
   hwc2_display_t display = HWC_DISPLAY_PRIMARY;
 
-  error = hwc2_hidl_->setLayerCompositionType(
+  error = hidl_->setLayerCompositionType(
       display, hardware_composer_layer_,
       composition_type_.cast<Hwc2::IComposerClient::Composition>());
   ALOGE_IF(
@@ -1095,7 +1005,7 @@
       "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
       error.to_string().c_str());
 
-  error = hwc2_hidl_->setLayerBlendMode(
+  error = hidl_->setLayerBlendMode(
       display, hardware_composer_layer_,
       blending_.cast<Hwc2::IComposerClient::BlendMode>());
   ALOGE_IF(error != HWC::Error::None,
@@ -1104,41 +1014,39 @@
 
   // TODO(eieio): Use surface attributes or some other mechanism to control
   // the layer display frame.
-  error = hwc2_hidl_->setLayerDisplayFrame(
+  error = hidl_->setLayerDisplayFrame(
       display, hardware_composer_layer_,
-      {0, 0, display_metrics_->width, display_metrics_->height});
+      {0, 0, display_metrics.width, display_metrics.height});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer display frame: %s",
            error.to_string().c_str());
 
-  error = hwc2_hidl_->setLayerVisibleRegion(
+  error = hidl_->setLayerVisibleRegion(
       display, hardware_composer_layer_,
-      {{0, 0, display_metrics_->width, display_metrics_->height}});
+      {{0, 0, display_metrics.width, display_metrics.height}});
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer visible region: %s",
            error.to_string().c_str());
 
-  error =
-      hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+  error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
            error.to_string().c_str());
 
-  error =
-      hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+  error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
   ALOGE_IF(error != HWC::Error::None,
            "Layer::UpdateLayerSettings: Error setting z_ order: %s",
            error.to_string().c_str());
 }
 
-void Layer::CommonLayerSetup() {
+void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) {
   HWC::Error error =
-      hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+      hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
   ALOGE_IF(
       error != HWC::Error::None,
       "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
       error.to_string().c_str());
-  UpdateLayerSettings();
+  UpdateLayerSettings(display_metrics);
 }
 
 void Layer::Prepare() {
@@ -1157,12 +1065,12 @@
   if (!handle.get()) {
     if (composition_type_ == HWC::Composition::Invalid) {
       composition_type_ = HWC::Composition::SolidColor;
-      hwc2_hidl_->setLayerCompositionType(
+      hidl_->setLayerCompositionType(
           HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
       Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
-      hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
-                                layer_color);
+      hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+                           layer_color);
     } else {
       // The composition type is already set. Nothing else to do until a
       // buffer arrives.
@@ -1170,15 +1078,15 @@
   } else {
     if (composition_type_ != target_composition_type_) {
       composition_type_ = target_composition_type_;
-      hwc2_hidl_->setLayerCompositionType(
+      hidl_->setLayerCompositionType(
           HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
           composition_type_.cast<Hwc2::IComposerClient::Composition>());
     }
 
     HWC::Error error{HWC::Error::None};
-    error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
-                                       hardware_composer_layer_, 0, handle,
-                                       acquire_fence_.Get());
+    error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+                                  hardware_composer_layer_, 0, handle,
+                                  acquire_fence_.Get());
 
     ALOGE_IF(error != HWC::Error::None,
              "Layer::Prepare: Error setting layer buffer: %s",
@@ -1187,9 +1095,9 @@
     if (!surface_rect_functions_applied_) {
       const float float_right = right;
       const float float_bottom = bottom;
-      error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
-                                             hardware_composer_layer_,
-                                             {0, 0, float_right, float_bottom});
+      error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+                                        hardware_composer_layer_,
+                                        {0, 0, float_right, float_bottom});
 
       ALOGE_IF(error != HWC::Error::None,
                "Layer::Prepare: Error setting layer source crop: %s",
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index a0c50e1..fc0efee 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -54,11 +54,6 @@
  public:
   Layer() {}
 
-  // Sets up the global state used by all Layer instances. This must be called
-  // before using any Layer methods.
-  static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
-                                const HWCDisplayMetrics* metrics);
-
   // Releases any shared pointers and fence handles held by this instance.
   void Reset();
 
@@ -72,6 +67,7 @@
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
   // |index| is the index of this surface in the DirectDisplaySurface array.
   void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+             const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
              HWC::BlendMode blending, HWC::Transform transform,
              HWC::Composition composition_type, size_t z_roder);
 
@@ -83,9 +79,10 @@
   // |transform| receives HWC_TRANSFORM_* values.
   // |composition_type| receives either HWC_FRAMEBUFFER for most layers or
   // HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
-  void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
-             HWC::Transform transform, HWC::Composition composition_type,
-             size_t z_order);
+  void Setup(const std::shared_ptr<IonBuffer>& buffer,
+             const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
+             HWC::BlendMode blending, HWC::Transform transform,
+             HWC::Composition composition_type, size_t z_order);
 
   // Layers that use a direct IonBuffer should call this each frame to update
   // which buffer will be used for the next PostLayers.
@@ -121,7 +118,7 @@
   bool IsLayerSetup() const { return !source_.empty(); }
 
   // Applies all of the settings to this layer using the hwc functions
-  void UpdateLayerSettings();
+  void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics);
 
   int GetSurfaceId() const {
     int surface_id = -1;
@@ -142,10 +139,9 @@
   }
 
  private:
-  void CommonLayerSetup();
+  void CommonLayerSetup(const HWCDisplayMetrics& display_metrics);
 
-  static Hwc2::Composer* hwc2_hidl_;
-  static const HWCDisplayMetrics* display_metrics_;
+  Hwc2::Composer* hidl_ = nullptr;
 
   // The hardware composer layer and metrics to use during the prepare cycle.
   hwc2_layer_t hardware_composer_layer_ = 0;
@@ -263,11 +259,10 @@
   static constexpr size_t kMaxHardwareLayers = 4;
 
   HardwareComposer();
-  HardwareComposer(Hwc2::Composer* hidl,
-                   RequestDisplayCallback request_display_callback);
   ~HardwareComposer();
 
-  bool Initialize();
+  bool Initialize(Hwc2::Composer* hidl,
+                  RequestDisplayCallback request_display_callback);
 
   bool IsInitialized() const { return initialized_; }
 
@@ -281,11 +276,6 @@
   // Get the HMD display metrics for the current display.
   display::Metrics GetHmdDisplayMetrics() const;
 
-  HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
-                                 hwc2_attribute_t attributes,
-                                 int32_t* out_value) const;
-  HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
-                               HWCDisplayMetrics* out_metrics) const;
   std::string Dump();
 
   void SetVSyncCallback(VSyncCallback callback);
@@ -308,34 +298,31 @@
   int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
   void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
 
-  void OnHardwareComposerRefresh();
-
  private:
-  int32_t EnableVsync(bool enabled);
+  HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display,
+                                 hwc2_config_t config,
+                                 hwc2_attribute_t attributes,
+                                 int32_t* out_value) const;
+  HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display,
+                               hwc2_config_t config,
+                               HWCDisplayMetrics* out_metrics) const;
+
+  HWC::Error EnableVsync(bool enabled);
 
   class ComposerCallback : public Hwc2::IComposerCallback {
    public:
-    ComposerCallback() {}
-
-    hardware::Return<void> onHotplug(Hwc2::Display /*display*/,
-                                     Connection /*connected*/) override {
-      // TODO(skiazyk): depending on how the server is implemented, we might
-      // have to set it up to synchronize with receiving this event, as it can
-      // potentially be a critical event for setting up state within the
-      // hwc2 module. That is, we (technically) should not call any other hwc
-      // methods until this method has been called after registering the
-      // callbacks.
-      return hardware::Void();
-    }
-
-    hardware::Return<void> onRefresh(Hwc2::Display /*display*/) override {
-      return hardware::Void();
-    }
-
-    hardware::Return<void> onVsync(Hwc2::Display /*display*/,
-                                   int64_t /*timestamp*/) override {
-      return hardware::Void();
-    }
+    ComposerCallback();
+    hardware::Return<void> onHotplug(Hwc2::Display display,
+                                     Connection conn) override;
+    hardware::Return<void> onRefresh(Hwc2::Display display) override;
+    hardware::Return<void> onVsync(Hwc2::Display display,
+                                   int64_t timestamp) override;
+    const pdx::LocalHandle& GetVsyncEventFd() const;
+    int64_t GetVsyncTime();
+   private:
+    std::mutex vsync_mutex_;
+    pdx::LocalHandle vsync_event_fd_;
+    int64_t vsync_time_ = -1;
   };
 
   HWC::Error Validate(hwc2_display_t display);
@@ -364,17 +351,18 @@
   void UpdatePostThreadState(uint32_t state, bool suspend);
 
   // 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.
+  // control thread, or timeout_ms is reached before any events occur. Any
+  // errors are returned as negative errno values, with -ETIMEDOUT returned in
+  // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
+  // returned.
   int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
-                                  int requested_events);
+                                  int requested_events,
+                                  int timeout_ms);
 
-  // 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.
+  // WaitForVSync and SleepUntil are 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 ReadVSyncTimestamp(int64_t* timestamp);
   int WaitForVSync(int64_t* timestamp);
   int SleepUntil(int64_t wakeup_timestamp);
 
@@ -398,11 +386,9 @@
 
   bool initialized_;
 
-  // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
-  // this pointer.
-  Hwc2::Composer* hwc2_hidl_;
+  std::unique_ptr<Hwc2::Composer> hidl_;
+  sp<ComposerCallback> hidl_callback_;
   RequestDisplayCallback request_display_callback_;
-  sp<ComposerCallback> callbacks_;
 
   // Display metrics of the physical display.
   HWCDisplayMetrics native_display_metrics_;
@@ -433,7 +419,8 @@
   std::thread post_thread_;
 
   // Post thread state machine and synchronization primitives.
-  PostThreadStateType post_thread_state_{PostThreadState::Idle};
+  PostThreadStateType post_thread_state_{
+      PostThreadState::Idle | PostThreadState::Suspended};
   std::atomic<bool> post_thread_quiescent_{true};
   bool post_thread_resumed_{false};
   pdx::LocalHandle post_thread_event_fd_;
@@ -444,9 +431,6 @@
   // Backlight LED brightness sysfs node.
   pdx::LocalHandle backlight_brightness_fd_;
 
-  // Primary display vsync event sysfs node.
-  pdx::LocalHandle primary_display_vsync_event_fd_;
-
   // Primary display wait_pingpong state sysfs node.
   pdx::LocalHandle primary_display_wait_pp_fd_;
 
@@ -478,12 +462,6 @@
 
   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);
-  static void HwcHotplug(hwc2_callback_data_t callbackData,
-                         hwc2_display_t display, hwc2_connection_t connected);
-
   HardwareComposer(const HardwareComposer&) = delete;
   void operator=(const HardwareComposer&) = delete;
 };
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index e7f41a7..33cbc84 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -29,9 +29,6 @@
   void GrantDisplayOwnership();
   void SeizeDisplayOwnership();
 
-  // Called on a binder thread.
-  void OnHardwareComposerRefresh();
-
   // dump all vr flinger state.
   std::string Dump();
 
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 56405de..fcf94f0 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -133,10 +133,6 @@
   display_service_->SeizeDisplayOwnership();
 }
 
-void VrFlinger::OnHardwareComposerRefresh() {
-  display_service_->OnHardwareComposerRefresh();
-}
-
 std::string VrFlinger::Dump() {
   // TODO(karthikrs): Add more state information here.
   return display_service_->DumpState(0/*unused*/);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 744dd50..248ef53 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -134,9 +134,11 @@
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     if (config == EGL_NO_CONFIG) {
 #ifdef USE_HWC2
-        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
+                                               /*logConfig*/ false);
 #else
-        config = RenderEngine::chooseEglConfig(display, format);
+        config = RenderEngine::chooseEglConfig(display, format,
+                                               /*logConfig*/ false);
 #endif
     }
     eglSurface = eglCreateWindowSurface(display, config, window, NULL);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 704b17e..433a224 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -215,6 +215,10 @@
     }
 }
 
+bool Composer::isRemote() {
+    return mClient->isRemote();
+}
+
 void Composer::resetCommands() {
     mWriter.reset();
 }
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 40d2a4c..31a3c1d 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -143,6 +143,11 @@
 
     void registerCallback(const sp<IComposerCallback>& callback);
 
+    // Returns true if the connected composer service is running in a remote
+    // process, false otherwise. This will return false if the service is
+    // configured in passthrough mode, for example.
+    bool isRemote();
+
     // Reset all pending commands in the command buffer. Useful if you want to
     // skip a frame but have already queued some commands.
     void resetCommands();
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b749ce6..78c0c85 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -33,45 +33,6 @@
 #include <algorithm>
 #include <inttypes.h>
 
-extern "C" {
-    static void hotplug_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId, int32_t intConnected) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            auto connected = static_cast<HWC2::Connection>(intConnected);
-            device->callHotplug(std::move(display), connected);
-        } else {
-            ALOGE("Hotplug callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-
-    static void refresh_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            device->callRefresh(std::move(display));
-        } else {
-            ALOGE("Refresh callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-
-    static void vsync_hook(hwc2_callback_data_t callbackData,
-            hwc2_display_t displayId, int64_t timestamp) {
-        auto device = static_cast<HWC2::Device*>(callbackData);
-        auto display = device->getDisplayById(displayId);
-        if (display) {
-            device->callVsync(std::move(display), timestamp);
-        } else {
-            ALOGE("Vsync callback called with unknown display %" PRIu64,
-                    displayId);
-        }
-    }
-}
-
 using android::Fence;
 using android::FloatRect;
 using android::GraphicBuffer;
@@ -86,51 +47,78 @@
 
 namespace Hwc2 = android::Hwc2;
 
+namespace {
+
+class ComposerCallbackBridge : public Hwc2::IComposerCallback {
+public:
+    ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
+            : mCallback(callback), mSequenceId(sequenceId),
+              mHasPrimaryDisplay(false) {}
+
+    Return<void> onHotplug(Hwc2::Display display,
+                           IComposerCallback::Connection conn) override
+    {
+        HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
+        if (!mHasPrimaryDisplay) {
+            LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
+                    "Initial onHotplug callback should be "
+                    "primary display connected");
+            mHasPrimaryDisplay = true;
+            mCallback->onHotplugReceived(mSequenceId, display,
+                                         connection, true);
+        } else {
+            mCallback->onHotplugReceived(mSequenceId, display,
+                                         connection, false);
+        }
+        return Void();
+    }
+
+    Return<void> onRefresh(Hwc2::Display display) override
+    {
+        mCallback->onRefreshReceived(mSequenceId, display);
+        return Void();
+    }
+
+    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
+    {
+        mCallback->onVsyncReceived(mSequenceId, display, timestamp);
+        return Void();
+    }
+
+    bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }
+
+private:
+    ComposerCallback* mCallback;
+    int32_t mSequenceId;
+    bool mHasPrimaryDisplay;
+};
+
+} // namespace anonymous
+
+
 // Device methods
 
 Device::Device(const std::string& serviceName)
   : mComposer(std::make_unique<Hwc2::Composer>(serviceName)),
     mCapabilities(),
     mDisplays(),
-    mHotplug(),
-    mPendingHotplugs(),
-    mRefresh(),
-    mPendingRefreshes(),
-    mVsync(),
-    mPendingVsyncs()
+    mRegisteredCallback(false)
 {
     loadCapabilities();
-    registerCallbacks();
 }
 
-Device::~Device()
-{
-    for (auto element : mDisplays) {
-        auto display = element.second.lock();
-        if (!display) {
-            ALOGE("~Device: Found a display (%" PRId64 " that has already been"
-                    " destroyed", element.first);
-            continue;
-        }
-
-        DisplayType displayType = HWC2::DisplayType::Invalid;
-        auto error = display->getType(&displayType);
-        if (error != Error::None) {
-            ALOGE("~Device: Failed to determine type of display %" PRIu64
-                    ": %s (%d)", display->getId(), to_string(error).c_str(),
-                    static_cast<int32_t>(error));
-            continue;
-        }
-
-        if (displayType == HWC2::DisplayType::Physical) {
-            error = display->setVsyncEnabled(HWC2::Vsync::Disable);
-            if (error != Error::None) {
-                ALOGE("~Device: Failed to disable vsync for display %" PRIu64
-                        ": %s (%d)", display->getId(), to_string(error).c_str(),
-                        static_cast<int32_t>(error));
-            }
-        }
+void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
+    if (mRegisteredCallback) {
+        ALOGW("Callback already registered. Ignored extra registration "
+                "attempt.");
+        return;
     }
+    mRegisteredCallback = true;
+    sp<ComposerCallbackBridge> callbackBridge(
+            new ComposerCallbackBridge(callback, sequenceId));
+    mComposer->registerCallback(callbackBridge);
+    LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
+            "Registered composer callback but didn't get primary display");
 }
 
 // Required by HWC2 device
@@ -146,7 +134,7 @@
 }
 
 Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
-        android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
+        android_pixel_format_t* format, Display** outDisplay)
 {
     ALOGI("Creating virtual display");
 
@@ -159,104 +147,66 @@
         return error;
     }
 
-    ALOGI("Created virtual display");
+    auto display = std::make_unique<Display>(
+            *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+    *outDisplay = display.get();
     *format = static_cast<android_pixel_format_t>(intFormat);
-    *outDisplay = getDisplayById(displayId);
-    if (!*outDisplay) {
-        ALOGE("Failed to get display by id");
-        return Error::BadDisplay;
-    }
-    (*outDisplay)->setConnected(true);
+    mDisplays.emplace(displayId, std::move(display));
+    ALOGI("Created virtual display");
     return Error::None;
 }
 
-void Device::registerHotplugCallback(HotplugCallback hotplug)
+void Device::destroyDisplay(hwc2_display_t displayId)
 {
-    ALOGV("registerHotplugCallback");
-    mHotplug = hotplug;
-    for (auto& pending : mPendingHotplugs) {
-        auto& display = pending.first;
-        auto connected = pending.second;
-        ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
-                to_string(connected).c_str());
-        mHotplug(std::move(display), connected);
-    }
+    ALOGI("Destroying display %" PRIu64, displayId);
+    mDisplays.erase(displayId);
 }
 
-void Device::registerRefreshCallback(RefreshCallback refresh)
-{
-    mRefresh = refresh;
-    for (auto& pending : mPendingRefreshes) {
-        mRefresh(std::move(pending));
-    }
-}
+void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
+    if (connection == Connection::Connected) {
+        auto display = getDisplayById(displayId);
+        if (display) {
+            if (display->isConnected()) {
+                ALOGW("Attempt to hotplug connect display %" PRIu64
+                        " , which is already connected.", displayId);
+            } else {
+                display->setConnected(true);
+            }
+        } else {
+            DisplayType displayType;
+            auto intError = mComposer->getDisplayType(displayId,
+                    reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+                            &displayType));
+            auto error = static_cast<Error>(intError);
+            if (error != Error::None) {
+                ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+                        "Aborting hotplug attempt.",
+                        displayId, to_string(error).c_str(), intError);
+                return;
+            }
 
-void Device::registerVsyncCallback(VsyncCallback vsync)
-{
-    mVsync = vsync;
-    for (auto& pending : mPendingVsyncs) {
-        auto& display = pending.first;
-        auto timestamp = pending.second;
-        mVsync(std::move(display), timestamp);
-    }
-}
-
-// For use by Device callbacks
-
-void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
-{
-    if (connected == Connection::Connected) {
-        if (!display->isConnected()) {
-            mComposer->setClientTargetSlotCount(display->getId());
-            display->loadConfigs();
-            display->setConnected(true);
+            auto newDisplay = std::make_unique<Display>(
+                    *mComposer.get(), mCapabilities, displayId, displayType);
+            mDisplays.emplace(displayId, std::move(newDisplay));
         }
-    } else {
-        display->setConnected(false);
-        mDisplays.erase(display->getId());
-    }
-
-    if (mHotplug) {
-        mHotplug(std::move(display), connected);
-    } else {
-        ALOGV("callHotplug called, but no valid callback registered, storing");
-        mPendingHotplugs.emplace_back(std::move(display), connected);
-    }
-}
-
-void Device::callRefresh(std::shared_ptr<Display> display)
-{
-    if (mRefresh) {
-        mRefresh(std::move(display));
-    } else {
-        ALOGV("callRefresh called, but no valid callback registered, storing");
-        mPendingRefreshes.emplace_back(std::move(display));
-    }
-}
-
-void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
-{
-    if (mVsync) {
-        mVsync(std::move(display), timestamp);
-    } else {
-        ALOGV("callVsync called, but no valid callback registered, storing");
-        mPendingVsyncs.emplace_back(std::move(display), timestamp);
+    } else if (connection == Connection::Disconnected) {
+        // The display will later be destroyed by a call to
+        // destroyDisplay(). For now we just mark it disconnected.
+        auto display = getDisplayById(displayId);
+        if (display) {
+            display->setConnected(false);
+        } else {
+            ALOGW("Attempted to disconnect unknown display %" PRIu64,
+                  displayId);
+        }
     }
 }
 
 // Other Device methods
 
-std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
-    if (mDisplays.count(id) != 0) {
-        auto strongDisplay = mDisplays[id].lock();
-        ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
-                " longer alive", id);
-        return strongDisplay;
-    }
-
-    auto display = std::make_shared<Display>(*this, id);
-    mDisplays.emplace(id, display);
-    return display;
+Display* Device::getDisplayById(hwc2_display_t id) {
+    auto iter = mDisplays.find(id);
+    return iter == mDisplays.end() ? nullptr : iter->second.get();
 }
 
 // Device initialization methods
@@ -271,84 +221,37 @@
     }
 }
 
-bool Device::hasCapability(HWC2::Capability capability) const
-{
-    return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
-            capability) != mCapabilities.cend();
-}
-
-namespace {
-class ComposerCallback : public Hwc2::IComposerCallback {
-public:
-    ComposerCallback(Device* device) : mDevice(device) {}
-
-    Return<void> onHotplug(Hwc2::Display display,
-            Connection connected) override
-    {
-        hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
-        return Void();
-    }
-
-    Return<void> onRefresh(Hwc2::Display display) override
-    {
-        refresh_hook(mDevice, display);
-        return Void();
-    }
-
-    Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
-    {
-        vsync_hook(mDevice, display, timestamp);
-        return Void();
-    }
-
-private:
-    Device* mDevice;
-};
-} // namespace anonymous
-
-void Device::registerCallbacks()
-{
-    sp<ComposerCallback> callback = new ComposerCallback(this);
-    mComposer->registerCallback(callback);
-}
-
-
-// For use by Display
-
-void Device::destroyVirtualDisplay(hwc2_display_t display)
-{
-    ALOGI("Destroying virtual display");
-    auto intError = mComposer->destroyVirtualDisplay(display);
-    auto error = static_cast<Error>(intError);
-    ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
-            " %s (%d)", display, to_string(error).c_str(), intError);
-    mDisplays.erase(display);
-}
-
 // Display methods
 
-Display::Display(Device& device, hwc2_display_t id)
-  : mDevice(device),
+Display::Display(android::Hwc2::Composer& composer,
+                 const std::unordered_set<Capability>& capabilities,
+                 hwc2_display_t id, DisplayType type)
+  : mComposer(composer),
+    mCapabilities(capabilities),
     mId(id),
     mIsConnected(false),
-    mType(DisplayType::Invalid)
+    mType(type)
 {
     ALOGV("Created display %" PRIu64, id);
-
-    auto intError = mDevice.mComposer->getDisplayType(mId,
-            reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
-    auto error = static_cast<Error>(intError);
-    if (error != Error::None) {
-        ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
-              id, to_string(error).c_str(), intError);
-    }
+    setConnected(true);
 }
 
-Display::~Display()
-{
-    ALOGV("Destroyed display %" PRIu64, mId);
+Display::~Display() {
+    mLayers.clear();
+
     if (mType == DisplayType::Virtual) {
-        mDevice.destroyVirtualDisplay(mId);
+        ALOGV("Destroying virtual display");
+        auto intError = mComposer.destroyVirtualDisplay(mId);
+        auto error = static_cast<Error>(intError);
+        ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64
+                ") failed: %s (%d)", mId, to_string(error).c_str(), intError);
+    } else if (mType == DisplayType::Physical) {
+        auto error = setVsyncEnabled(HWC2::Vsync::Disable);
+        if (error != Error::None) {
+            ALOGE("~Display: Failed to disable vsync for display %" PRIu64
+                    ": %s (%d)", mId, to_string(error).c_str(),
+                    static_cast<int32_t>(error));
+        }
     }
 }
 
@@ -383,22 +286,35 @@
 
 Error Display::acceptChanges()
 {
-    auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
+    auto intError = mComposer.acceptDisplayChanges(mId);
     return static_cast<Error>(intError);
 }
 
-Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
+Error Display::createLayer(Layer** outLayer)
 {
+    if (!outLayer) {
+        return Error::BadParameter;
+    }
     hwc2_layer_t layerId = 0;
-    auto intError = mDevice.mComposer->createLayer(mId, &layerId);
+    auto intError = mComposer.createLayer(mId, &layerId);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
     }
 
-    auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
-    mLayers.emplace(layerId, layer);
-    *outLayer = std::move(layer);
+    auto layer = std::make_unique<Layer>(
+            mComposer, mCapabilities, mId, layerId);
+    *outLayer = layer.get();
+    mLayers.emplace(layerId, std::move(layer));
+    return Error::None;
+}
+
+Error Display::destroyLayer(Layer* layer)
+{
+    if (!layer) {
+        return Error::BadParameter;
+    }
+    mLayers.erase(layer->getId());
     return Error::None;
 }
 
@@ -407,7 +323,7 @@
 {
     ALOGV("[%" PRIu64 "] getActiveConfig", mId);
     hwc2_config_t configId = 0;
-    auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
+    auto intError = mComposer.getActiveConfig(mId, &configId);
     auto error = static_cast<Error>(intError);
 
     if (error != Error::None) {
@@ -430,12 +346,12 @@
 }
 
 Error Display::getChangedCompositionTypes(
-        std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
+        std::unordered_map<Layer*, Composition>* outTypes)
 {
     std::vector<Hwc2::Layer> layerIds;
     std::vector<Hwc2::IComposerClient::Composition> types;
-    auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
-            &layerIds, &types);
+    auto intError = mComposer.getChangedCompositionTypes(
+            mId, &layerIds, &types);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
     error = static_cast<Error>(intError);
@@ -464,7 +380,7 @@
 Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
 {
     std::vector<Hwc2::ColorMode> modes;
-    auto intError = mDevice.mComposer->getColorModes(mId, &modes);
+    auto intError = mComposer.getColorModes(mId, &modes);
     uint32_t numModes = modes.size();
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -489,19 +405,18 @@
 
 Error Display::getName(std::string* outName) const
 {
-    auto intError = mDevice.mComposer->getDisplayName(mId, outName);
+    auto intError = mComposer.getDisplayName(mId, outName);
     return static_cast<Error>(intError);
 }
 
 Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
-        std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
-                outLayerRequests)
+        std::unordered_map<Layer*, LayerRequest>* outLayerRequests)
 {
     uint32_t intDisplayRequests;
     std::vector<Hwc2::Layer> layerIds;
     std::vector<uint32_t> layerRequests;
-    auto intError = mDevice.mComposer->getDisplayRequests(mId,
-            &intDisplayRequests, &layerIds, &layerRequests);
+    auto intError = mComposer.getDisplayRequests(
+            mId, &intDisplayRequests, &layerIds, &layerRequests);
     uint32_t numElements = layerIds.size();
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
@@ -535,7 +450,7 @@
 Error Display::supportsDoze(bool* outSupport) const
 {
     bool intSupport = false;
-    auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
+    auto intError = mComposer.getDozeSupport(mId, &intSupport);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -552,7 +467,7 @@
     float maxAverageLuminance = -1.0f;
     float minLuminance = -1.0f;
     std::vector<Hwc2::Hdr> intTypes;
-    auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
+    auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
             &maxLuminance, &maxAverageLuminance, &minLuminance);
     auto error = static_cast<HWC2::Error>(intError);
 
@@ -571,25 +486,24 @@
 }
 
 Error Display::getReleaseFences(
-        std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
+        std::unordered_map<Layer*, sp<Fence>>* outFences) const
 {
     std::vector<Hwc2::Layer> layerIds;
     std::vector<int> fenceFds;
-    auto intError = mDevice.mComposer->getReleaseFences(mId,
-            &layerIds, &fenceFds);
+    auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
     auto error = static_cast<Error>(intError);
     uint32_t numElements = layerIds.size();
     if (error != Error::None) {
         return error;
     }
 
-    std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
+    std::unordered_map<Layer*, sp<Fence>> releaseFences;
     releaseFences.reserve(numElements);
     for (uint32_t element = 0; element < numElements; ++element) {
         auto layer = getLayerById(layerIds[element]);
         if (layer) {
             sp<Fence> fence(new Fence(fenceFds[element]));
-            releaseFences.emplace(std::move(layer), fence);
+            releaseFences.emplace(layer, fence);
         } else {
             ALOGE("getReleaseFences: invalid layer %" PRIu64
                     " found on display %" PRIu64, layerIds[element], mId);
@@ -607,7 +521,7 @@
 Error Display::present(sp<Fence>* outPresentFence)
 {
     int32_t presentFenceFd = -1;
-    auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
+    auto intError = mComposer.presentDisplay(mId, &presentFenceFd);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         return error;
@@ -625,7 +539,7 @@
                 config->getDisplayId(), mId);
         return Error::BadConfig;
     }
-    auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
+    auto intError = mComposer.setActiveConfig(mId, config->getId());
     return static_cast<Error>(intError);
 }
 
@@ -634,7 +548,7 @@
 {
     // TODO: Properly encode client target surface damage
     int32_t fenceFd = acquireFence->dup();
-    auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
+    auto intError = mComposer.setClientTarget(mId, slot, target,
             fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
             std::vector<Hwc2::IComposerClient::Rect>());
     return static_cast<Error>(intError);
@@ -642,15 +556,15 @@
 
 Error Display::setColorMode(android_color_mode_t mode)
 {
-    auto intError = mDevice.mComposer->setColorMode(mId,
-            static_cast<Hwc2::ColorMode>(mode));
+    auto intError = mComposer.setColorMode(
+            mId, static_cast<Hwc2::ColorMode>(mode));
     return static_cast<Error>(intError);
 }
 
 Error Display::setColorTransform(const android::mat4& matrix,
         android_color_transform_t hint)
 {
-    auto intError = mDevice.mComposer->setColorTransform(mId,
+    auto intError = mComposer.setColorTransform(mId,
             matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
     return static_cast<Error>(intError);
 }
@@ -660,7 +574,7 @@
 {
     int32_t fenceFd = releaseFence->dup();
     auto handle = buffer->getNativeBuffer()->handle;
-    auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
+    auto intError = mComposer.setOutputBuffer(mId, handle, fenceFd);
     close(fenceFd);
     return static_cast<Error>(intError);
 }
@@ -668,14 +582,14 @@
 Error Display::setPowerMode(PowerMode mode)
 {
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
-    auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
+    auto intError = mComposer.setPowerMode(mId, intMode);
     return static_cast<Error>(intError);
 }
 
 Error Display::setVsyncEnabled(Vsync enabled)
 {
     auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
-    auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
+    auto intError = mComposer.setVsyncEnabled(mId, intEnabled);
     return static_cast<Error>(intError);
 }
 
@@ -683,8 +597,7 @@
 {
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
-    auto intError = mDevice.mComposer->validateDisplay(mId,
-            &numTypes, &numRequests);
+    auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -701,7 +614,8 @@
     uint32_t numTypes = 0;
     uint32_t numRequests = 0;
     int32_t presentFenceFd = -1;
-    auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+    auto intError = mComposer.presentOrValidateDisplay(
+            mId, &numTypes, &numRequests, &presentFenceFd, state);
     auto error = static_cast<Error>(intError);
     if (error != Error::None && error != Error::HasChanges) {
         return error;
@@ -720,15 +634,23 @@
 
 void Display::discardCommands()
 {
-    mDevice.mComposer->resetCommands();
+    mComposer.resetCommands();
 }
 
 // For use by Device
 
+void Display::setConnected(bool connected) {
+    if (!mIsConnected && connected && mType == DisplayType::Physical) {
+        mComposer.setClientTargetSlotCount(mId);
+        loadConfigs();
+    }
+    mIsConnected = connected;
+}
+
 int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
 {
     int32_t value = 0;
-    auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
+    auto intError = mComposer.getDisplayAttribute(mId, configId,
             static_cast<Hwc2::IComposerClient::Attribute>(attribute),
             &value);
     auto error = static_cast<Error>(intError);
@@ -760,7 +682,7 @@
     ALOGV("[%" PRIu64 "] loadConfigs", mId);
 
     std::vector<Hwc2::Config> configIds;
-    auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
+    auto intError = mComposer.getDisplayConfigs(mId, &configIds);
     auto error = static_cast<Error>(intError);
     if (error != Error::None) {
         ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
@@ -773,54 +695,51 @@
     }
 }
 
-// For use by Layer
-
-void Display::destroyLayer(hwc2_layer_t layerId)
-{
-    auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
-    auto error = static_cast<Error>(intError);
-    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
-            " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
-            intError);
-    mLayers.erase(layerId);
-}
-
 // Other Display methods
 
-std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
+Layer* Display::getLayerById(hwc2_layer_t id) const
 {
     if (mLayers.count(id) == 0) {
         return nullptr;
     }
 
-    auto layer = mLayers.at(id).lock();
-    return layer;
+    return mLayers.at(id).get();
 }
 
 // Layer methods
 
-Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
-  : mDisplay(display),
-    mDisplayId(display->getId()),
-    mDevice(display->getDevice()),
-    mId(id)
+Layer::Layer(android::Hwc2::Composer& composer,
+             const std::unordered_set<Capability>& capabilities,
+             hwc2_display_t displayId, hwc2_layer_t layerId)
+  : mComposer(composer),
+    mCapabilities(capabilities),
+    mDisplayId(displayId),
+    mId(layerId)
 {
-    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
-            display->getId());
+    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId);
 }
 
 Layer::~Layer()
 {
-    auto display = mDisplay.lock();
-    if (display) {
-        display->destroyLayer(mId);
+    auto intError = mComposer.destroyLayer(mDisplayId, mId);
+    auto error = static_cast<Error>(intError);
+    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+            " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
+            intError);
+    if (mLayerDestroyedListener) {
+        mLayerDestroyedListener(this);
     }
 }
 
+void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) {
+    LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener,
+            "Attempt to set layer destroyed listener multiple times");
+    mLayerDestroyedListener = listener;
+}
+
 Error Layer::setCursorPosition(int32_t x, int32_t y)
 {
-    auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
-            mId, x, y);
+    auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y);
     return static_cast<Error>(intError);
 }
 
@@ -828,8 +747,8 @@
         const sp<Fence>& acquireFence)
 {
     int32_t fenceFd = acquireFence->dup();
-    auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
-            mId, slot, buffer, fenceFd);
+    auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer,
+                                             fenceFd);
     return static_cast<Error>(intError);
 }
 
@@ -839,7 +758,7 @@
     // rects for HWC
     Hwc2::Error intError = Hwc2::Error::NONE;
     if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
-        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+        intError = mComposer.setLayerSurfaceDamage(mDisplayId,
                 mId, std::vector<Hwc2::IComposerClient::Rect>());
     } else {
         size_t rectCount = 0;
@@ -851,8 +770,7 @@
                     rectArray[rect].right, rectArray[rect].bottom});
         }
 
-        intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
-                mId, hwcRects);
+        intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects);
     }
 
     return static_cast<Error>(intError);
@@ -861,24 +779,22 @@
 Error Layer::setBlendMode(BlendMode mode)
 {
     auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
-    auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
-            mId, intMode);
+    auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setColor(hwc_color_t color)
 {
     Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
-    auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
-            mId, hwcColor);
+    auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setCompositionType(Composition type)
 {
     auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
-    auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
-            mId, intType);
+    auto intError = mComposer.setLayerCompositionType(
+            mDisplayId, mId, intType);
     return static_cast<Error>(intError);
 }
 
@@ -889,8 +805,7 @@
     }
     mDataSpace = dataspace;
     auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
-    auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
-            mId, intDataspace);
+    auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace);
     return static_cast<Error>(intError);
 }
 
@@ -898,27 +813,24 @@
 {
     Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
         frame.right, frame.bottom};
-    auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
-            mId, hwcRect);
+    auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setPlaneAlpha(float alpha)
 {
-    auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
-            mId, alpha);
+    auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setSidebandStream(const native_handle_t* stream)
 {
-    if (!mDevice.hasCapability(Capability::SidebandStream)) {
+    if (mCapabilities.count(Capability::SidebandStream) == 0) {
         ALOGE("Attempted to call setSidebandStream without checking that the "
                 "device supports sideband streams");
         return Error::Unsupported;
     }
-    auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
-            mId, stream);
+    auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream);
     return static_cast<Error>(intError);
 }
 
@@ -926,16 +838,14 @@
 {
     Hwc2::IComposerClient::FRect hwcRect{
         crop.left, crop.top, crop.right, crop.bottom};
-    auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
-            mId, hwcRect);
+    auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setTransform(Transform transform)
 {
     auto intTransform = static_cast<Hwc2::Transform>(transform);
-    auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
-            mId, intTransform);
+    auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform);
     return static_cast<Error>(intError);
 }
 
@@ -950,20 +860,19 @@
                 rectArray[rect].right, rectArray[rect].bottom});
     }
 
-    auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
-            mId, hwcRects);
+    auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setZOrder(uint32_t z)
 {
-    auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
+    auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z);
     return static_cast<Error>(intError);
 }
 
 Error Layer::setInfo(uint32_t type, uint32_t appId)
 {
-  auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
+  auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId);
   return static_cast<Error>(intError);
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 9bcda1e..fbe4c7e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -53,10 +53,26 @@
 class Display;
 class Layer;
 
-typedef std::function<void(std::shared_ptr<Display>, Connection)>
-        HotplugCallback;
-typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
-typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
+// Implement this interface to receive hardware composer events.
+//
+// These callback functions will generally be called on a hwbinder thread, but
+// when first registering the callback the onHotplugReceived() function will
+// immediately be called on the thread calling registerCallback().
+//
+// All calls receive a sequenceId, which will be the value that was supplied to
+// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
+// from different hardware composer instances.
+class ComposerCallback {
+ public:
+    virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+                                   Connection connection,
+                                   bool primaryDisplay) = 0;
+    virtual void onRefreshReceived(int32_t sequenceId,
+                                   hwc2_display_t display) = 0;
+    virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+                                 int64_t timestamp) = 0;
+    virtual ~ComposerCallback() = default;
+};
 
 // C++ Wrapper around hwc2_device_t. Load all functions pointers
 // and handle callback registration.
@@ -66,10 +82,8 @@
     // Service name is expected to be 'default' or 'vr' for normal use.
     // 'vr' will slightly modify the behavior of the mComposer.
     Device(const std::string& serviceName);
-    ~Device();
 
-    friend class HWC2::Display;
-    friend class HWC2::Layer;
+    void registerCallback(ComposerCallback* callback, int32_t sequenceId);
 
     // Required by HWC2
 
@@ -81,27 +95,14 @@
 
     uint32_t getMaxVirtualDisplayCount() const;
     Error createVirtualDisplay(uint32_t width, uint32_t height,
-            android_pixel_format_t* format,
-            std::shared_ptr<Display>* outDisplay);
+            android_pixel_format_t* format, Display** outDisplay);
+    void destroyDisplay(hwc2_display_t displayId);
 
-    void registerHotplugCallback(HotplugCallback hotplug);
-    void registerRefreshCallback(RefreshCallback refresh);
-    void registerVsyncCallback(VsyncCallback vsync);
-
-    // For use by callbacks
-
-    void callHotplug(std::shared_ptr<Display> display, Connection connected);
-    void callRefresh(std::shared_ptr<Display> display);
-    void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp);
+    void onHotplug(hwc2_display_t displayId, Connection connection);
 
     // Other Device methods
 
-    // This will create a Display if one is not found, but it will not be marked
-    // as connected. This Display may be null if the display has been torn down
-    // but has not been removed from the map yet.
-    std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
-
-    bool hasCapability(HWC2::Capability capability) const;
+    Display* getDisplayById(hwc2_display_t id);
 
     android::Hwc2::Composer* getComposer() { return mComposer.get(); }
 
@@ -109,37 +110,23 @@
     // Initialization methods
 
     void loadCapabilities();
-    void registerCallbacks();
-
-    // For use by Display
-
-    void destroyVirtualDisplay(hwc2_display_t display);
 
     // Member variables
     std::unique_ptr<android::Hwc2::Composer> mComposer;
-
     std::unordered_set<Capability> mCapabilities;
-    std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
-
-    HotplugCallback mHotplug;
-    std::vector<std::pair<std::shared_ptr<Display>, Connection>>
-            mPendingHotplugs;
-    RefreshCallback mRefresh;
-    std::vector<std::shared_ptr<Display>> mPendingRefreshes;
-    VsyncCallback mVsync;
-    std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
+    std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+    bool mRegisteredCallback;
 };
 
 // Convenience C++ class to access hwc2_device_t Display functions directly.
-class Display : public std::enable_shared_from_this<Display>
+class Display
 {
 public:
-    Display(Device& device, hwc2_display_t id);
+    Display(android::Hwc2::Composer& composer,
+            const std::unordered_set<Capability>& capabilities,
+            hwc2_display_t id, DisplayType type);
     ~Display();
 
-    friend class HWC2::Device;
-    friend class HWC2::Layer;
-
     class Config
     {
     public:
@@ -212,12 +199,12 @@
     // Required by HWC2
 
     [[clang::warn_unused_result]] Error acceptChanges();
-    [[clang::warn_unused_result]] Error createLayer(
-            std::shared_ptr<Layer>* outLayer);
+    [[clang::warn_unused_result]] Error createLayer(Layer** outLayer);
+    [[clang::warn_unused_result]] Error destroyLayer(Layer* layer);
     [[clang::warn_unused_result]] Error getActiveConfig(
             std::shared_ptr<const Config>* outConfig) const;
     [[clang::warn_unused_result]] Error getChangedCompositionTypes(
-            std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+            std::unordered_map<Layer*, Composition>* outTypes);
     [[clang::warn_unused_result]] Error getColorModes(
             std::vector<android_color_mode_t>* outModes) const;
 
@@ -227,14 +214,13 @@
     [[clang::warn_unused_result]] Error getName(std::string* outName) const;
     [[clang::warn_unused_result]] Error getRequests(
             DisplayRequest* outDisplayRequests,
-            std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
-                    outLayerRequests);
+            std::unordered_map<Layer*, LayerRequest>* outLayerRequests);
     [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
     [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
     [[clang::warn_unused_result]] Error getHdrCapabilities(
             std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
     [[clang::warn_unused_result]] Error getReleaseFences(
-            std::unordered_map<std::shared_ptr<Layer>,
+            std::unordered_map<Layer*,
                     android::sp<android::Fence>>* outFences) const;
     [[clang::warn_unused_result]] Error present(
             android::sp<android::Fence>* outPresentFence);
@@ -266,32 +252,31 @@
 
     // Other Display methods
 
-    Device& getDevice() const { return mDevice; }
     hwc2_display_t getId() const { return mId; }
     bool isConnected() const { return mIsConnected; }
+    void setConnected(bool connected);  // For use by Device only
 
 private:
-    // For use by Device
-
-    void setConnected(bool connected) { mIsConnected = connected; }
     int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
     void loadConfig(hwc2_config_t configId);
     void loadConfigs();
 
-    // For use by Layer
-    void destroyLayer(hwc2_layer_t layerId);
-
     // This may fail (and return a null pointer) if no layer with this ID exists
     // on this display
-    std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const;
+    Layer* getLayerById(hwc2_layer_t id) const;
 
     // Member variables
 
-    Device& mDevice;
+    // These are references to data owned by HWC2::Device, which will outlive
+    // this HWC2::Display, so these references are guaranteed to be valid for
+    // the lifetime of this object.
+    android::Hwc2::Composer& mComposer;
+    const std::unordered_set<Capability>& mCapabilities;
+
     hwc2_display_t mId;
     bool mIsConnected;
     DisplayType mType;
-    std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
+    std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
     // The ordering in this map matters, for getConfigs(), when it is
     // converted to a vector
     std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
@@ -301,12 +286,18 @@
 class Layer
 {
 public:
-    Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id);
+    Layer(android::Hwc2::Composer& composer,
+          const std::unordered_set<Capability>& capabilities,
+          hwc2_display_t displayId, hwc2_layer_t layerId);
     ~Layer();
 
-    bool isAbandoned() const { return mDisplay.expired(); }
     hwc2_layer_t getId() const { return mId; }
 
+    // Register a listener to be notified when the layer is destroyed. When the
+    // listener function is called, the Layer will be in the process of being
+    // destroyed, so it's not safe to call methods on it.
+    void setLayerDestroyedListener(std::function<void(Layer*)> listener);
+
     [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
     [[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
             const android::sp<android::GraphicBuffer>& buffer,
@@ -333,11 +324,16 @@
     [[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId);
 
 private:
-    std::weak_ptr<Display> mDisplay;
+    // These are references to data owned by HWC2::Device, which will outlive
+    // this HWC2::Layer, so these references are guaranteed to be valid for
+    // the lifetime of this object.
+    android::Hwc2::Composer& mComposer;
+    const std::unordered_set<Capability>& mCapabilities;
+
     hwc2_display_t mDisplayId;
-    Device& mDevice;
     hwc2_layer_t mId;
     android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
+    std::function<void(Layer*)> mLayerDestroyedListener;
 };
 
 } // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index abf7dd1..b096a3a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -65,7 +65,6 @@
       mFreeDisplaySlots(),
       mHwcDisplaySlots(),
       mCBContext(),
-      mEventHandler(nullptr),
       mVSyncCounts(),
       mRemainingHwcVirtualDisplays(0)
 {
@@ -74,41 +73,15 @@
         mVSyncCounts[i] = 0;
     }
 
-    loadHwcModule(serviceName);
+    mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
+    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
 }
 
 HWComposer::~HWComposer() {}
 
-void HWComposer::setEventHandler(EventHandler* handler)
-{
-    if (handler == nullptr) {
-        ALOGE("setEventHandler: Rejected attempt to clear handler");
-        return;
-    }
-
-    bool wasNull = (mEventHandler == nullptr);
-    mEventHandler = handler;
-
-    if (wasNull) {
-        auto hotplugHook = std::bind(&HWComposer::hotplug, this,
-                std::placeholders::_1, std::placeholders::_2);
-        mHwcDevice->registerHotplugCallback(hotplugHook);
-        auto invalidateHook = std::bind(&HWComposer::invalidate, this,
-                std::placeholders::_1);
-        mHwcDevice->registerRefreshCallback(invalidateHook);
-        auto vsyncHook = std::bind(&HWComposer::vsync, this,
-                std::placeholders::_1, std::placeholders::_2);
-        mHwcDevice->registerVsyncCallback(vsyncHook);
-    }
-}
-
-// Load and prepare the hardware composer module.  Sets mHwc.
-void HWComposer::loadHwcModule(const std::string& serviceName)
-{
-    ALOGV("loadHwcModule");
-    mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
-
-    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
+                                  int32_t sequenceId) {
+    mHwcDevice->registerCallback(callback, sequenceId);
 }
 
 bool HWComposer::hasCapability(HWC2::Capability capability) const
@@ -146,54 +119,51 @@
     }
 }
 
-void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
-        HWC2::Connection connected) {
-    ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
-            to_string(connected).c_str());
-    int32_t disp = 0;
+void HWComposer::onHotplug(hwc2_display_t displayId,
+                           HWC2::Connection connection) {
+    ALOGV("hotplug: %" PRIu64 ", %s", displayId,
+            to_string(connection).c_str());
+    mHwcDevice->onHotplug(displayId, connection);
     if (!mDisplayData[0].hwcDisplay) {
-        ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+        ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
                 " display would be connected");
-        mDisplayData[0].hwcDisplay = display;
-        mHwcDisplaySlots[display->getId()] = 0;
-        disp = DisplayDevice::DISPLAY_PRIMARY;
+        mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+        mHwcDisplaySlots[displayId] = 0;
     } else {
         // Disconnect is handled through HWComposer::disconnectDisplay via
         // SurfaceFlinger's onHotplugReceived callback handling
-        if (connected == HWC2::Connection::Connected) {
-            mDisplayData[1].hwcDisplay = display;
-            mHwcDisplaySlots[display->getId()] = 1;
+        if (connection == HWC2::Connection::Connected) {
+            mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+            mHwcDisplaySlots[displayId] = 1;
         }
-        disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-    mEventHandler->onHotplugReceived(this, disp,
-            connected == HWC2::Connection::Connected);
 }
 
-void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
-    mEventHandler->onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
-        int64_t timestamp) {
+bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
+                         int32_t* outDisplay) {
+    auto display = mHwcDevice->getDisplayById(displayId);
+    if (!display) {
+        ALOGE("onVsync Failed to find display %" PRIu64, displayId);
+        return false;
+    }
     auto displayType = HWC2::DisplayType::Invalid;
     auto error = display->getType(&displayType);
     if (error != HWC2::Error::None) {
-        ALOGE("vsync: Failed to determine type of display %" PRIu64,
+        ALOGE("onVsync: Failed to determine type of display %" PRIu64,
                 display->getId());
-        return;
+        return false;
     }
 
     if (displayType == HWC2::DisplayType::Virtual) {
         ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
                 display->getId());
-        return;
+        return false;
     }
 
     if (mHwcDisplaySlots.count(display->getId()) == 0) {
         ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
                 display->getId());
-        return;
+        return false;
     }
 
     int32_t disp = mHwcDisplaySlots[display->getId()];
@@ -207,17 +177,21 @@
         if (timestamp == mLastHwVSync[disp]) {
             ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
                     timestamp);
-            return;
+            return false;
         }
 
         mLastHwVSync[disp] = timestamp;
     }
 
+    if (outDisplay) {
+        *outDisplay = disp;
+    }
+
     char tag[16];
     snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
     ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
 
-    mEventHandler->onVSyncReceived(this, disp, timestamp);
+    return true;
 }
 
 status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -236,7 +210,7 @@
         return INVALID_OPERATION;
     }
 
-    std::shared_ptr<HWC2::Display> display;
+    HWC2::Display* display;
     auto error = mHwcDevice->createVirtualDisplay(width, height, format,
             &display);
     if (error != HWC2::Error::None) {
@@ -265,13 +239,13 @@
     return NO_ERROR;
 }
 
-std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
     if (!isValidDisplay(displayId)) {
         ALOGE("Failed to create layer on invalid display %d", displayId);
         return nullptr;
     }
     auto display = mDisplayData[displayId].hwcDisplay;
-    std::shared_ptr<HWC2::Layer> layer;
+    HWC2::Layer* layer;
     auto error = display->createLayer(&layer);
     if (error != HWC2::Error::None) {
         ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
@@ -281,6 +255,19 @@
     return layer;
 }
 
+void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("Failed to destroy layer on invalid display %d", displayId);
+        return;
+    }
+    auto display = mDisplayData[displayId].hwcDisplay;
+    auto error = display->destroyLayer(layer);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to destroy layer on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+}
+
 nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const {
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
@@ -348,10 +335,8 @@
                 displayId);
         return modes;
     }
-    const std::shared_ptr<HWC2::Display>& hwcDisplay =
-            mDisplayData[displayId].hwcDisplay;
 
-    auto error = hwcDisplay->getColorModes(&modes);
+    auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes);
     if (error != HWC2::Error::None) {
         ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
                 to_string(error).c_str(), static_cast<int32_t>(error));
@@ -471,7 +456,7 @@
             return UNKNOWN_ERROR;
         }
         if (state == 1) { //Present Succeeded.
-            std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+            std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
             error = hwcDisplay->getReleaseFences(&releaseFences);
             displayData.releaseFences = std::move(releaseFences);
             displayData.lastPresentFence = outPresentFence;
@@ -490,8 +475,7 @@
         return BAD_INDEX;
     }
 
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
-        changedTypes;
+    std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
     changedTypes.reserve(numTypes);
     error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
     if (error != HWC2::Error::None) {
@@ -503,8 +487,7 @@
 
 
     displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
-        layerRequests;
+    std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
     layerRequests.reserve(numRequests);
     error = hwcDisplay->getRequests(&displayData.displayRequests,
             &layerRequests);
@@ -598,7 +581,7 @@
 }
 
 sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
-        const std::shared_ptr<HWC2::Layer>& layer) const {
+        HWC2::Layer* layer) const {
     if (!isValidDisplay(displayId)) {
         ALOGE("getLayerReleaseFence: Invalid display");
         return Fence::NO_FENCE;
@@ -639,7 +622,7 @@
         return UNKNOWN_ERROR;
     }
 
-    std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+    std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
     error = hwcDisplay->getReleaseFences(&releaseFences);
     if (error != HWC2::Error::None) {
         ALOGE("presentAndGetReleaseFences: Failed to get release fences "
@@ -787,6 +770,8 @@
     auto hwcId = displayData.hwcDisplay->getId();
     mHwcDisplaySlots.erase(hwcId);
     displayData.reset();
+
+    mHwcDevice->destroyDisplay(hwcId);
 }
 
 status_t HWComposer::setOutputBuffer(int32_t displayId,
@@ -885,7 +870,7 @@
 HWComposer::DisplayData::DisplayData()
   : hasClientComposition(false),
     hasDeviceComposition(false),
-    hwcDisplay(),
+    hwcDisplay(nullptr),
     lastPresentFence(Fence::NO_FENCE),
     outbufHandle(nullptr),
     outbufAcquireFence(Fence::NO_FENCE),
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3dfb65b..3640bb5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -65,23 +65,14 @@
 class HWComposer
 {
 public:
-    class EventHandler {
-        friend class HWComposer;
-        virtual void onVSyncReceived(
-            HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
-        virtual void onInvalidateReceived(HWComposer* composer) = 0;
-    protected:
-        virtual ~EventHandler() {}
-    };
-
     // Uses the named composer service. Valid choices for normal use
     // are 'default' and 'vr'.
     HWComposer(const std::string& serviceName);
 
     ~HWComposer();
 
-    void setEventHandler(EventHandler* handler);
+    void registerCallback(HWC2::ComposerCallback* callback,
+                          int32_t sequenceId);
 
     bool hasCapability(HWC2::Capability capability) const;
 
@@ -91,7 +82,9 @@
             android_pixel_format_t* format, int32_t* outId);
 
     // Attempts to create a new layer on this display
-    std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
+    HWC2::Layer* createLayer(int32_t displayId);
+    // Destroy a previously created layer
+    void destroyLayer(int32_t displayId, HWC2::Layer* layer);
 
     // Asks the HAL what it can do
     status_t prepare(DisplayDevice& displayDevice);
@@ -126,7 +119,7 @@
 
     // Get last release fence for the given layer
     sp<Fence> getLayerReleaseFence(int32_t displayId,
-            const std::shared_ptr<HWC2::Layer>& layer) const;
+            HWC2::Layer* layer) const;
 
     // Set the output buffer and acquire fence for a virtual display.
     // Returns INVALID_OPERATION if displayId is not a virtual display.
@@ -142,6 +135,12 @@
 
     // Events handling ---------------------------------------------------------
 
+    // Returns true if successful, false otherwise. The
+    // DisplayDevice::DisplayType of the display is returned as an output param.
+    bool onVsync(hwc2_display_t displayId, int64_t timestamp,
+                 int32_t* outDisplay);
+    void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
+
     void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
 
     // Query display parameters.  Pass in a display index (e.g.
@@ -169,19 +168,11 @@
 private:
     static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
-    void loadHwcModule(const std::string& serviceName);
-
     bool isValidDisplay(int32_t displayId) const;
     static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
     struct cb_context;
 
-    void invalidate(const std::shared_ptr<HWC2::Display>& display);
-    void vsync(const std::shared_ptr<HWC2::Display>& display,
-            int64_t timestamp);
-    void hotplug(const std::shared_ptr<HWC2::Display>& display,
-            HWC2::Connection connected);
-
     struct DisplayData {
         DisplayData();
         ~DisplayData();
@@ -189,11 +180,10 @@
 
         bool hasClientComposition;
         bool hasDeviceComposition;
-        std::shared_ptr<HWC2::Display> hwcDisplay;
+        HWC2::Display* hwcDisplay;
         HWC2::DisplayRequest displayRequests;
         sp<Fence> lastPresentFence;  // signals when the last set op retires
-        std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
-                releaseFences;
+        std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
         buffer_handle_t outbufHandle;
         sp<Fence> outbufAcquireFence;
         mutable std::unordered_map<int32_t,
@@ -214,7 +204,6 @@
     mutable Mutex mDisplayLock;
 
     cb_context*                     mCBContext;
-    EventHandler*                   mEventHandler;
     size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
     uint32_t                        mRemainingHwcVirtualDisplays;
 
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index ee6e886..052a959 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -31,34 +31,35 @@
 }
 
 bool EventControlThread::threadLoop() {
-    Mutex::Autolock lock(mMutex);
-
-    bool vsyncEnabled = mVsyncEnabled;
-
-#ifdef USE_HWC2
-    mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
-#else
-    mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
-            mVsyncEnabled);
-#endif
+    enum class VsyncState {Unset, On, Off};
+    auto currentVsyncState = VsyncState::Unset;
 
     while (true) {
-        status_t err = mCond.wait(mMutex);
-        if (err != NO_ERROR) {
-            ALOGE("error waiting for new events: %s (%d)",
-                strerror(-err), err);
-            return false;
+        auto requestedVsyncState = VsyncState::On;
+        {
+            Mutex::Autolock lock(mMutex);
+            requestedVsyncState =
+                    mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+            while (currentVsyncState == requestedVsyncState) {
+                status_t err = mCond.wait(mMutex);
+                if (err != NO_ERROR) {
+                    ALOGE("error waiting for new events: %s (%d)",
+                          strerror(-err), err);
+                    return false;
+                }
+                requestedVsyncState =
+                        mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+            }
         }
 
-        if (vsyncEnabled != mVsyncEnabled) {
+        bool enable = requestedVsyncState == VsyncState::On;
 #ifdef USE_HWC2
-            mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+        mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
 #else
-            mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
-                    SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+        mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
+                SurfaceFlinger::EVENT_VSYNC, enable);
 #endif
-            vsyncEnabled = mVsyncEnabled;
-        }
+        currentVsyncState = requestedVsyncState;
     }
 
     return false;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3903a55..54d4cbd 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -201,6 +201,12 @@
     }
     mFlinger->deleteTextureAsync(mTextureName);
     mFrameTracker.logAndResetStats(mName);
+
+#ifdef USE_HWC2
+    ALOGE_IF(!mHwcLayers.empty(),
+            "Found stale hardware composer layers when destroying "
+            "surface flinger layer");
+#endif
 }
 
 // ---------------------------------------------------------------------------
@@ -303,7 +309,7 @@
     mSurfaceFlingerConsumer->abandon();
 
 #ifdef USE_HWC2
-    clearHwcLayers();
+    destroyAllHwcLayers();
 #endif
 
     for (const auto& child : mCurrentChildren) {
@@ -364,6 +370,48 @@
 // h/w composer set-up
 // ---------------------------------------------------------------------------
 
+#ifdef USE_HWC2
+bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
+    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+                "Already have a layer for hwcId %d", hwcId);
+    HWC2::Layer* layer = hwc->createLayer(hwcId);
+    if (!layer) {
+        return false;
+    }
+    HWCInfo& hwcInfo = mHwcLayers[hwcId];
+    hwcInfo.hwc = hwc;
+    hwcInfo.layer = layer;
+    layer->setLayerDestroyedListener(
+            [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+    return true;
+}
+
+void Layer::destroyHwcLayer(int32_t hwcId) {
+    if (mHwcLayers.count(hwcId) == 0) {
+        return;
+    }
+    auto& hwcInfo = mHwcLayers[hwcId];
+    LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
+            "Attempt to destroy null layer");
+    LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
+    hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
+    // The layer destroyed listener should have cleared the entry from
+    // mHwcLayers. Verify that.
+    LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+            "Stale layer entry in mHwcLayers");
+}
+
+void Layer::destroyAllHwcLayers() {
+    size_t numLayers = mHwcLayers.size();
+    for (size_t i = 0; i < numLayers; ++i) {
+        LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
+        destroyHwcLayer(mHwcLayers.begin()->first);
+    }
+    LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
+            "All hardware composer layers should have been destroyed");
+}
+#endif
+
 Rect Layer::getContentCrop() const {
     // this is the crop rectangle that applies to the buffer
     // itself (as opposed to the window)
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8df8c49..1b7d075 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -447,37 +447,21 @@
 #ifdef USE_HWC2
     // -----------------------------------------------------------------------
 
+    bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
+    void destroyHwcLayer(int32_t hwcId);
+    void destroyAllHwcLayers();
+
     bool hasHwcLayer(int32_t hwcId) {
-        if (mHwcLayers.count(hwcId) == 0) {
-            return false;
-        }
-        if (mHwcLayers[hwcId].layer->isAbandoned()) {
-            ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
-            mHwcLayers.erase(hwcId);
-            return false;
-        }
-        return true;
+        return mHwcLayers.count(hwcId) > 0;
     }
 
-    std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) {
+    HWC2::Layer* getHwcLayer(int32_t hwcId) {
         if (mHwcLayers.count(hwcId) == 0) {
             return nullptr;
         }
         return mHwcLayers[hwcId].layer;
     }
 
-    void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
-        if (layer) {
-            mHwcLayers[hwcId].layer = layer;
-        } else {
-            mHwcLayers.erase(hwcId);
-        }
-    }
-
-    void clearHwcLayers() {
-        mHwcLayers.clear();
-    }
-
 #endif
     // -----------------------------------------------------------------------
 
@@ -766,12 +750,14 @@
     // HWC items, accessed from the main thread
     struct HWCInfo {
         HWCInfo()
-          : layer(),
+          : hwc(nullptr),
+            layer(nullptr),
             forceClientComposition(false),
             compositionType(HWC2::Composition::Invalid),
             clearClientTarget(false) {}
 
-        std::shared_ptr<HWC2::Layer> layer;
+        HWComposer* hwc;
+        HWC2::Layer* layer;
         bool forceClientComposition;
         HWC2::Composition compositionType;
         bool clearClientTarget;
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index ac2d8b2..57f468d 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -64,7 +64,7 @@
                        "EGL_ANDROIDX_no_config_context") &&
         !findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
                        "EGL_KHR_no_config_context")) {
-        config = chooseEglConfig(display, hwcFormat);
+        config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
     }
 
     EGLint renderableType = 0;
@@ -108,7 +108,7 @@
 
     EGLConfig dummyConfig = config;
     if (dummyConfig == EGL_NO_CONFIG) {
-        dummyConfig = chooseEglConfig(display, hwcFormat);
+        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
     }
     EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
     EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
@@ -406,7 +406,8 @@
     return err;
 }
 
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
+                                        bool logConfig) {
     status_t err;
     EGLConfig config;
 
@@ -427,18 +428,20 @@
         }
     }
 
-    // print some debugging info
-    EGLint r,g,b,a;
-    eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
-    eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
-    eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
-    eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
-    ALOGI("EGL information:");
-    ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
-    ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
-    ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
-    ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
-    ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+    if (logConfig) {
+        // print some debugging info
+        EGLint r,g,b,a;
+        eglGetConfigAttrib(display, config, EGL_RED_SIZE,   &r);
+        eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+        eglGetConfigAttrib(display, config, EGL_BLUE_SIZE,  &b);
+        eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+        ALOGI("EGL information:");
+        ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
+        ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
+        ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+        ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+        ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+    }
 
     return config;
 }
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 56f5827..9544579 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -64,7 +64,7 @@
     };
     static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
 
-    static EGLConfig chooseEglConfig(EGLDisplay display, int format);
+    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
 
     void primeCache() const;
 
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 609b15b..0d93467 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -77,6 +77,7 @@
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 
+#include "DisplayHardware/ComposerHal.h"
 #include "DisplayHardware/FramebufferSurface.h"
 #include "DisplayHardware/HWComposer.h"
 #include "DisplayHardware/VirtualDisplaySurface.h"
@@ -101,10 +102,24 @@
 
 namespace android {
 
-
 using namespace android::hardware::configstore;
 using namespace android::hardware::configstore::V1_0;
 
+namespace {
+class ConditionalLock {
+public:
+    ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
+        if (lock) {
+            mMutex.lock();
+        }
+    }
+    ~ConditionalLock() { if (mLocked) mMutex.unlock(); }
+private:
+    Mutex& mMutex;
+    bool mLocked;
+};
+}  // namespace anonymous
+
 // ---------------------------------------------------------------------------
 
 const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -147,9 +162,6 @@
         mLayersRemoved(false),
         mLayersAdded(false),
         mRepaintEverything(0),
-        mHwc(nullptr),
-        mRealHwc(nullptr),
-        mVrHwc(nullptr),
         mHwcServiceName(getHwcServiceName()),
         mRenderEngine(nullptr),
         mBootTime(systemTime()),
@@ -177,7 +189,9 @@
         mTotalTime(0),
         mLastSwapTime(0),
         mNumLayers(0),
-        mVrFlingerRequestsDisplay(false)
+        mVrFlingerRequestsDisplay(false),
+        mMainThreadId(std::this_thread::get_id()),
+        mComposerSequenceId(0)
 {
     ALOGI("SurfaceFlinger is starting");
 
@@ -583,48 +597,46 @@
 
     ALOGI("Phase offset NS: %" PRId64 "", vsyncPhaseOffsetNs);
 
-    { // Autolock scope
-        Mutex::Autolock _l(mStateLock);
+    Mutex::Autolock _l(mStateLock);
 
-        // initialize EGL for the default display
-        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-        eglInitialize(mEGLDisplay, NULL, NULL);
+    // initialize EGL for the default display
+    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(mEGLDisplay, NULL, NULL);
 
-        // start the EventThread
-        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-                vsyncPhaseOffsetNs, true, "app");
-        mEventThread = new EventThread(vsyncSrc, *this, false);
-        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-                sfVsyncPhaseOffsetNs, true, "sf");
-        mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
-        mEventQueue.setEventThread(mSFEventThread);
+    // start the EventThread
+    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            vsyncPhaseOffsetNs, true, "app");
+    mEventThread = new EventThread(vsyncSrc, *this, false);
+    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            sfVsyncPhaseOffsetNs, true, "sf");
+    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
+    mEventQueue.setEventThread(mSFEventThread);
 
-        // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
-        struct sched_param param = {0};
-        param.sched_priority = 2;
-        if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-            ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
-        }
-        if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
-            ALOGE("Couldn't set SCHED_FIFO for EventThread");
-        }
-
-        // Get a RenderEngine for the given display / config (can't fail)
-        mRenderEngine = RenderEngine::create(mEGLDisplay,
-                HAL_PIXEL_FORMAT_RGBA_8888,
-                hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
+    // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
+    struct sched_param param = {0};
+    param.sched_priority = 2;
+    if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
+    }
+    if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 0) {
+        ALOGE("Couldn't set SCHED_FIFO for EventThread");
     }
 
-    // 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.");
-    mRealHwc = new HWComposer(mHwcServiceName);
-    mHwc = mRealHwc;
-    mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+    // Get a RenderEngine for the given display / config (can't fail)
+    mRenderEngine = RenderEngine::create(mEGLDisplay,
+            HAL_PIXEL_FORMAT_RGBA_8888,
+            hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
 
-    Mutex::Autolock _l(mStateLock);
+    // retrieve the EGL context that was selected/created
+    mEGLContext = mRenderEngine->getEGLContext();
+
+    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
+            "couldn't create EGLContext");
+
+    LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
+            "Starting with vr flinger active is not currently supported.");
+    mHwc.reset(new HWComposer(mHwcServiceName));
+    mHwc->registerCallback(this, mComposerSequenceId);
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
@@ -639,16 +651,6 @@
         }
     }
 
-    // retrieve the EGL context that was selected/created
-    mEGLContext = mRenderEngine->getEGLContext();
-
-    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
-            "couldn't create EGLContext");
-
-    // make the GLContext current so that we can create textures when creating
-    // Layers (which may happens before we render something)
-    getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
-
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
 
@@ -1218,11 +1220,16 @@
     sLastResyncAttempted = now;
 }
 
-void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
-                                     nsecs_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
+        hwc2_display_t displayId, int64_t timestamp) {
     Mutex::Autolock lock(mStateLock);
-    // Ignore any vsyncs from the non-active hardware composer.
-    if (composer != mHwc) {
+    // Ignore any vsyncs from a previous hardware composer.
+    if (sequenceId != mComposerSequenceId) {
+        return;
+    }
+
+    int32_t type;
+    if (!mHwc->onVsync(displayId, timestamp, &type)) {
         return;
     }
 
@@ -1230,7 +1237,7 @@
 
     { // Scope for the lock
         Mutex::Autolock _l(mHWVsyncLock);
-        if (type == 0 && mPrimaryHWVsyncEnabled) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
             needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
         }
     }
@@ -1248,7 +1255,7 @@
 }
 
 void SurfaceFlinger::createDefaultDisplayDevice() {
-    const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+    const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY;
     wp<IBinder> token = mBuiltinDisplays[type];
 
     // All non-virtual displays are currently considered secure.
@@ -1279,28 +1286,49 @@
     mDisplays.add(token, hw);
     setActiveColorModeInternal(hw, HAL_COLOR_MODE_NATIVE);
     hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+
+    // Add the primary display token to mDrawingState so we don't try to
+    // recreate the DisplayDevice for the primary display.
+    mDrawingState.displays.add(token, DisplayDeviceState(type, true));
+
+    // make the GLContext current so that we can create textures when creating
+    // Layers (which may happens before we render something)
+    hw->makeCurrent(mEGLDisplay, mEGLContext);
 }
 
-void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
-    ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
+        hwc2_display_t display, HWC2::Connection connection,
+        bool primaryDisplay) {
+    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
+          sequenceId, display,
+          connection == HWC2::Connection::Connected ?
+                  "connected" : "disconnected",
+          primaryDisplay ? "primary" : "external");
 
-    if (composer->isUsingVrComposer()) {
-        // We handle initializing the primary display device for the VR
-        // window manager hwc explicitly at the time of transition.
-        if (disp != DisplayDevice::DISPLAY_PRIMARY) {
-            ALOGE("External displays are not supported by the vr hardware composer.");
+    // Only lock if we're not on the main thread. This function is normally
+    // called on a hwbinder thread, but for the primary display it's called on
+    // the main thread with the state lock already held, so don't attempt to
+    // acquire it here.
+    ConditionalLock lock(mStateLock,
+            std::this_thread::get_id() != mMainThreadId);
+
+    if (primaryDisplay) {
+        mHwc->onHotplug(display, connection);
+        if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) {
+            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
         }
-        return;
-    }
-
-    if (disp == DisplayDevice::DISPLAY_PRIMARY) {
-        Mutex::Autolock lock(mStateLock);
-        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
         createDefaultDisplayDevice();
     } else {
+        if (sequenceId != mComposerSequenceId) {
+            return;
+        }
+        if (mHwc->isUsingVrComposer()) {
+            ALOGE("External displays are not supported by the vr hardware composer.");
+            return;
+        }
+        mHwc->onHotplug(display, connection);
         auto type = DisplayDevice::DISPLAY_EXTERNAL;
-        Mutex::Autolock _l(mStateLock);
-        if (connected) {
+        if (connection == HWC2::Connection::Connected) {
             createBuiltinDisplayLocked(type);
         } else {
             mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
@@ -1312,46 +1340,31 @@
     }
 }
 
-void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId,
+                                       hwc2_display_t /*display*/) {
     Mutex::Autolock lock(mStateLock);
-    if (composer == mHwc) {
-        repaintEverything();
-    } else {
-        // This isn't from our current hardware composer. If it's a callback
-        // from the real composer, forward the refresh request to vr
-        // flinger. Otherwise ignore it.
-        if (!composer->isUsingVrComposer()) {
-            mVrFlinger->OnHardwareComposerRefresh();
-        }
+    if (sequenceId != mComposerSequenceId) {
+        return;
     }
+    repaintEverything();
 }
 
 void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
     ATRACE_CALL();
+    Mutex::Autolock lock(mStateLock);
     getHwComposer().setVsyncEnabled(disp,
             enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
 }
 
 // Note: it is assumed the caller holds |mStateLock| when this is called
-void SurfaceFlinger::resetHwcLocked() {
+void SurfaceFlinger::resetDisplayState() {
     disableHardwareVsync(true);
-    clearHwcLayers(mDrawingState.layersSortedByZ);
-    clearHwcLayers(mCurrentState.layersSortedByZ);
-    for (size_t disp = 0; disp < mDisplays.size(); ++disp) {
-        clearHwcLayers(mDisplays[disp]->getVisibleLayersSortedByZ());
-    }
     // Clear the drawing state so that the logic inside of
     // handleTransactionLocked will fire. It will determine the delta between
     // mCurrentState and mDrawingState and re-apply all changes when we make the
     // transition.
     mDrawingState.displays.clear();
-    // Release virtual display hwcId during vr mode transition.
-    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
-        const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
-        if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
-            displayDevice->disconnect(getHwComposer());
-        }
-    }
+    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     mDisplays.clear();
 }
 
@@ -1363,57 +1376,54 @@
         return;
     }
 
-    if (vrFlingerRequestsDisplay && !mVrHwc) {
-        // Construct new HWComposer without holding any locks.
-        mVrHwc = new HWComposer("vr");
-
-        // Set up the event handlers. This step is neccessary to initialize the internal state of
-        // the hardware composer object properly. Our callbacks are designed such that if they are
-        // triggered between now and the point where the display is properly re-initialized, they
-        // will not have any effect, so this is safe to do here, before the lock is aquired.
-        mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
-        ALOGV("Vr HWC created");
+    if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) {
+        ALOGE("Vr flinger is only supported for remote hardware composer"
+              " service connections. Ignoring request to transition to vr"
+              " flinger.");
+        mVrFlingerRequestsDisplay = false;
+        return;
     }
 
     Mutex::Autolock _l(mStateLock);
 
-    if (vrFlingerRequestsDisplay) {
-        resetHwcLocked();
+    int currentDisplayPowerMode = getDisplayDeviceLocked(
+            mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode();
 
-        mHwc = mVrHwc;
-        mVrFlinger->GrantDisplayOwnership();
-
-    } else {
+    if (!vrFlingerRequestsDisplay) {
         mVrFlinger->SeizeDisplayOwnership();
+    }
 
-        resetHwcLocked();
+    resetDisplayState();
+    mHwc.reset();  // Delete the current instance before creating the new one
+    mHwc.reset(new HWComposer(
+            vrFlingerRequestsDisplay ? "vr" : mHwcServiceName));
+    mHwc->registerCallback(this, ++mComposerSequenceId);
 
-        mHwc = mRealHwc;
+    LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(),
+            "Switched to non-remote hardware composer");
+
+    if (vrFlingerRequestsDisplay) {
+        mVrFlinger->GrantDisplayOwnership();
+    } else {
         enableHardwareVsync();
     }
 
     mVisibleRegionsDirty = true;
     invalidateHwcGeometry();
 
-    // Explicitly re-initialize the primary display. This is because some other
-    // parts of this class rely on the primary display always being available.
-    createDefaultDisplayDevice();
-
     // Re-enable default display.
-    sp<LambdaMessage> requestMessage = new LambdaMessage([&]() {
-        sp<DisplayDevice> hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
-        setPowerModeInternal(hw, HWC_POWER_MODE_NORMAL);
+    sp<DisplayDevice> hw(getDisplayDeviceLocked(
+            mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
+    setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true);
 
-        // Reset the timing values to account for the period of the swapped in HWC
-        const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
-        const nsecs_t period = activeConfig->getVsyncPeriod();
-        mAnimFrameTracker.setDisplayRefreshPeriod(period);
+    // Reset the timing values to account for the period of the swapped in HWC
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const nsecs_t period = activeConfig->getVsyncPeriod();
+    mAnimFrameTracker.setDisplayRefreshPeriod(period);
 
-        // Use phase of 0 since phase is not known.
-        // Use latency of 0, which will snap to the ideal latency.
-        setCompositorTimingSnapped(0, period, 0);
-    });
-    postMessageAsync(requestMessage);
+    // Use phase of 0 since phase is not known.
+    // Use latency of 0, which will snap to the ideal latency.
+    setCompositorTimingSnapped(0, period, 0);
 
     android_atomic_or(1, &mRepaintEverything);
     setTransactionFlags(eDisplayTransactionNeeded);
@@ -1749,15 +1759,14 @@
                         } else {
                             // Clear out the HWC layer if this layer was
                             // previously visible, but no longer is
-                            layer->setHwcLayer(displayDevice->getHwcDisplayId(),
-                                    nullptr);
+                            layer->destroyHwcLayer(
+                                    displayDevice->getHwcDisplayId());
                         }
                     } else {
                         // WM changes displayDevice->layerStack upon sleep/awake.
                         // Here we make sure we delete the HWC layers even if
                         // WM changed their layer stack.
-                        layer->setHwcLayer(displayDevice->getHwcDisplayId(),
-                                nullptr);
+                        layer->destroyHwcLayer(displayDevice->getHwcDisplayId());
                     }
                 });
             }
@@ -1872,10 +1881,7 @@
                 for (size_t i = 0; i < currentLayers.size(); i++) {
                     const auto& layer = currentLayers[i];
                     if (!layer->hasHwcLayer(hwcId)) {
-                        auto hwcLayer = mHwc->createLayer(hwcId);
-                        if (hwcLayer) {
-                            layer->setHwcLayer(hwcId, std::move(hwcLayer));
-                        } else {
+                        if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
                             layer->forceClientComposition(hwcId);
                             continue;
                         }
@@ -2161,7 +2167,7 @@
                         if (state.surface != NULL) {
 
                             // Allow VR composer to use virtual displays.
-                            if (mUseHwcVirtualDisplays || mHwc == mVrHwc) {
+                            if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) {
                                 int width = 0;
                                 int status = state.surface->query(
                                         NATIVE_WINDOW_WIDTH, &width);
@@ -3285,7 +3291,8 @@
     d.height = 0;
     displays.add(d);
     setTransactionState(state, displays, 0);
-    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
+    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
+                         /*stateLockHeld*/ false);
 
     const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
     const nsecs_t period = activeConfig->getVsyncPeriod();
@@ -3311,7 +3318,7 @@
 }
 
 void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
-        int mode) {
+             int mode, bool stateLockHeld) {
     ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
             this);
     int32_t type = hw->getDisplayType();
@@ -3328,7 +3335,7 @@
     }
 
     if (mInterceptor.isEnabled()) {
-        Mutex::Autolock _l(mStateLock);
+        ConditionalLock lock(mStateLock, !stateLockHeld);
         ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
         if (idx < 0) {
             ALOGW("Surface Interceptor SavePowerMode: invalid display token");
@@ -3414,7 +3421,8 @@
                 ALOGW("Attempt to set power mode = %d for virtual display",
                         mMode);
             } else {
-                mFlinger.setPowerModeInternal(hw, mMode);
+                mFlinger.setPowerModeInternal(
+                        hw, mMode, /*stateLockHeld*/ false);
             }
             return true;
         }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5123b58..058f4a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,13 +60,20 @@
 #include "SurfaceInterceptor.h"
 #include "StartPropertySetThread.h"
 
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
 #include "DisplayHardware/HWComposer.h"
+#else
+#include "DisplayHardware/HWComposer_hwc1.h"
+#endif
+
 #include "Effects/Daltonizer.h"
 
 #include <map>
 #include <mutex>
 #include <queue>
 #include <string>
+#include <thread>
 #include <utility>
 
 namespace android {
@@ -99,7 +106,11 @@
 
 class SurfaceFlinger : public BnSurfaceComposer,
                        private IBinder::DeathRecipient,
+#ifdef USE_HWC2
+                       private HWC2::ComposerCallback
+#else
                        private HWComposer::EventHandler
+#endif
 {
 public:
 
@@ -314,11 +325,20 @@
     virtual void onFirstRef();
 
     /* ------------------------------------------------------------------------
-     * HWComposer::EventHandler interface
+     * HWC2::ComposerCallback / HWComposer::EventHandler interface
      */
-    virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
-    virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
-    virtual void onInvalidateReceived(HWComposer* composer);
+#ifdef USE_HWC2
+    void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+                         int64_t timestamp) override;
+    void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+                           HWC2::Connection connection,
+                           bool primaryDisplay) override;
+    void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+#else
+    void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
+    void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
+    void onInvalidateReceived(HWComposer* composer) override;
+#endif
 
     /* ------------------------------------------------------------------------
      * Message handling
@@ -333,7 +353,12 @@
     // called on the main thread in response to setActiveConfig()
     void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
     // called on the main thread in response to setPowerMode()
+#ifdef USE_HWC2
+    void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
+                              bool stateLockHeld);
+#else
     void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
+#endif
 
     // Called on the main thread in response to setActiveColorMode()
     void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
@@ -591,13 +616,7 @@
     /* ------------------------------------------------------------------------
      * VrFlinger
      */
-    template<typename T>
-    void clearHwcLayers(const T& layers) {
-        for (size_t i = 0; i < layers.size(); ++i) {
-            layers[i]->clearHwcLayers();
-        }
-    }
-    void resetHwcLocked();
+    void resetDisplayState();
 
     // Check to see if we should handoff to vr flinger.
     void updateVrFlinger();
@@ -624,13 +643,14 @@
     // access must be protected by mInvalidateLock
     volatile int32_t mRepaintEverything;
 
-    // current, real and vr hardware composers.
-    HWComposer* mHwc;
+    // The current hardware composer interface. When switching into and out of
+    // vr, our HWComposer instance will be recreated.
+    std::unique_ptr<HWComposer> mHwc;
+
 #ifdef USE_HWC2
-    HWComposer* mRealHwc;
-    HWComposer* mVrHwc;
     const std::string mHwcServiceName; // "default" for real use, something else for testing.
 #endif
+
     // constant members (no synchronization needed for access)
     RenderEngine* mRenderEngine;
     nsecs_t mBootTime;
@@ -644,10 +664,6 @@
     EGLDisplay mEGLDisplay;
     sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
 
-#ifdef USE_HWC2
-    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
-#endif
-
     // Can only accessed from the main thread, these members
     // don't need synchronization
     State mDrawingState{LayerVector::StateSet::Drawing};
@@ -769,8 +785,14 @@
     status_t CheckTransactCodeCredentials(uint32_t code);
 
 #ifdef USE_HWC2
+    std::unique_ptr<dvr::VrFlinger> mVrFlinger;
     std::atomic<bool> mVrFlingerRequestsDisplay;
     static bool useVrFlinger;
+    std::thread::id mMainThreadId;
+    // The composer sequence id is a monotonically increasing integer that we
+    // use to differentiate callbacks from different hardware composer
+    // instances. Each hardware composer instance gets a different sequence id.
+    int32_t mComposerSequenceId;
 #endif
 
     float mSaturation = 1.0f;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 7aaa42a..78a04e0 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -535,8 +535,8 @@
 
     // Initialize the H/W composer object.  There may or may not be an
     // actual hardware composer underneath.
-    mHwc = new HWComposer(this,
-            *static_cast<HWComposer::EventHandler *>(this));
+    mHwc.reset(new HWComposer(this,
+            *static_cast<HWComposer::EventHandler *>(this)));
 
     // get a RenderEngine for the given display / config (can't fail)
     mRenderEngine = RenderEngine::create(mEGLDisplay,