drm_hwcomposer: Merge remote-tracking branch 'aosp/upstream-main' into HEAD am: 38163fdedc

Original change: https://android-review.googlesource.com/c/platform/external/drm_hwcomposer/+/1809159

Change-Id: I97b4652389ac4dd30b56e7992431a1cf831e73c7
diff --git a/.ci/.common.sh b/.ci/.common.sh
index 93f7f95..0183aba 100644
--- a/.ci/.common.sh
+++ b/.ci/.common.sh
@@ -5,7 +5,7 @@
 
 CXXARGS="-fPIC -Wall -Werror -DPLATFORM_SDK_VERSION=30 -D__ANDROID_API__=30 -Wsign-promo -Wimplicit-fallthrough"
 CXXARGS+=" -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -Wno-gnu-include-next "
-CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fexceptions -fno-rtti"
+CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fno-rtti"
 
 BUILD_FILES=(
 backend/BackendClient.cpp
@@ -28,7 +28,7 @@
 drm/DrmDevice.cpp
 drm/DrmEncoder.cpp
 drm/DrmEventListener.cpp
-drm/DrmGenericImporter.cpp
+drm/DrmFbImporter.cpp
 drm/DrmMode.cpp
 drm/DrmPlane.cpp
 drm/DrmProperty.cpp
diff --git a/.ci/.gitlab-ci-clang-tidy-fine.sh b/.ci/.gitlab-ci-clang-tidy-fine.sh
index 644f621..c1805e8 100755
--- a/.ci/.gitlab-ci-clang-tidy-fine.sh
+++ b/.ci/.gitlab-ci-clang-tidy-fine.sh
@@ -3,6 +3,8 @@
 . ./.ci/.common.sh
 
 TIDY_FILES=(
+drm/DrmFbImporter.h
+utils/UniqueFd.h
 utils/log.h
 utils/properties.h
 )
diff --git a/Android.bp b/Android.bp
index d3c812d..a4d8e18 100644
--- a/Android.bp
+++ b/Android.bp
@@ -113,7 +113,7 @@
         "drm/DrmDevice.cpp",
         "drm/DrmEncoder.cpp",
         "drm/DrmEventListener.cpp",
-        "drm/DrmGenericImporter.cpp",
+        "drm/DrmFbImporter.cpp",
         "drm/DrmMode.cpp",
         "drm/DrmPlane.cpp",
         "drm/DrmProperty.cpp",
diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp
index 8b2abfd..02667cf 100644
--- a/DrmHwcTwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -19,9 +19,11 @@
 
 #include "DrmHwcTwo.h"
 
+#include <fcntl.h>
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer2.h>
 #include <sync/sync.h>
+#include <unistd.h>
 
 #include <cinttypes>
 #include <iostream>
@@ -47,14 +49,13 @@
 HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
                                      HWC2::DisplayType type) {
   DrmDevice *drm = resource_manager_.GetDrmDevice(displ);
-  std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ);
-  if (!drm || !importer) {
-    ALOGE("Failed to get a valid drmresource and importer");
+  if (!drm) {
+    ALOGE("Failed to get a valid drmresource");
     return HWC2::Error::NoResources;
   }
   displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
-                    std::forward_as_tuple(&resource_manager_, drm, importer,
-                                          displ, type));
+                    std::forward_as_tuple(&resource_manager_, drm, displ,
+                                          type));
 
   DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
   if (!crtc) {
@@ -209,12 +210,10 @@
 }
 
 DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
-                                  DrmDevice *drm,
-                                  std::shared_ptr<Importer> importer,
-                                  hwc2_display_t handle, HWC2::DisplayType type)
+                                  DrmDevice *drm, hwc2_display_t handle,
+                                  HWC2::DisplayType type)
     : resource_manager_(resource_manager),
       drm_(drm),
-      importer_(std::move(importer)),
       handle_(handle),
       type_(type),
       color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
@@ -583,6 +582,9 @@
   return HWC2::Error::None;
 }
 
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767
+ */
 HWC2::Error DrmHwcTwo::HwcDisplay::GetReleaseFences(uint32_t *num_elements,
                                                     hwc2_layer_t *layers,
                                                     int32_t *fences) {
@@ -600,22 +602,22 @@
     }
 
     layers[num_layers - 1] = l.first;
-    fences[num_layers - 1] = l.second.take_release_fence();
+    fences[num_layers - 1] = l.second.release_fence_.Release();
   }
   *num_elements = num_layers;
   return HWC2::Error::None;
 }
 
-void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(int fd) {
-  if (fd < 0)
+void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(UniqueFd fd) {
+  if (!fd) {
     return;
+  }
 
-  if (present_fence_.get() >= 0) {
-    int old_fence = present_fence_.get();
-    present_fence_.Set(sync_merge("dc_present", old_fence, fd));
-    close(fd);
+  if (present_fence_) {
+    present_fence_ = UniqueFd(
+        sync_merge("dc_present", present_fence_.Get(), fd.Get()));
   } else {
-    present_fence_.Set(fd);
+    present_fence_ = std::move(fd);
   }
 }
 
@@ -650,7 +652,7 @@
   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
     DrmHwcLayer layer;
     l.second->PopulateDrmLayer(&layer);
-    int ret = layer.ImportBuffer(importer_.get());
+    int ret = layer.ImportBuffer(drm_);
     if (ret) {
       ALOGE("Failed to import layer, ret=%d", ret);
       return HWC2::Error::NoResources;
@@ -673,7 +675,7 @@
   std::vector<DrmPlane *> overlay_planes(overlay_planes_);
   ret = composition->Plan(&primary_planes, &overlay_planes);
   if (ret) {
-    ALOGE("Failed to plan the composition ret=%d", ret);
+    ALOGV("Failed to plan the composition ret=%d", ret);
     return HWC2::Error::BadConfig;
   }
 
@@ -701,6 +703,9 @@
   return HWC2::Error::None;
 }
 
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805
+ */
 HWC2::Error DrmHwcTwo::HwcDisplay::PresentDisplay(int32_t *present_fence) {
   supported(__func__);
   HWC2::Error ret;
@@ -761,15 +766,17 @@
   return HWC2::Error::None;
 }
 
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1861
+ */
 HWC2::Error DrmHwcTwo::HwcDisplay::SetClientTarget(buffer_handle_t target,
                                                    int32_t acquire_fence,
                                                    int32_t dataspace,
                                                    hwc_region_t /*damage*/) {
   supported(__func__);
-  UniqueFd uf(acquire_fence);
 
   client_layer_.set_buffer(target);
-  client_layer_.set_acquire_fence(uf.get());
+  client_layer_.acquire_fence_ = UniqueFd(acquire_fence);
   client_layer_.SetLayerDataspace(dataspace);
 
   /* TODO: Do not update source_crop every call.
@@ -1047,13 +1054,15 @@
   return HWC2::Error::None;
 }
 
+/* Find API details at:
+ * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=2314
+ */
 HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer,
                                                 int32_t acquire_fence) {
   supported(__func__);
-  UniqueFd uf(acquire_fence);
 
   set_buffer(buffer);
-  set_acquire_fence(uf.get());
+  acquire_fence_ = UniqueFd(acquire_fence);
   return HWC2::Error::None;
 }
 
@@ -1144,11 +1153,9 @@
       break;
   }
 
-  OutputFd release_fence = release_fence_output();
-
   layer->sf_handle = buffer_;
-  layer->acquire_fence = acquire_fence_.Release();
-  layer->release_fence = std::move(release_fence);
+  // TODO(rsglobal): Avoid extra fd duplication
+  layer->acquire_fence = UniqueFd(fcntl(acquire_fence_.Get(), F_DUPFD_CLOEXEC));
   layer->display_frame = display_frame_;
   layer->alpha = lround(65535.0F * alpha_);
   layer->source_crop = source_crop_;
diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h
index a0d8cdd..111c664 100644
--- a/DrmHwcTwo.h
+++ b/DrmHwcTwo.h
@@ -25,7 +25,6 @@
 
 #include "compositor/DrmDisplayCompositor.h"
 #include "compositor/Planner.h"
-#include "drm/DrmGenericImporter.h"
 #include "drm/ResourceManager.h"
 #include "drm/VSyncWorker.h"
 #include "drmhwcomposer.h"
@@ -83,27 +82,6 @@
       buffer_ = buffer;
     }
 
-    int take_acquire_fence() {
-      return acquire_fence_.Release();
-    }
-    void set_acquire_fence(int acquire_fence) {
-      acquire_fence_.Set(dup(acquire_fence));
-    }
-
-    int release_fence() {
-      return release_fence_.get();
-    }
-    int take_release_fence() {
-      return release_fence_.Release();
-    }
-    void manage_release_fence() {
-      release_fence_.Set(release_fence_raw_);
-      release_fence_raw_ = -1;
-    }
-    OutputFd release_fence_output() {
-      return OutputFd(&release_fence_raw_);
-    }
-
     hwc_rect_t display_frame() {
       return display_frame_;
     }
@@ -139,6 +117,16 @@
     HWC2::Error SetLayerVisibleRegion(hwc_region_t visible);
     HWC2::Error SetLayerZOrder(uint32_t order);
 
+    UniqueFd acquire_fence_;
+
+    /*
+     * Release fence is not used.
+     * There is no release fence support available in the DRM/KMS. In case no
+     * release fence provided application will use this buffer for writing when
+     * the next frame present fence is signaled.
+     */
+    UniqueFd release_fence_;
+
    private:
     // sf_type_ stores the initial type given to us by surfaceflinger,
     // validated_type_ stores the type after running ValidateDisplay
@@ -147,9 +135,6 @@
 
     HWC2::BlendMode blending_ = HWC2::BlendMode::None;
     buffer_handle_t buffer_ = NULL;
-    UniqueFd acquire_fence_;
-    int release_fence_raw_ = -1;
-    UniqueFd release_fence_;
     hwc_rect_t display_frame_;
     float alpha_ = 1.0f;
     hwc_frect_t source_crop_;
@@ -164,8 +149,7 @@
   class HwcDisplay {
    public:
     HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
-               std::shared_ptr<Importer> importer, hwc2_display_t handle,
-               HWC2::DisplayType type);
+               hwc2_display_t handle, HWC2::DisplayType type);
     HwcDisplay(const HwcDisplay &) = delete;
     HWC2::Error Init(std::vector<DrmPlane *> *planes);
 
@@ -305,10 +289,6 @@
       return connector_;
     }
 
-    const std::shared_ptr<Importer> &importer() const {
-      return importer_;
-    }
-
     ResourceManager *resource_manager() const {
       return resource_manager_;
     }
@@ -322,14 +302,13 @@
     }
 
    private:
-    void AddFenceToPresentFence(int fd);
+    void AddFenceToPresentFence(UniqueFd fd);
 
     constexpr static size_t MATRIX_SIZE = 16;
 
     ResourceManager *resource_manager_;
     DrmDevice *drm_;
     DrmDisplayCompositor compositor_;
-    std::shared_ptr<Importer> importer_;
     std::unique_ptr<Planner> planner_;
 
     std::vector<DrmPlane *> primary_planes_;
diff --git a/compositor/DrmDisplayComposition.cpp b/compositor/DrmDisplayComposition.cpp
index 7008e9c..49dff0e 100644
--- a/compositor/DrmDisplayComposition.cpp
+++ b/compositor/DrmDisplayComposition.cpp
@@ -101,7 +101,7 @@
                                                             primary_planes,
                                                             overlay_planes);
   if (ret) {
-    ALOGE("Planner failed provisioning planes ret=%d", ret);
+    ALOGV("Planner failed provisioning planes ret=%d", ret);
     return ret;
   }
 
@@ -156,14 +156,10 @@
   }
 }
 
-static void DumpBuffer(const DrmHwcBuffer &buffer, std::ostringstream *out) {
-  if (!buffer) {
-    *out << "buffer=<invalid>";
-    return;
-  }
-
+static void DumpBuffer(const DrmHwcLayer &layer, std::ostringstream *out) {
   *out << "buffer[w/h/format]=";
-  *out << buffer->width << "/" << buffer->height << "/" << buffer->format;
+  *out << layer.buffer_info.width << "/" << layer.buffer_info.height << "/"
+       << layer.buffer_info.format;
 }
 
 static void DumpTransform(uint32_t transform, std::ostringstream *out) {
@@ -249,7 +245,7 @@
     const DrmHwcLayer &layer = layers_[i];
     *out << "      [" << i << "] ";
 
-    DumpBuffer(layer.buffer, out);
+    DumpBuffer(layer, out);
 
     if (layer.protected_usage())
       *out << " protected";
diff --git a/compositor/DrmDisplayComposition.h b/compositor/DrmDisplayComposition.h
index 27b34f2..1738630 100644
--- a/compositor/DrmDisplayComposition.h
+++ b/compositor/DrmDisplayComposition.h
@@ -127,16 +127,10 @@
     return planner_;
   }
 
-  int take_out_fence() {
-    return out_fence_.Release();
-  }
-
-  void set_out_fence(int out_fence) {
-    out_fence_.Set(out_fence);
-  }
-
   void Dump(std::ostringstream *out) const;
 
+  UniqueFd out_fence_;
+
  private:
   bool validate_composition_type(DrmCompositionType desired);
 
@@ -147,8 +141,6 @@
   uint32_t dpms_mode_ = DRM_MODE_DPMS_ON;
   DrmMode display_mode_;
 
-  UniqueFd out_fence_ = -1;
-
   bool geometry_changed_ = true;
   std::vector<DrmHwcLayer> layers_;
   std::vector<DrmCompositionPlane> composition_planes_;
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index 665446e..a1fe50f 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -286,12 +286,12 @@
         break;
       }
       DrmHwcLayer &layer = layers[source_layers.front()];
-      if (!layer.buffer) {
+      if (!layer.FbIdHandle) {
         ALOGE("Expected a valid framebuffer for pset");
         break;
       }
-      fb_id = layer.buffer->fb_id;
-      fence_fd = layer.acquire_fence.get();
+      fb_id = layer.FbIdHandle->GetFbId();
+      fence_fd = layer.acquire_fence.Get();
       display_frame = layer.display_frame;
       source_crop = layer.source_crop;
       alpha = layer.alpha;
@@ -540,7 +540,7 @@
   }
 
   if (crtc->out_fence_ptr_property().id()) {
-    display_comp->set_out_fence((int)out_fences[crtc->pipe()]);
+    display_comp->out_fence_ = UniqueFd((int)out_fences[crtc->pipe()]);
   }
 
   return ret;
diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h
index aebb6ff..c0eed0c 100644
--- a/compositor/DrmDisplayCompositor.h
+++ b/compositor/DrmDisplayCompositor.h
@@ -72,10 +72,11 @@
   void Dump(std::ostringstream *out) const;
   void Vsync(int display, int64_t timestamp);
   void ClearDisplay();
-  int TakeOutFence() {
-    if (!active_composition_)
-      return -1;
-    return active_composition_->take_out_fence();
+  UniqueFd TakeOutFence() {
+    if (!active_composition_) {
+      return UniqueFd();
+    }
+    return std::move(active_composition_->out_fence_);
   }
 
   FlatteningState GetFlatteningState() const;
diff --git a/compositor/Planner.cpp b/compositor/Planner.cpp
index 42259d1..9db03c3 100644
--- a/compositor/Planner.cpp
+++ b/compositor/Planner.cpp
@@ -60,7 +60,7 @@
   for (auto &i : stages_) {
     int ret = i->ProvisionPlanes(&composition, layers, &planes);
     if (ret) {
-      ALOGE("Failed provision stage with ret %d", ret);
+      ALOGV("Failed provision stage with ret %d", ret);
       return std::make_tuple(ret, std::vector<DrmCompositionPlane>());
     }
   }
@@ -105,7 +105,7 @@
       break;
 
     if (ret) {
-      ALOGE("Failed to emplace layer %zu, dropping it", i->first);
+      ALOGV("Failed to emplace layer %zu, dropping it", i->first);
       return ret;
     }
   }
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index 150aa01..abc8edc 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -112,6 +112,8 @@
 }
 
 DrmDevice::DrmDevice() : event_listener_(this) {
+  self.reset(this);
+  mDrmFbImporter = std::make_unique<DrmFbImporter>(self);
 }
 
 DrmDevice::~DrmDevice() {
@@ -120,7 +122,7 @@
 
 std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) {
   /* TODO: Use drmOpenControl here instead */
-  fd_.Set(open(path, O_RDWR | O_CLOEXEC));
+  fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC));
   if (fd() < 0) {
     ALOGE("Failed to open dri %s: %s", path, strerror(errno));
     return std::make_tuple(-ENODEV, 0);
@@ -146,6 +148,13 @@
   }
 #endif
 
+  uint64_t cap_value = 0;
+  if (drmGetCap(fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) {
+    ALOGW("drmGetCap failed. Fallback to no modifier support.");
+    cap_value = 0;
+  }
+  HasAddFb2ModifiersSupport_ = cap_value != 0;
+
   drmSetMaster(fd());
   if (!drmIsMaster(fd())) {
     ALOGE("DRM/KMS master access required");
@@ -576,9 +585,9 @@
 }
 
 std::string DrmDevice::GetName() const {
-  auto *ver = drmGetVersion(fd_.get());
+  auto *ver = drmGetVersion(fd());
   if (!ver) {
-    ALOGW("Failed to get drm version for fd=%d", fd_.get());
+    ALOGW("Failed to get drm version for fd=%d", fd());
     return "generic";
   }
 
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index d8f347f..dfca263 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -26,10 +26,15 @@
 #include "DrmCrtc.h"
 #include "DrmEncoder.h"
 #include "DrmEventListener.h"
+#include "DrmFbImporter.h"
 #include "DrmPlane.h"
+#include "utils/UniqueFd.h"
 
 namespace android {
 
+class DrmFbImporter;
+class DrmPlane;
+
 class DrmDevice {
  public:
   DrmDevice();
@@ -38,7 +43,7 @@
   std::tuple<int, int> Init(const char *path, int num_displays);
 
   int fd() const {
-    return fd_.get();
+    return fd_.Get();
   }
 
   const std::vector<std::unique_ptr<DrmConnector>> &connectors() const {
@@ -83,6 +88,14 @@
     event_listener_.RegisterHotplugHandler(handler);
   }
 
+  bool HasAddFb2ModifiersSupport() const {
+    return HasAddFb2ModifiersSupport_;
+  }
+
+  DrmFbImporter &GetDrmFbImporter() {
+    return *mDrmFbImporter.get();
+  }
+
  private:
   int TryEncoderForDisplay(int display, DrmEncoder *enc);
   int GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name,
@@ -104,6 +117,12 @@
   std::pair<uint32_t, uint32_t> min_resolution_;
   std::pair<uint32_t, uint32_t> max_resolution_;
   std::map<int, int> displays_;
+
+  bool HasAddFb2ModifiersSupport_{};
+
+  std::shared_ptr<DrmDevice> self;
+
+  std::unique_ptr<DrmFbImporter> mDrmFbImporter;
 };
 }  // namespace android
 
diff --git a/drm/DrmEventListener.cpp b/drm/DrmEventListener.cpp
index a6eee47..b303653 100644
--- a/drm/DrmEventListener.cpp
+++ b/drm/DrmEventListener.cpp
@@ -39,11 +39,11 @@
 }
 
 int DrmEventListener::Init() {
-  uevent_fd_.Set(
+  uevent_fd_ = UniqueFd(
       socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
-  if (uevent_fd_.get() < 0) {
+  if (!uevent_fd_) {
     ALOGE("Failed to open uevent socket: %s", strerror(errno));
-    return uevent_fd_.get();
+    return -errno;
   }
 
   struct sockaddr_nl addr {};
@@ -51,7 +51,7 @@
   addr.nl_pid = 0;
   addr.nl_groups = 0xFFFFFFFF;
 
-  int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr));
+  int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr));
   if (ret) {
     ALOGE("Failed to bind uevent socket: %s", strerror(errno));
     return -errno;
@@ -60,8 +60,8 @@
   // NOLINTNEXTLINE(readability-isolate-declaration)
   FD_ZERO(&fds_);
   FD_SET(drm_->fd(), &fds_);
-  FD_SET(uevent_fd_.get(), &fds_);
-  max_fd_ = std::max(drm_->fd(), uevent_fd_.get());
+  FD_SET(uevent_fd_.Get(), &fds_);
+  max_fd_ = std::max(drm_->fd(), uevent_fd_.Get());
 
   return InitWorker();
 }
@@ -96,7 +96,7 @@
     ALOGE("Failed to get monotonic clock on hotplug %d", ret);
 
   while (true) {
-    ret = read(uevent_fd_.get(), &buffer, sizeof(buffer));
+    ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
     if (ret == 0)
       return;
 
@@ -139,7 +139,7 @@
     drmHandleEvent(drm_->fd(), &event_context);
   }
 
-  if (FD_ISSET(uevent_fd_.get(), &fds_))
+  if (FD_ISSET(uevent_fd_.Get(), &fds_))
     UEventHandler();
 }
 }  // namespace android
diff --git a/drm/DrmEventListener.h b/drm/DrmEventListener.h
index c880a8c..f1f7310 100644
--- a/drm/DrmEventListener.h
+++ b/drm/DrmEventListener.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_DRM_EVENT_LISTENER_H_
 #define ANDROID_DRM_EVENT_LISTENER_H_
 
-#include "autofd.h"
+#include "utils/UniqueFd.h"
 #include "utils/Worker.h"
 
 namespace android {
diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp
new file mode 100644
index 0000000..8440093
--- /dev/null
+++ b/drm/DrmFbImporter.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define LOG_TAG "hwc-platform-drm-generic"
+
+#include "DrmFbImporter.h"
+
+#include <hardware/gralloc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cinttypes>
+#include <system_error>
+
+#include "utils/log.h"
+#include "utils/properties.h"
+
+namespace android {
+
+auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle,
+                                   const std::shared_ptr<DrmDevice> &drm)
+    -> std::shared_ptr<DrmFbIdHandle> {
+  // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage
+  std::shared_ptr<DrmFbIdHandle> local(new DrmFbIdHandle(drm));
+
+  local->gem_handles_[0] = first_gem_handle;
+  int32_t err = 0;
+
+  /* Framebuffer object creation require gem handle for every used plane */
+  for (int i = 1; i < local->gem_handles_.size(); i++) {
+    if (bo->prime_fds[i] > 0) {
+      if (bo->prime_fds[i] != bo->prime_fds[0]) {
+        err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i],
+                                 &local->gem_handles_.at(i));
+        if (err != 0) {
+          ALOGE("failed to import prime fd %d errno=%d", bo->prime_fds[i],
+                errno);
+        }
+      } else {
+        local->gem_handles_.at(i) = local->gem_handles_[0];
+      }
+    }
+  }
+
+  bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE &&
+                       bo->modifiers[0] != DRM_FORMAT_MOD_INVALID;
+
+  if (!drm->HasAddFb2ModifiersSupport() && has_modifiers) {
+    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
+          bo->modifiers[0]);
+    local.reset();
+    return local;
+  }
+
+  /* Create framebuffer object */
+  if (!has_modifiers) {
+    err = drmModeAddFB2(drm->fd(), bo->width, bo->height, bo->format,
+                        &local->gem_handles_[0], &bo->pitches[0],
+                        &bo->offsets[0], &local->fb_id_, 0);
+  } else {
+    err = drmModeAddFB2WithModifiers(drm->fd(), bo->width, bo->height,
+                                     bo->format, &local->gem_handles_[0],
+                                     &bo->pitches[0], &bo->offsets[0],
+                                     &bo->modifiers[0], &local->fb_id_,
+                                     DRM_MODE_FB_MODIFIERS);
+  }
+  if (err != 0) {
+    ALOGE("could not create drm fb %d", err);
+    local.reset();
+  }
+
+  return local;
+}
+
+DrmFbIdHandle::~DrmFbIdHandle() {
+  /* Destroy framebuffer object */
+  if (drmModeRmFB(drm_->fd(), fb_id_) != 0) {
+    ALOGE("Failed to rm fb");
+  }
+
+  /* Close GEM handles.
+   *
+   * WARNING: TODO(nobody):
+   * From Linux side libweston relies on libgbm to get KMS handle and never
+   * closes it (handle is closed by libgbm on buffer destruction)
+   * Probably we should offer similar approach to users (at least on user
+   * request via system properties)
+   */
+  struct drm_gem_close gem_close {};
+  for (int i = 0; i < gem_handles_.size(); i++) {
+    /* Don't close invalid handle. Close handle only once in cases
+     * where several YUV planes located in the single buffer. */
+    if (gem_handles_[i] == 0 ||
+        (i != 0 && gem_handles_[i] == gem_handles_[0])) {
+      continue;
+    }
+    gem_close.handle = gem_handles_[i];
+    int32_t err = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+    if (err != 0) {
+      ALOGE("Failed to close gem handle %d, errno: %d", gem_handles_[i], errno);
+    }
+  }
+}
+
+auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo)
+    -> std::shared_ptr<DrmFbIdHandle> {
+  /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */
+  GemHandle first_handle = 0;
+  int32_t err = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &first_handle);
+
+  if (err != 0) {
+    ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err);
+    return std::shared_ptr<DrmFbIdHandle>();
+  }
+
+  auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle);
+
+  if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) {
+    if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second.lock()) {
+      return drm_fb_id_handle_shared;
+    }
+    drm_fb_id_handle_cache_.erase(drm_fb_id_cached);
+  }
+
+  /* Cleanup cached empty weak pointers */
+  const int minimal_cleanup_size = 128;
+  if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) {
+    CleanupEmptyCacheElements();
+  }
+
+  /* No DrmFbIdHandle found in cache, create framebuffer object */
+  auto fb_id_handle = DrmFbIdHandle::CreateInstance(bo, first_handle, drm_);
+  if (fb_id_handle) {
+    drm_fb_id_handle_cache_[first_handle] = fb_id_handle;
+  }
+
+  return fb_id_handle;
+}
+
+}  // namespace android
diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h
new file mode 100644
index 0000000..167aa60
--- /dev/null
+++ b/drm/DrmFbImporter.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_DRMFBIMPORTER_H_
+#define DRM_DRMFBIMPORTER_H_
+
+#include <drm/drm_fourcc.h>
+#include <hardware/gralloc.h>
+
+#include <array>
+#include <map>
+
+#include "drm/DrmDevice.h"
+#include "drmhwcgralloc.h"
+
+#ifndef DRM_FORMAT_INVALID
+#define DRM_FORMAT_INVALID 0
+#endif
+
+using GemHandle = uint32_t;
+
+namespace android {
+
+class DrmFbIdHandle {
+ public:
+  static auto CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle,
+                             const std::shared_ptr<DrmDevice> &drm)
+      -> std::shared_ptr<DrmFbIdHandle>;
+
+  ~DrmFbIdHandle();
+  DrmFbIdHandle(DrmFbIdHandle &&) = delete;
+  DrmFbIdHandle(const DrmFbIdHandle &) = delete;
+  auto operator=(const DrmFbIdHandle &) = delete;
+  auto operator=(DrmFbIdHandle &&) = delete;
+
+  auto GetFbId [[nodiscard]] () const -> uint32_t {
+    return fb_id_;
+  }
+
+ private:
+  explicit DrmFbIdHandle(std::shared_ptr<DrmDevice> drm)
+      : drm_(std::move(drm)){};
+
+  const std::shared_ptr<DrmDevice> drm_;
+
+  uint32_t fb_id_{};
+  std::array<GemHandle, HWC_DRM_BO_MAX_PLANES> gem_handles_{};
+};
+
+class DrmFbImporter {
+ public:
+  explicit DrmFbImporter(std::shared_ptr<DrmDevice> drm)
+      : drm_(std::move(drm)){};
+  ~DrmFbImporter() = default;
+  DrmFbImporter(const DrmFbImporter &) = delete;
+  DrmFbImporter(DrmFbImporter &&) = delete;
+  auto operator=(const DrmFbImporter &) = delete;
+  auto operator=(DrmFbImporter &&) = delete;
+
+  auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr<DrmFbIdHandle>;
+
+ private:
+  void CleanupEmptyCacheElements() {
+    for (auto it = drm_fb_id_handle_cache_.begin();
+         it != drm_fb_id_handle_cache_.end();) {
+      if (it->second.expired()) {
+        it = drm_fb_id_handle_cache_.erase(it);
+      } else {
+        ++it;
+      }
+    }
+  }
+
+  const std::shared_ptr<DrmDevice> drm_;
+
+  std::map<GemHandle, std::weak_ptr<DrmFbIdHandle>> drm_fb_id_handle_cache_;
+};
+
+}  // namespace android
+
+#endif
diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp
deleted file mode 100644
index 0cbe601..0000000
--- a/drm/DrmGenericImporter.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "hwc-platform-drm-generic"
-
-#include "DrmGenericImporter.h"
-
-#include <gralloc_handle.h>
-#include <hardware/gralloc.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <cinttypes>
-
-#include "utils/log.h"
-#include "utils/properties.h"
-
-namespace android {
-
-DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) {
-  uint64_t cap_value = 0;
-  if (drmGetCap(drm_->fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) {
-    ALOGE("drmGetCap failed. Fallback to no modifier support.");
-    cap_value = 0;
-  }
-  has_modifier_support_ = cap_value != 0;
-}
-
-int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) {
-  int ret = 0;
-
-  for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
-    if (bo->prime_fds[i] > 0) {
-      if (i == 0 || bo->prime_fds[i] != bo->prime_fds[0]) {
-        ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[i],
-                                 &bo->gem_handles[i]);
-        if (ret) {
-          ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[i], ret);
-          return ret;
-        }
-      } else {
-        bo->gem_handles[i] = bo->gem_handles[0];
-      }
-    }
-  }
-
-  bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE &&
-                       bo->modifiers[0] != DRM_FORMAT_MOD_INVALID;
-
-  if (!has_modifier_support_ && has_modifiers) {
-    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
-          bo->modifiers[0]);
-    return -EINVAL;
-  }
-
-  if (!has_modifiers)
-    ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
-                        bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id,
-                        0);
-  else
-    ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
-                                     bo->format, bo->gem_handles, bo->pitches,
-                                     bo->offsets, bo->modifiers, &bo->fb_id,
-                                     DRM_MODE_FB_MODIFIERS);
-
-  if (ret) {
-    ALOGE("could not create drm fb %d", ret);
-    return ret;
-  }
-
-  for (unsigned int gem_handle : bo->gem_handles) {
-    if (!gem_handle)
-      continue;
-
-    ImportHandle(gem_handle);
-  }
-
-  return ret;
-}
-
-int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
-  if (bo->fb_id)
-    if (drmModeRmFB(drm_->fd(), bo->fb_id))
-      ALOGE("Failed to rm fb");
-
-  for (unsigned int &gem_handle : bo->gem_handles) {
-    if (!gem_handle)
-      continue;
-
-    if (ReleaseHandle(gem_handle))
-      ALOGE("Failed to release gem handle %d", gem_handle);
-    else
-      gem_handle = 0;
-  }
-  return 0;
-}
-
-int DrmGenericImporter::ImportHandle(uint32_t gem_handle) {
-  gem_refcount_[gem_handle]++;
-
-  return 0;
-}
-
-int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) {
-  if (--gem_refcount_[gem_handle])
-    return 0;
-
-  gem_refcount_.erase(gem_handle);
-
-  return CloseHandle(gem_handle);
-}
-
-int DrmGenericImporter::CloseHandle(uint32_t gem_handle) {
-  struct drm_gem_close gem_close {};
-  gem_close.handle = gem_handle;
-  int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
-  if (ret)
-    ALOGE("Failed to close gem handle %d %d", gem_handle, ret);
-
-  return ret;
-}
-}  // namespace android
diff --git a/drm/DrmGenericImporter.h b/drm/DrmGenericImporter.h
deleted file mode 100644
index 27cfc3b..0000000
--- a/drm/DrmGenericImporter.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_PLATFORM_DRM_GENERIC_H_
-#define ANDROID_PLATFORM_DRM_GENERIC_H_
-
-#include <drm/drm_fourcc.h>
-#include <hardware/gralloc.h>
-
-#include <map>
-
-#include "drm/DrmDevice.h"
-#include "drmhwcgralloc.h"
-
-#ifndef DRM_FORMAT_INVALID
-#define DRM_FORMAT_INVALID 0
-#endif
-
-namespace android {
-
-class Importer {
- public:
-  virtual ~Importer() = default;
-
-  // Imports the buffer referred to by handle into bo.
-  //
-  // Note: This can be called from a different thread than ReleaseBuffer. The
-  //       implementation is responsible for ensuring thread safety.
-  virtual int ImportBuffer(hwc_drm_bo_t *bo) = 0;
-
-  // Releases the buffer object (ie: does the inverse of ImportBuffer)
-  //
-  // Note: This can be called from a different thread than ImportBuffer. The
-  //       implementation is responsible for ensuring thread safety.
-  virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0;
-};
-
-class DrmGenericImporter : public Importer {
- public:
-  DrmGenericImporter(DrmDevice *drm);
-  ~DrmGenericImporter() override = default;
-
-  int ImportBuffer(hwc_drm_bo_t *bo) override;
-  int ReleaseBuffer(hwc_drm_bo_t *bo) override;
-  int ImportHandle(uint32_t gem_handle);
-  int ReleaseHandle(uint32_t gem_handle);
-
- protected:
-  DrmDevice *drm_;
-
- private:
-  int CloseHandle(uint32_t gem_handle);
-  std::map<uint32_t, int> gem_refcount_;
-  bool has_modifier_support_;
-};
-
-}  // namespace android
-
-#endif
diff --git a/drm/DrmPlane.cpp b/drm/DrmPlane.cpp
index 5443e7e..6433fb6 100644
--- a/drm/DrmPlane.cpp
+++ b/drm/DrmPlane.cpp
@@ -231,7 +231,7 @@
     }
   }
 
-  uint32_t format = layer->buffer->format;
+  uint32_t format = layer->buffer_info.format;
   if (!IsFormatSupported(format)) {
     ALOGV("Plane %d does not supports %c%c%c%c format", id_, format,
           format >> 8, format >> 16, format >> 24);
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index f8e9cab..ef44180 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -74,20 +74,11 @@
                        (const hw_module_t **)&gralloc_);
 }
 
-int ResourceManager::AddDrmDevice(std::string const &path) {
-  std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>();
+int ResourceManager::AddDrmDevice(const std::string &path) {
+  auto drm = std::make_unique<DrmDevice>();
   int displays_added = 0;
   int ret = 0;
   std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_);
-  if (ret)
-    return ret;
-  std::shared_ptr<Importer> importer;
-  importer = std::make_shared<DrmGenericImporter>(drm.get());
-  if (!importer) {
-    ALOGE("Failed to create importer instance");
-    return -ENODEV;
-  }
-  importers_.push_back(importer);
   drms_.push_back(std::move(drm));
   num_displays_ += displays_added;
   return ret;
@@ -139,14 +130,6 @@
   return nullptr;
 }
 
-std::shared_ptr<Importer> ResourceManager::GetImporter(int display) {
-  for (unsigned int i = 0; i < drms_.size(); i++) {
-    if (drms_[i]->HandlesDisplay(display))
-      return importers_[i];
-  }
-  return nullptr;
-}
-
 const gralloc_module_t *ResourceManager::gralloc() {
   return gralloc_;
 }
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index fca6e1f..9b4155b 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -20,7 +20,7 @@
 #include <string.h>
 
 #include "DrmDevice.h"
-#include "DrmGenericImporter.h"
+#include "DrmFbImporter.h"
 
 namespace android {
 
@@ -31,7 +31,6 @@
   ResourceManager &operator=(const ResourceManager &) = delete;
   int Init();
   DrmDevice *GetDrmDevice(int display);
-  std::shared_ptr<Importer> GetImporter(int display);
   const gralloc_module_t *gralloc();
   DrmConnector *AvailableWritebackConnector(int display);
   const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const {
@@ -50,7 +49,6 @@
 
   int num_displays_;
   std::vector<std::unique_ptr<DrmDevice>> drms_;
-  std::vector<std::shared_ptr<Importer>> importers_;
   const gralloc_module_t *gralloc_;
 
   bool scale_with_gpu_{};
diff --git a/include/autofd.h b/include/autofd.h
deleted file mode 100644
index 9af6c22..0000000
--- a/include/autofd.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_AUTO_FD_H_
-#define ANDROID_AUTO_FD_H_
-
-#include <unistd.h>
-
-namespace android {
-
-class UniqueFd {
- public:
-  UniqueFd() = default;
-  UniqueFd(int fd) : fd_(fd) {
-  }
-  UniqueFd(UniqueFd &&rhs) {
-    fd_ = rhs.fd_;
-    rhs.fd_ = -1;
-  }
-
-  UniqueFd &operator=(UniqueFd &&rhs) {
-    Set(rhs.Release());
-    return *this;
-  }
-
-  ~UniqueFd() {
-    if (fd_ >= 0)
-      close(fd_);
-  }
-
-  int Release() {
-    int old_fd = fd_;
-    fd_ = -1;
-    return old_fd;
-  }
-
-  int Set(int fd) {
-    if (fd_ >= 0)
-      close(fd_);
-    fd_ = fd;
-    return fd_;
-  }
-
-  void Close() {
-    if (fd_ >= 0)
-      close(fd_);
-    fd_ = -1;
-  }
-
-  int get() const {
-    return fd_;
-  }
-
- private:
-  int fd_ = -1;
-};
-
-struct OutputFd {
-  OutputFd() = default;
-  OutputFd(int *fd) : fd_(fd) {
-  }
-  OutputFd(OutputFd &&rhs) {
-    fd_ = rhs.fd_;
-    rhs.fd_ = NULL;
-  }
-
-  OutputFd &operator=(OutputFd &&rhs) {
-    fd_ = rhs.fd_;
-    rhs.fd_ = NULL;
-    return *this;
-  }
-
-  int Set(int fd) {
-    if (*fd_ >= 0)
-      close(*fd_);
-    *fd_ = fd;
-    return fd;
-  }
-
-  int get() {
-    return *fd_;
-  }
-
-  operator bool() const {
-    return fd_ != NULL;
-  }
-
- private:
-  int *fd_ = NULL;
-};
-}  // namespace android
-
-#endif
diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h
index 05b2cf0..db54802 100644
--- a/include/drmhwcgralloc.h
+++ b/include/drmhwcgralloc.h
@@ -29,11 +29,8 @@
   uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
   uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
   uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
-  uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
   uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
-  uint32_t fb_id;
   int acquire_fence_fd;
-  void *priv;
 } hwc_drm_bo_t;
 
 #endif  // ANDROID_DRMHWCGRALLOC_H_
diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h
index a04cc29..22af12b 100644
--- a/include/drmhwcomposer.h
+++ b/include/drmhwcomposer.h
@@ -17,99 +17,20 @@
 #ifndef ANDROID_DRM_HWCOMPOSER_H_
 #define ANDROID_DRM_HWCOMPOSER_H_
 
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
 #include <stdbool.h>
 #include <stdint.h>
 
 #include <vector>
 
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
-#include "autofd.h"
+#include "drm/DrmFbImporter.h"
 #include "drmhwcgralloc.h"
-
-struct hwc_import_context;
-
-int hwc_import_init(struct hwc_import_context **ctx);
-int hwc_import_destroy(struct hwc_import_context *ctx);
-
-int hwc_import_bo_create(int fd, struct hwc_import_context *ctx,
-                         buffer_handle_t buf, struct hwc_drm_bo *bo);
-bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx,
-                           struct hwc_drm_bo *bo);
+#include "utils/UniqueFd.h"
 
 namespace android {
 
-class Importer;
-
-class DrmHwcBuffer {
- public:
-  DrmHwcBuffer() = default;
-  DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer)
-      : bo_(bo), importer_(importer) {
-  }
-  DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) {
-    rhs.importer_ = NULL;
-  }
-
-  ~DrmHwcBuffer() {
-    Clear();
-  }
-
-  DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) {
-    Clear();
-    importer_ = rhs.importer_;
-    rhs.importer_ = NULL;
-    bo_ = rhs.bo_;
-    return *this;
-  }
-
-  operator bool() const {
-    return importer_ != NULL;
-  }
-
-  const hwc_drm_bo *operator->() const;
-
-  void Clear();
-
-  int ImportBuffer(buffer_handle_t handle, Importer *importer);
-
- private:
-  hwc_drm_bo bo_;
-  Importer *importer_ = NULL;
-};
-
-class DrmHwcNativeHandle {
- public:
-  DrmHwcNativeHandle() = default;
-
-  DrmHwcNativeHandle(native_handle_t *handle) : handle_(handle) {
-  }
-
-  DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) {
-    handle_ = rhs.handle_;
-    rhs.handle_ = NULL;
-  }
-
-  ~DrmHwcNativeHandle();
-
-  DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) {
-    Clear();
-    handle_ = rhs.handle_;
-    rhs.handle_ = NULL;
-    return *this;
-  }
-
-  int CopyBufferHandle(buffer_handle_t handle);
-
-  void Clear();
-
-  buffer_handle_t get() const {
-    return handle_;
-  }
-
- private:
-  native_handle_t *handle_ = NULL;
-};
+class DrmFbIdHandle;
 
 enum DrmHwcTransform {
   kIdentity = 0,
@@ -128,9 +49,10 @@
 
 struct DrmHwcLayer {
   buffer_handle_t sf_handle = NULL;
+  hwc_drm_bo_t buffer_info{};
+  std::shared_ptr<DrmFbIdHandle> FbIdHandle;
+
   int gralloc_buffer_usage = 0;
-  DrmHwcBuffer buffer;
-  DrmHwcNativeHandle handle;
   uint32_t transform;
   DrmHwcBlending blending = DrmHwcBlending::kNone;
   uint16_t alpha = 0xffff;
@@ -139,17 +61,11 @@
   android_dataspace_t dataspace;
 
   UniqueFd acquire_fence;
-  OutputFd release_fence;
 
-  int ImportBuffer(Importer *importer);
-  int InitFromDrmHwcLayer(DrmHwcLayer *layer, Importer *importer);
+  int ImportBuffer(DrmDevice *drmDevice);
 
   void SetTransform(int32_t sf_transform);
 
-  buffer_handle_t get_usable_handle() const {
-    return handle.get() != NULL ? handle.get() : sf_handle;
-  }
-
   bool protected_usage() const {
     return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) ==
            GRALLOC_USAGE_PROTECTED;
diff --git a/utils/UniqueFd.h b/utils/UniqueFd.h
new file mode 100644
index 0000000..1a390ba
--- /dev/null
+++ b/utils/UniqueFd.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015, 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UNIQUEFD_H_
+#define UNIQUEFD_H_
+
+#include <unistd.h>
+
+#include <memory>
+
+namespace android {
+
+/*
+ * Using UniqueFd:
+ * 1. Create UniqueFd object:
+ *    auto fd_obj = UniqueFd(open("SomeFile", xxx));
+ *
+ * 2. Check whether the fd_obj is empty:
+ *    if (!fd_obj) { return -errno; }
+ *
+ * 3. Accessing the file descriptor:
+ *    int ret = read(fd_obj.Get(), buf, buf_size);
+ *
+ * 4. Closing the file:
+ *    FD will be closed once execution leaves fd_obj scope (on any return,
+ *    exception, destruction of class/struct where object is member, etc.).
+ *    User can also force closing the fd_obj by calling:
+ *      fd_obj = UniqueFd();
+ *      // fd is closed and fd_obj is empty now.
+ *
+ * 5. File descriptor may be transferred to the code, which will close it after
+ *    using. This can be done in 2 ways:
+ *    a. Duplicate the fd, in this case both fds should be closed separately:
+ *      int out_fd = dup(fd_obj.Get();
+ *      ...
+ *      close(out_fd);
+ *    b. Transfer ownership, use this method if you do not need the fd anymore.
+ *      int out_fd = fd_obj.Release();
+ *      // fd_obj is empty now.
+ *      ...
+ *      close(out_fd);
+ *
+ * 6. Transferring fd into another UniqueFD object:
+ *    UniqueFd fd_obj_2 = std::move(fd_obj);
+ *    // fd_obj empty now
+ */
+
+constexpr int kEmptyFd = -1;
+
+class UniqueFd {
+ public:
+  UniqueFd() = default;
+  explicit UniqueFd(int fd) : fd_(fd){};
+
+  auto Release [[nodiscard]] () -> int {
+    return std::exchange(fd_, kEmptyFd);
+  }
+
+  auto Get [[nodiscard]] () const -> int {
+    return fd_;
+  }
+
+  explicit operator bool() const {
+    return fd_ != kEmptyFd;
+  }
+
+  ~UniqueFd() {
+    Set(kEmptyFd);
+  }
+
+  /* Allow move semantics */
+  UniqueFd(UniqueFd &&rhs) noexcept {
+    Set(rhs.Release());
+  }
+
+  auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & {
+    Set(rhs.Release());
+    return *this;
+  }
+
+  /* Disable copy semantics */
+  UniqueFd(const UniqueFd &) = delete;
+  auto operator=(const UniqueFd &) = delete;
+
+ private:
+  void Set(int new_fd) {
+    if (fd_ != kEmptyFd) {
+      close(fd_);
+    }
+    fd_ = new_fd;
+  }
+
+  int fd_ = kEmptyFd;
+};
+
+}  // namespace android
+
+#endif
diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp
index 81097ce..6de6500 100644
--- a/utils/hwcutils.cpp
+++ b/utils/hwcutils.cpp
@@ -22,118 +22,32 @@
 #include <ui/GraphicBufferMapper.h>
 
 #include "bufferinfo/BufferInfoGetter.h"
-#include "drm/DrmGenericImporter.h"
+#include "drm/DrmFbImporter.h"
 #include "drmhwcomposer.h"
 
 #define UNUSED(x) (void)(x)
 
 namespace android {
 
-const hwc_drm_bo *DrmHwcBuffer::operator->() const {
-  if (importer_ == nullptr) {
-    ALOGE("Access of non-existent BO");
-    exit(1);
-    return nullptr;
-  }
-  return &bo_;
-}
+int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) {
+  buffer_info = hwc_drm_bo_t{};
 
-void DrmHwcBuffer::Clear() {
-  if (importer_ != nullptr) {
-    importer_->ReleaseBuffer(&bo_);
-    importer_ = nullptr;
-  }
-}
-
-int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
-  hwc_drm_bo tmp_bo{};
-
-  int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo);
+  int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(sf_handle,
+                                                           &buffer_info);
   if (ret) {
     ALOGE("Failed to convert buffer info %d", ret);
     return ret;
   }
 
-  ret = importer->ImportBuffer(&tmp_bo);
-  if (ret) {
-    ALOGE("Failed to import buffer %d", ret);
-    return ret;
+  FbIdHandle = drmDevice->GetDrmFbImporter().GetOrCreateFbId(&buffer_info);
+  if (!FbIdHandle) {
+    ALOGE("Failed to import buffer");
+    return -EINVAL;
   }
 
-  if (importer_ != nullptr) {
-    importer_->ReleaseBuffer(&bo_);
-  }
-
-  importer_ = importer;
-
-  bo_ = tmp_bo;
-
   return 0;
 }
 
-int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle) {
-  native_handle_t *handle_copy = nullptr;
-  GraphicBufferMapper &gm(GraphicBufferMapper::get());
-  int ret = 0;
-
-  ret = gm.getGrallocMapper().importBuffer(handle,
-                                           (buffer_handle_t *)&handle_copy);
-
-  if (ret) {
-    ALOGE("Failed to import buffer handle %d", ret);
-    return ret;
-  }
-
-  Clear();
-
-  handle_ = handle_copy;
-
-  return 0;
-}
-
-DrmHwcNativeHandle::~DrmHwcNativeHandle() {
-  Clear();
-}
-
-void DrmHwcNativeHandle::Clear() {
-  if (handle_ != nullptr) {
-    GraphicBufferMapper &gm(GraphicBufferMapper::get());
-    int ret = gm.freeBuffer(handle_);
-    if (ret) {
-      ALOGE("Failed to free buffer handle %d", ret);
-    }
-    handle_ = nullptr;
-  }
-}
-
-int DrmHwcLayer::ImportBuffer(Importer *importer) {
-  int ret = buffer.ImportBuffer(sf_handle, importer);
-  if (ret)
-    return ret;
-
-  const hwc_drm_bo *bo = buffer.operator->();
-
-  ret = handle.CopyBufferHandle(sf_handle);
-  if (ret)
-    return ret;
-
-  gralloc_buffer_usage = bo->usage;
-
-  return 0;
-}
-
-int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer,
-                                     Importer *importer) {
-  blending = src_layer->blending;
-  sf_handle = src_layer->sf_handle;
-  acquire_fence = -1;
-  display_frame = src_layer->display_frame;
-  alpha = src_layer->alpha;
-  source_crop = src_layer->source_crop;
-  transform = src_layer->transform;
-  return ImportBuffer(importer);
-}
-
 void DrmHwcLayer::SetTransform(int32_t sf_transform) {
   transform = 0;
   // 270* and 180* cannot be combined with flips. More specifically, they