Snap for 7570015 from f38e2635ad1c83e03e8c305e44c7a3c7f1e31329 to mainline-sdkext-release

Change-Id: Ided51c2a1081d3ddcfc74f2caa38098cfda7f060
diff --git a/Android.bp b/Android.bp
index 85be0b5..7bb2bd6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,12 +15,32 @@
 // =====================
 // libdrmhwc_utils.a
 // =====================
+package {
+    default_applicable_licenses: ["external_drm_hwcomposer_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "external_drm_hwcomposer_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_library_static {
     name: "libdrmhwc_utils",
 
-    srcs: ["utils/worker.cpp"],
+    srcs: ["utils/Worker.cpp"],
 
-    include_dirs: ["external/drm_hwcomposer/include"],
+    include_dirs: [
+        "external/drm_hwcomposer/include",
+        "external/drm_hwcomposer",
+    ],
 
     cflags: [
         "-Wall",
@@ -41,13 +61,17 @@
         "libcutils",
         "libdrm",
         "libhardware",
+        "libhidlbase",
         "liblog",
         "libsync",
         "libui",
         "libutils",
     ],
 
-    include_dirs: ["external/drm_hwcomposer/include"],
+    include_dirs: [
+        "external/drm_hwcomposer/include",
+        "external/drm_hwcomposer",
+    ],
 
     static_libs: ["libdrmhwc_utils"],
 
@@ -61,6 +85,12 @@
         "-DHWC2_INCLUDE_STRINGIFICATION",
     ],
 
+    product_variables: {
+        platform_sdk_version: {
+            cflags: ["-DPLATFORM_SDK_VERSION=%d"],
+        },
+    },
+
     relative_install_path: "hw",
     vendor: true,
 }
@@ -68,26 +98,34 @@
     name: "drm_hwcomposer",
     defaults: ["hwcomposer.drm_defaults"],
     srcs: [
-        "drmhwctwo.cpp",
+        "DrmHwcTwo.cpp",
 
-        "compositor/drmdisplaycomposition.cpp",
-        "compositor/drmdisplaycompositor.cpp",
+        "bufferinfo/BufferInfoGetter.cpp",
+        "bufferinfo/BufferInfoMapperMetadata.cpp",
 
-        "drm/drmconnector.cpp",
-        "drm/drmcrtc.cpp",
-        "drm/drmdevice.cpp",
-        "drm/drmencoder.cpp",
-        "drm/drmeventlistener.cpp",
-        "drm/drmmode.cpp",
-        "drm/drmplane.cpp",
-        "drm/drmproperty.cpp",
-        "drm/resourcemanager.cpp",
-        "drm/vsyncworker.cpp",
+        "compositor/DrmDisplayComposition.cpp",
+        "compositor/DrmDisplayCompositor.cpp",
+        "compositor/Planner.cpp",
 
-        "platform/platform.cpp",
+        "drm/DrmConnector.cpp",
+        "drm/DrmCrtc.cpp",
+        "drm/DrmDevice.cpp",
+        "drm/DrmEncoder.cpp",
+        "drm/DrmEventListener.cpp",
+        "drm/DrmGenericImporter.cpp",
+        "drm/DrmMode.cpp",
+        "drm/DrmPlane.cpp",
+        "drm/DrmProperty.cpp",
+        "drm/ResourceManager.cpp",
+        "drm/VSyncWorker.cpp",
 
         "utils/autolock.cpp",
         "utils/hwcutils.cpp",
+
+        "backend/BackendManager.cpp",
+        "backend/Backend.cpp",
+        "backend/BackendClient.cpp",
+        "backend/BackendRCarDu.cpp",
     ],
 }
 
@@ -95,44 +133,37 @@
     name: "hwcomposer.drm",
     defaults: ["hwcomposer.drm_defaults"],
     whole_static_libs: ["drm_hwcomposer"],
-    srcs: ["platform/platformdrmgeneric.cpp"],
-    cppflags: ["-DUSE_DRM_GENERIC_IMPORTER"],
+    srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"],
 }
 
 cc_library_shared {
     name: "hwcomposer.drm_minigbm",
     defaults: ["hwcomposer.drm_defaults"],
     whole_static_libs: ["drm_hwcomposer"],
-    srcs: [
-        "platform/platformdrmgeneric.cpp",
-        "platform/platformminigbm.cpp",
-    ],
+    srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"],
     include_dirs: ["external/minigbm/cros_gralloc"],
 }
 
 // Used by hwcomposer.drm_imagination
 filegroup {
     name: "drm_hwcomposer_platformimagination",
-    srcs: [
-        "platform/platformdrmgeneric.cpp",
-        "platform/platformimagination.cpp",
-    ],
+    srcs: ["bufferinfo/legacy/BufferInfoImagination.cpp"],
 }
 
 // Used by hwcomposer.drm_hikey and hwcomposer.drm_hikey960
 filegroup {
     name: "drm_hwcomposer_platformhisi",
-    srcs: [
-        "platform/platformdrmgeneric.cpp",
-        "platform/platformhisi.cpp",
-    ],
+    srcs: ["bufferinfo/legacy/BufferInfoMaliHisi.cpp"],
 }
 
 // Used by hwcomposer.drm_meson
 filegroup {
     name: "drm_hwcomposer_platformmeson",
-    srcs: [
-        "platform/platformdrmgeneric.cpp",
-        "platform/platformmeson.cpp",
-    ],
+    srcs: ["bufferinfo/legacy/BufferInfoMaliMeson.cpp"],
+}
+
+// Used by hwcomposer.drm_mediatek
+filegroup {
+    name: "drm_hwcomposer_platformmediatek",
+    srcs: ["bufferinfo/legacy/BufferInfoMaliMediatek.cpp"],
 }
diff --git a/drmhwctwo.cpp b/DrmHwcTwo.cpp
similarity index 88%
rename from drmhwctwo.cpp
rename to DrmHwcTwo.cpp
index ab39144..93b6fa7 100644
--- a/drmhwctwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -17,38 +17,22 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #define LOG_TAG "hwc-drm-two"
 
-#include "drmhwctwo.h"
-#include "drmdisplaycomposition.h"
-#include "drmhwcomposer.h"
-#include "platform.h"
-#include "vsyncworker.h"
-
-#include <inttypes.h>
-#include <string>
+#include "DrmHwcTwo.h"
 
 #include <cutils/properties.h>
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer2.h>
+#include <inttypes.h>
 #include <log/log.h>
 
+#include <string>
+
+#include "backend/BackendManager.h"
+#include "bufferinfo/BufferInfoGetter.h"
+#include "compositor/DrmDisplayComposition.h"
+
 namespace android {
 
-class DrmVsyncCallback : public VsyncCallback {
- public:
-  DrmVsyncCallback(hwc2_callback_data_t data, hwc2_function_pointer_t hook)
-      : data_(data), hook_(hook) {
-  }
-
-  void Callback(int display, int64_t timestamp) {
-    auto hook = reinterpret_cast<HWC2_PFN_VSYNC>(hook_);
-    hook(data_, display, timestamp);
-  }
-
- private:
-  hwc2_callback_data_t data_;
-  hwc2_function_pointer_t hook_;
-};
-
 DrmHwcTwo::DrmHwcTwo() {
   common.tag = HARDWARE_DEVICE_TAG;
   common.version = HWC_DEVICE_API_VERSION_2_0;
@@ -142,6 +126,7 @@
           << ((delta.failed_kms_present_ > 0)
                   ? " !!! Internal failure, FIX it please\n"
                   : "")
+          << " Flattened frames: " << delta.frames_flattened_ << "\n"
           << " Pixel operations (free units)"
           << " : [TOTAL: " << delta.total_pixops_
           << " / GPU: " << delta.gpu_pixops_ << "]\n"
@@ -152,6 +137,8 @@
 std::string DrmHwcTwo::HwcDisplay::Dump() {
   auto out = (std::stringstream()
               << "- Display on: " << connector_->name() << "\n"
+              << "  Flattening state: " << compositor_.GetFlatteningState()
+              << "\n"
               << "Statistics since system boot:\n"
               << DumpDelta(total_stats_) << "\n\n"
               << "Statistics since last dumpsys request:\n"
@@ -192,22 +179,21 @@
                                         hwc2_callback_data_t data,
                                         hwc2_function_pointer_t function) {
   supported(__func__);
-  auto callback = static_cast<HWC2::Callback>(descriptor);
 
-  if (!function) {
-    callbacks_.erase(callback);
-    return HWC2::Error::None;
-  }
-
-  callbacks_.emplace(callback, HwcCallback(data, function));
-
-  switch (callback) {
+  switch (static_cast<HWC2::Callback>(descriptor)) {
     case HWC2::Callback::Hotplug: {
+      SetHotplugCallback(data, function);
       auto &drmDevices = resource_manager_.getDrmDevices();
       for (auto &device : drmDevices)
         HandleInitialHotplugState(device.get());
       break;
     }
+    case HWC2::Callback::Refresh: {
+      for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
+           displays_)
+        d.second.RegisterRefreshCallback(data, function);
+      break;
+    }
     case HWC2::Callback::Vsync: {
       for (std::pair<const hwc2_display_t, DrmHwcTwo::HwcDisplay> &d :
            displays_)
@@ -262,7 +248,8 @@
   // Split up the given display planes into primary and overlay to properly
   // interface with the composition
   char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
-  property_get("hwc.drm.use_overlay_planes", use_overlay_planes_prop, "1");
+  property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
+               "1");
   bool use_overlay_planes = atoi(use_overlay_planes_prop);
   for (auto &plane : *planes) {
     if (plane->type() == DRM_PLANE_TYPE_PRIMARY)
@@ -289,6 +276,12 @@
     return HWC2::Error::BadDisplay;
   }
 
+  ret = BackendManager::GetInstance().SetBackendForDisplay(this);
+  if (ret) {
+    ALOGE("Failed to set backend for d=%d %d\n", display, ret);
+    return HWC2::Error::BadDisplay;
+  }
+
   return ChosePreferredConfig();
 }
 
@@ -302,12 +295,16 @@
   return SetActiveConfig(connector_->get_preferred_mode_id());
 }
 
-HWC2::Error DrmHwcTwo::HwcDisplay::RegisterVsyncCallback(
+void DrmHwcTwo::HwcDisplay::RegisterVsyncCallback(
     hwc2_callback_data_t data, hwc2_function_pointer_t func) {
   supported(__func__);
-  auto callback = std::make_shared<DrmVsyncCallback>(data, func);
-  vsync_worker_.RegisterCallback(std::move(callback));
-  return HWC2::Error::None;
+  vsync_worker_.RegisterClientCallback(data, func);
+}
+
+void DrmHwcTwo::HwcDisplay::RegisterRefreshCallback(
+    hwc2_callback_data_t data, hwc2_function_pointer_t func) {
+  supported(__func__);
+  compositor_.SetRefreshCallback(data, func);
 }
 
 HWC2::Error DrmHwcTwo::HwcDisplay::AcceptDisplayChanges() {
@@ -761,11 +758,6 @@
                               .right = static_cast<int>(mode->h_display()),
                               .bottom = static_cast<int>(mode->v_display())};
   client_layer_.SetLayerDisplayFrame(display_frame);
-  hwc_frect_t source_crop = {.left = 0.0f,
-                             .top = 0.0f,
-                             .right = mode->h_display() + 0.0f,
-                             .bottom = mode->v_display() + 0.0f};
-  client_layer_.SetLayerSourceCrop(source_crop);
 
   return HWC2::Error::None;
 }
@@ -780,15 +772,30 @@
   client_layer_.set_buffer(target);
   client_layer_.set_acquire_fence(uf.get());
   client_layer_.SetLayerDataspace(dataspace);
+
+  /* TODO: Do not update source_crop every call.
+   * It makes sense to do it once after every hotplug event. */
+  hwc_drm_bo bo{};
+  BufferInfoGetter::GetInstance()->ConvertBoInfo(target, &bo);
+
+  hwc_frect_t source_crop = {.left = 0.0f,
+                             .top = 0.0f,
+                             .right = bo.width + 0.0f,
+                             .bottom = bo.height + 0.0f};
+  client_layer_.SetLayerSourceCrop(source_crop);
+
   return HWC2::Error::None;
 }
 
 HWC2::Error DrmHwcTwo::HwcDisplay::SetColorMode(int32_t mode) {
   supported(__func__);
 
-  if (mode != HAL_COLOR_MODE_NATIVE)
+  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
     return HWC2::Error::BadParameter;
 
+  if (mode != HAL_COLOR_MODE_NATIVE)
+    return HWC2::Error::Unsupported;
+
   color_mode_ = mode;
   return HWC2::Error::None;
 }
@@ -881,78 +888,98 @@
 HWC2::Error DrmHwcTwo::HwcDisplay::ValidateDisplay(uint32_t *num_types,
                                                    uint32_t *num_requests) {
   supported(__func__);
-  *num_types = 0;
-  *num_requests = 0;
-  size_t avail_planes = primary_planes_.size() + overlay_planes_.size();
 
-  /*
-   * If more layers then planes, save one plane
-   * for client composited layers
-   */
-  if (avail_planes < layers_.size())
-    avail_planes--;
-
-  std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map;
-  for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l : layers_)
-    z_map.emplace(std::make_pair(l.second.z_order(), &l.second));
-
-  uint32_t total_pixops = CalcPixOps(z_map, 0, z_map.size()), gpu_pixops = 0;
-
-  int client_start = -1, client_size = 0;
-
-  for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
-    if (!HardwareSupportsLayerType(l.second->sf_type()) ||
-        !importer_->CanImportBuffer(l.second->buffer()) ||
-        color_transform_hint_ != HAL_COLOR_TRANSFORM_IDENTITY) {
-      if (client_start < 0)
-        client_start = l.first;
-      client_size = (l.first - client_start) + 1;
-    }
-  }
-
-  int extra_client = (z_map.size() - client_size) - avail_planes;
-  if (extra_client > 0) {
-    int start = 0, steps;
-    if (client_size != 0) {
-      int prepend = std::min(client_start, extra_client);
-      int append = std::min(int(z_map.size() - (client_start + client_size)),
-                            extra_client);
-      start = client_start - prepend;
-      client_size += extra_client;
-      steps = 1 + std::min(std::min(append, prepend),
-                           int(z_map.size()) - (start + client_size));
-    } else {
-      client_size = extra_client;
-      steps = 1 + z_map.size() - extra_client;
-    }
-
-    gpu_pixops = INT_MAX;
-    for (int i = 0; i < steps; i++) {
-      uint32_t po = CalcPixOps(z_map, start + i, client_size);
-      if (po < gpu_pixops) {
-        gpu_pixops = po;
-        client_start = start + i;
-      }
-    }
-  }
-
-  MarkValidated(z_map, client_start, client_size);
-
-  if (CreateComposition(true) != HWC2::Error::None) {
-    ++total_stats_.failed_kms_validate_;
-    gpu_pixops = total_pixops;
-    client_size = z_map.size();
-    MarkValidated(z_map, 0, client_size);
-  }
-
-  *num_types = client_size;
-
-  total_stats_.gpu_pixops_ += gpu_pixops;
-  total_stats_.total_pixops_ += total_pixops;
-
-  return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
+  return backend_->ValidateDisplay(this, num_types, num_requests);
 }
 
+#if PLATFORM_SDK_VERSION > 28
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayIdentificationData(
+    uint8_t *outPort, uint32_t *outDataSize, uint8_t *outData) {
+  supported(__func__);
+
+  drmModePropertyBlobPtr blob;
+
+  if (connector_->GetEdidBlob(blob)) {
+    ALOGE("Failed to get edid property value.");
+    return HWC2::Error::Unsupported;
+  }
+
+  if (outData) {
+    *outDataSize = std::min(*outDataSize, blob->length);
+    memcpy(outData, blob->data, *outDataSize);
+  } else {
+    *outDataSize = blob->length;
+  }
+  *outPort = connector_->id();
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayCapabilities(
+    uint32_t *outNumCapabilities, uint32_t *outCapabilities) {
+  unsupported(__func__, outCapabilities);
+
+  if (outNumCapabilities == NULL) {
+    return HWC2::Error::BadParameter;
+  }
+
+  *outNumCapabilities = 0;
+
+  return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::GetDisplayBrightnessSupport(
+    bool *supported) {
+  *supported = false;
+  return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::SetDisplayBrightness(
+    float /* brightness */) {
+  return HWC2::Error::Unsupported;
+}
+
+#endif /* PLATFORM_SDK_VERSION > 28 */
+
+#if PLATFORM_SDK_VERSION > 27
+
+HWC2::Error DrmHwcTwo::HwcDisplay::GetRenderIntents(
+    int32_t mode, uint32_t *outNumIntents,
+    int32_t * /*android_render_intent_v1_1_t*/ outIntents) {
+  if (mode != HAL_COLOR_MODE_NATIVE) {
+    return HWC2::Error::BadParameter;
+  }
+
+  if (outIntents == nullptr) {
+    *outNumIntents = 1;
+    return HWC2::Error::None;
+  }
+  *outNumIntents = 1;
+  outIntents[0] = HAL_RENDER_INTENT_COLORIMETRIC;
+  return HWC2::Error::None;
+}
+
+HWC2::Error DrmHwcTwo::HwcDisplay::SetColorModeWithIntent(int32_t mode,
+                                                          int32_t intent) {
+  if (intent < HAL_RENDER_INTENT_COLORIMETRIC ||
+      intent > HAL_RENDER_INTENT_TONE_MAP_ENHANCE)
+    return HWC2::Error::BadParameter;
+
+  if (mode < HAL_COLOR_MODE_NATIVE || mode > HAL_COLOR_MODE_BT2100_HLG)
+    return HWC2::Error::BadParameter;
+
+  if (mode != HAL_COLOR_MODE_NATIVE)
+    return HWC2::Error::Unsupported;
+
+  if (intent != HAL_RENDER_INTENT_COLORIMETRIC)
+    return HWC2::Error::Unsupported;
+
+  color_mode_ = mode;
+  return HWC2::Error::None;
+}
+
+#endif /* PLATFORM_SDK_VERSION > 27 */
+
 HWC2::Error DrmHwcTwo::HwcLayer::SetCursorPosition(int32_t x, int32_t y) {
   supported(__func__);
   cursor_x_ = x;
@@ -971,12 +998,6 @@
   supported(__func__);
   UniqueFd uf(acquire_fence);
 
-  // The buffer and acquire_fence are handled elsewhere
-  if (sf_type_ == HWC2::Composition::Client ||
-      sf_type_ == HWC2::Composition::Sideband ||
-      sf_type_ == HWC2::Composition::SolidColor)
-    return HWC2::Error::None;
-
   set_buffer(buffer);
   set_acquire_fence(uf.get());
   return HWC2::Error::None;
@@ -1081,14 +1102,13 @@
 }
 
 void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) {
-  auto cb = callbacks_.find(HWC2::Callback::Hotplug);
-  if (cb == callbacks_.end())
-    return;
+  const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
 
-  auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(cb->second.func);
-  hotplug(cb->second.data, displayid,
-          (state == DRM_MODE_CONNECTED ? HWC2_CONNECTION_CONNECTED
-                                       : HWC2_CONNECTION_DISCONNECTED));
+  if (hotplug_callback_hook_ && hotplug_callback_data_)
+    hotplug_callback_hook_(hotplug_callback_data_, displayid,
+                           state == DRM_MODE_CONNECTED
+                               ? HWC2_CONNECTION_CONNECTED
+                               : HWC2_CONNECTION_DISCONNECTED);
 }
 
 void DrmHwcTwo::HandleInitialHotplugState(DrmDevice *drmDevice) {
@@ -1275,7 +1295,37 @@
       return ToHook<HWC2_PFN_VALIDATE_DISPLAY>(
           DisplayHook<decltype(&HwcDisplay::ValidateDisplay),
                       &HwcDisplay::ValidateDisplay, uint32_t *, uint32_t *>);
-
+#if PLATFORM_SDK_VERSION > 27
+    case HWC2::FunctionDescriptor::GetRenderIntents:
+      return ToHook<HWC2_PFN_GET_RENDER_INTENTS>(
+          DisplayHook<decltype(&HwcDisplay::GetRenderIntents),
+                      &HwcDisplay::GetRenderIntents, int32_t, uint32_t *,
+                      int32_t *>);
+    case HWC2::FunctionDescriptor::SetColorModeWithRenderIntent:
+      return ToHook<HWC2_PFN_SET_COLOR_MODE_WITH_RENDER_INTENT>(
+          DisplayHook<decltype(&HwcDisplay::SetColorModeWithIntent),
+                      &HwcDisplay::SetColorModeWithIntent, int32_t, int32_t>);
+#endif
+#if PLATFORM_SDK_VERSION > 28
+    case HWC2::FunctionDescriptor::GetDisplayIdentificationData:
+      return ToHook<HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA>(
+          DisplayHook<decltype(&HwcDisplay::GetDisplayIdentificationData),
+                      &HwcDisplay::GetDisplayIdentificationData, uint8_t *,
+                      uint32_t *, uint8_t *>);
+    case HWC2::FunctionDescriptor::GetDisplayCapabilities:
+      return ToHook<HWC2_PFN_GET_DISPLAY_CAPABILITIES>(
+          DisplayHook<decltype(&HwcDisplay::GetDisplayCapabilities),
+                      &HwcDisplay::GetDisplayCapabilities, uint32_t *,
+                      uint32_t *>);
+    case HWC2::FunctionDescriptor::GetDisplayBrightnessSupport:
+      return ToHook<HWC2_PFN_GET_DISPLAY_BRIGHTNESS_SUPPORT>(
+          DisplayHook<decltype(&HwcDisplay::GetDisplayBrightnessSupport),
+                      &HwcDisplay::GetDisplayBrightnessSupport, bool *>);
+    case HWC2::FunctionDescriptor::SetDisplayBrightness:
+      return ToHook<HWC2_PFN_SET_DISPLAY_BRIGHTNESS>(
+          DisplayHook<decltype(&HwcDisplay::SetDisplayBrightness),
+                      &HwcDisplay::SetDisplayBrightness, float>);
+#endif /* PLATFORM_SDK_VERSION > 28 */
     // Layer functions
     case HWC2::FunctionDescriptor::SetCursorPosition:
       return ToHook<HWC2_PFN_SET_CURSOR_POSITION>(
diff --git a/include/drmhwctwo.h b/DrmHwcTwo.h
similarity index 75%
rename from include/drmhwctwo.h
rename to DrmHwcTwo.h
index babe000..d489113 100644
--- a/include/drmhwctwo.h
+++ b/DrmHwcTwo.h
@@ -14,19 +14,26 @@
  * limitations under the License.
  */
 
-#include "drmdisplaycompositor.h"
-#include "drmhwcomposer.h"
-#include "platform.h"
-#include "resourcemanager.h"
-#include "vsyncworker.h"
+#ifndef ANDROID_DRM_HWC_TWO_H_
+#define ANDROID_DRM_HWC_TWO_H_
 
 #include <hardware/hwcomposer2.h>
+#include <math.h>
 
 #include <array>
 #include <map>
 
+#include "compositor/DrmDisplayCompositor.h"
+#include "compositor/Planner.h"
+#include "drm/DrmGenericImporter.h"
+#include "drm/ResourceManager.h"
+#include "drm/VSyncWorker.h"
+#include "drmhwcomposer.h"
+
 namespace android {
 
+class Backend;
+
 class DrmHwcTwo : public hwc2_device_t {
  public:
   static int HookDevOpen(const struct hw_module_t *module, const char *name,
@@ -36,7 +43,17 @@
 
   HWC2::Error Init();
 
- private:
+  hwc2_callback_data_t hotplug_callback_data_ = NULL;
+  HWC2_PFN_HOTPLUG hotplug_callback_hook_ = NULL;
+  std::mutex hotplug_callback_lock;
+
+  void SetHotplugCallback(hwc2_callback_data_t data,
+                          hwc2_function_pointer_t hook) {
+    const std::lock_guard<std::mutex> lock(hotplug_callback_lock);
+    hotplug_callback_data_ = data;
+    hotplug_callback_hook_ = reinterpret_cast<HWC2_PFN_HOTPLUG>(hook);
+  }
+
   class HwcLayer {
    public:
     HWC2::Composition sf_type() const {
@@ -93,6 +110,19 @@
 
     void PopulateDrmLayer(DrmHwcLayer *layer);
 
+    bool RequireScalingOrPhasing() {
+      float src_width = source_crop_.right - source_crop_.left;
+      float src_height = source_crop_.bottom - source_crop_.top;
+
+      float dest_width = display_frame_.right - display_frame_.left;
+      float dest_height = display_frame_.bottom - display_frame_.top;
+
+      bool scaling = src_width != dest_width || src_height != dest_height;
+      bool phasing = (source_crop_.left - floor(source_crop_.left) != 0) ||
+                     (source_crop_.top - floor(source_crop_.top) != 0);
+      return scaling || phasing;
+    }
+
     // Layer hooks
     HWC2::Error SetCursorPosition(int32_t x, int32_t y);
     HWC2::Error SetLayerBlendMode(int32_t mode);
@@ -131,14 +161,6 @@
     android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN;
   };
 
-  struct HwcCallback {
-    HwcCallback(hwc2_callback_data_t d, hwc2_function_pointer_t f)
-        : data(d), func(f) {
-    }
-    hwc2_callback_data_t data;
-    hwc2_function_pointer_t func;
-  };
-
   class HwcDisplay {
    public:
     HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
@@ -147,8 +169,17 @@
     HwcDisplay(const HwcDisplay &) = delete;
     HWC2::Error Init(std::vector<DrmPlane *> *planes);
 
-    HWC2::Error RegisterVsyncCallback(hwc2_callback_data_t data,
-                                      hwc2_function_pointer_t func);
+    void RegisterVsyncCallback(hwc2_callback_data_t data,
+                               hwc2_function_pointer_t func);
+    void RegisterRefreshCallback(hwc2_callback_data_t data,
+                                 hwc2_function_pointer_t func);
+    HWC2::Error CreateComposition(bool test);
+    bool HardwareSupportsLayerType(HWC2::Composition comp_type);
+    uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
+                        size_t first_z, size_t size);
+    void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
+                       size_t client_first_z, size_t client_size);
+
     void ClearDisplay();
 
     std::string Dump();
@@ -173,6 +204,20 @@
                                    uint32_t *num_elements, hwc2_layer_t *layers,
                                    int32_t *layer_requests);
     HWC2::Error GetDisplayType(int32_t *type);
+#if PLATFORM_SDK_VERSION > 27
+    HWC2::Error GetRenderIntents(int32_t mode, uint32_t *outNumIntents,
+                                 int32_t *outIntents);
+    HWC2::Error SetColorModeWithIntent(int32_t mode, int32_t intent);
+#endif
+#if PLATFORM_SDK_VERSION > 28
+    HWC2::Error GetDisplayIdentificationData(uint8_t *outPort,
+                                             uint32_t *outDataSize,
+                                             uint8_t *outData);
+    HWC2::Error GetDisplayCapabilities(uint32_t *outNumCapabilities,
+                                       uint32_t *outCapabilities);
+    HWC2::Error GetDisplayBrightnessSupport(bool *supported);
+    HWC2::Error SetDisplayBrightness(float);
+#endif
     HWC2::Error GetDozeSupport(int32_t *support);
     HWC2::Error GetHdrCapabilities(uint32_t *num_types, int32_t *types,
                                    float *max_luminance,
@@ -198,14 +243,74 @@
       return &it->second;
     }
 
+    /* Statistics */
+    struct Stats {
+      Stats minus(Stats b) {
+        return {total_frames_ - b.total_frames_,
+                total_pixops_ - b.total_pixops_,
+                gpu_pixops_ - b.gpu_pixops_,
+                failed_kms_validate_ - b.failed_kms_validate_,
+                failed_kms_present_ - b.failed_kms_present_,
+                frames_flattened_ - b.frames_flattened_};
+      }
+
+      uint32_t total_frames_ = 0;
+      uint64_t total_pixops_ = 0;
+      uint64_t gpu_pixops_ = 0;
+      uint32_t failed_kms_validate_ = 0;
+      uint32_t failed_kms_present_ = 0;
+      uint32_t frames_flattened_ = 0;
+    };
+
+    const Backend *backend() const {
+      return backend_.get();
+    }
+    void set_backend(std::unique_ptr<Backend> backend) {
+      backend_ = std::move(backend);
+    }
+
+    const std::vector<DrmPlane *> &primary_planes() const {
+      return primary_planes_;
+    }
+
+    const std::vector<DrmPlane *> &overlay_planes() const {
+      return overlay_planes_;
+    }
+
+    std::map<hwc2_layer_t, HwcLayer> &layers() {
+      return layers_;
+    }
+
+    const DrmDisplayCompositor &compositor() const {
+      return compositor_;
+    }
+
+    const DrmDevice *drm() const {
+      return drm_;
+    }
+
+    const DrmConnector *connector() const {
+      return connector_;
+    }
+
+    const std::shared_ptr<Importer> &importer() const {
+      return importer_;
+    }
+
+    ResourceManager *resource_manager() const {
+      return resource_manager_;
+    }
+
+    android_color_transform_t &color_transform_hint() {
+      return color_transform_hint_;
+    }
+
+    Stats &total_stats() {
+      return total_stats_;
+    }
+
    private:
-    HWC2::Error CreateComposition(bool test);
     void AddFenceToPresentFence(int fd);
-    bool HardwareSupportsLayerType(HWC2::Composition comp_type);
-    uint32_t CalcPixOps(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
-                        size_t first_z, size_t size);
-    void MarkValidated(std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map,
-                       size_t client_first_z, size_t client_size);
 
     constexpr static size_t MATRIX_SIZE = 16;
 
@@ -218,6 +323,8 @@
     std::vector<DrmPlane *> primary_planes_;
     std::vector<DrmPlane *> overlay_planes_;
 
+    std::unique_ptr<Backend> backend_;
+
     VSyncWorker vsync_worker_;
     DrmConnector *connector_ = NULL;
     DrmCrtc *crtc_ = NULL;
@@ -232,21 +339,8 @@
     android_color_transform_t color_transform_hint_;
 
     uint32_t frame_no_ = 0;
-    /* Statistics */
-    struct Stats {
-      Stats minus(Stats b) {
-        return {total_frames_ - b.total_frames_,
-                total_pixops_ - b.total_pixops_, gpu_pixops_ - b.gpu_pixops_,
-                failed_kms_validate_ - b.failed_kms_validate_,
-                failed_kms_present_ - b.failed_kms_present_};
-      }
-
-      uint32_t total_frames_ = 0;
-      uint64_t total_pixops_ = 0;
-      uint64_t gpu_pixops_ = 0;
-      uint32_t failed_kms_validate_ = 0;
-      uint32_t failed_kms_present_ = 0;
-    } total_stats_, prev_stats_;
+    Stats total_stats_;
+    Stats prev_stats_;
     std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
   };
 
@@ -262,6 +356,7 @@
     DrmDevice *drm_;
   };
 
+ private:
   static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) {
     return static_cast<DrmHwcTwo *>(dev);
   }
@@ -331,8 +426,9 @@
 
   ResourceManager resource_manager_;
   std::map<hwc2_display_t, HwcDisplay> displays_;
-  std::map<HWC2::Callback, HwcCallback> callbacks_;
 
   std::string mDumpString;
 };
 }  // namespace android
+
+#endif
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/OWNERS b/OWNERS
index 9991fd8..75e29ae 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,6 +1,5 @@
 adelva@google.com
 john.stultz@linaro.org
 marcheu@google.com
-marissaw@google.com
 seanpaul@google.com
 zachr@google.com
diff --git a/backend/Backend.cpp b/backend/Backend.cpp
new file mode 100644
index 0000000..887eb0e
--- /dev/null
+++ b/backend/Backend.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#include "Backend.h"
+
+#include "BackendManager.h"
+#include "bufferinfo/BufferInfoGetter.h"
+
+namespace android {
+
+HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+                                     uint32_t *num_types,
+                                     uint32_t *num_requests) {
+  *num_types = 0;
+  *num_requests = 0;
+  size_t avail_planes = display->primary_planes().size() +
+                        display->overlay_planes().size();
+
+  /*
+   * If more layers then planes, save one plane
+   * for client composited layers
+   */
+  if (avail_planes < display->layers().size())
+    avail_planes--;
+
+  std::map<uint32_t, DrmHwcTwo::HwcLayer *> z_map, z_map_tmp;
+  uint32_t z_index = 0;
+  // First create a map of layers and z_order values
+  for (std::pair<const hwc2_layer_t, DrmHwcTwo::HwcLayer> &l :
+       display->layers())
+    z_map_tmp.emplace(std::make_pair(l.second.z_order(), &l.second));
+  // normalise the map so that the lowest z_order layer has key 0
+  for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map_tmp)
+    z_map.emplace(std::make_pair(z_index++, l.second));
+
+  uint32_t total_pixops = display->CalcPixOps(z_map, 0, z_map.size());
+  uint32_t gpu_pixops = 0;
+
+  int client_start = -1, client_size = 0;
+
+  if (display->compositor().ShouldFlattenOnClient()) {
+    client_start = 0;
+    client_size = z_map.size();
+    display->MarkValidated(z_map, client_start, client_size);
+  } else {
+    std::tie(client_start, client_size) = GetClientLayers(display, z_map);
+
+    int extra_client = (z_map.size() - client_size) - avail_planes;
+    if (extra_client > 0) {
+      int start = 0, steps;
+      if (client_size != 0) {
+        int prepend = std::min(client_start, extra_client);
+        int append = std::min(int(z_map.size() - (client_start + client_size)),
+                              extra_client);
+        start = client_start - prepend;
+        client_size += extra_client;
+        steps = 1 + std::min(std::min(append, prepend),
+                             int(z_map.size()) - (start + client_size));
+      } else {
+        client_size = extra_client;
+        steps = 1 + z_map.size() - extra_client;
+      }
+
+      gpu_pixops = INT_MAX;
+      for (int i = 0; i < steps; i++) {
+        uint32_t po = display->CalcPixOps(z_map, start + i, client_size);
+        if (po < gpu_pixops) {
+          gpu_pixops = po;
+          client_start = start + i;
+        }
+      }
+    }
+
+    display->MarkValidated(z_map, client_start, client_size);
+
+    bool testing_needed = !(client_start == 0 && client_size == z_map.size());
+
+    if (testing_needed &&
+        display->CreateComposition(true) != HWC2::Error::None) {
+      ++display->total_stats().failed_kms_validate_;
+      gpu_pixops = total_pixops;
+      client_size = z_map.size();
+      display->MarkValidated(z_map, 0, client_size);
+    }
+  }
+
+  *num_types = client_size;
+
+  display->total_stats().frames_flattened_ = display->compositor()
+                                                 .GetFlattenedFramesCount();
+  display->total_stats().gpu_pixops_ += gpu_pixops;
+  display->total_stats().total_pixops_ += total_pixops;
+
+  return *num_types ? HWC2::Error::HasChanges : HWC2::Error::None;
+}
+
+std::tuple<int, int> Backend::GetClientLayers(
+    DrmHwcTwo::HwcDisplay *display,
+    const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map) {
+  int client_start = -1, client_size = 0;
+
+  for (auto & [ z_order, layer ] : z_map) {
+    if (IsClientLayer(display, layer)) {
+      if (client_start < 0)
+        client_start = z_order;
+      client_size = (z_order - client_start) + 1;
+    }
+  }
+
+  return std::make_tuple(client_start, client_size);
+}
+
+bool Backend::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+                            DrmHwcTwo::HwcLayer *layer) {
+  return !display->HardwareSupportsLayerType(layer->sf_type()) ||
+         !BufferInfoGetter::GetInstance()->IsHandleUsable(layer->buffer()) ||
+         display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY ||
+         (layer->RequireScalingOrPhasing() &&
+          display->resource_manager()->ForcedScalingWithGpu());
+}
+
+REGISTER_BACKEND("generic", Backend);
+
+}  // namespace android
diff --git a/backend/Backend.h b/backend/Backend.h
new file mode 100644
index 0000000..898fece
--- /dev/null
+++ b/backend/Backend.h
@@ -0,0 +1,38 @@
+/*
+ * 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_BACKEND_H
+#define ANDROID_BACKEND_H
+
+#include "DrmHwcTwo.h"
+
+namespace android {
+
+class Backend {
+ public:
+  virtual ~Backend() = default;
+  virtual HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+                                      uint32_t *num_types,
+                                      uint32_t *num_requests);
+  virtual std::tuple<int, int> GetClientLayers(
+      DrmHwcTwo::HwcDisplay *display,
+      const std::map<uint32_t, DrmHwcTwo::HwcLayer *> &z_map);
+  virtual bool IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+                             DrmHwcTwo::HwcLayer *layer);
+};
+}  // namespace android
+
+#endif
diff --git a/backend/BackendClient.cpp b/backend/BackendClient.cpp
new file mode 100644
index 0000000..033a35c
--- /dev/null
+++ b/backend/BackendClient.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "BackendClient.h"
+
+#include "BackendManager.h"
+
+namespace android {
+
+HWC2::Error BackendClient::ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+                                           uint32_t *num_types,
+                                           uint32_t * /*num_requests*/) {
+  for (auto & [ layer_handle, layer ] : display->layers()) {
+    layer.set_validated_type(HWC2::Composition::Client);
+    ++*num_types;
+  }
+  return HWC2::Error::HasChanges;
+}
+
+REGISTER_BACKEND("client", BackendClient);
+
+}  // namespace android
diff --git a/backend/BackendClient.h b/backend/BackendClient.h
new file mode 100644
index 0000000..13543f1
--- /dev/null
+++ b/backend/BackendClient.h
@@ -0,0 +1,32 @@
+/*
+ * 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_BACKEND_CLIENT_H
+#define ANDROID_BACKEND_CLIENT_H
+
+#include "Backend.h"
+
+namespace android {
+
+class BackendClient : public Backend {
+ public:
+  HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+                              uint32_t *num_types,
+                              uint32_t *num_requests) override;
+};
+}  // namespace android
+
+#endif
diff --git a/backend/BackendManager.cpp b/backend/BackendManager.cpp
new file mode 100644
index 0000000..0bacdcd
--- /dev/null
+++ b/backend/BackendManager.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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-backend"
+
+#include "BackendManager.h"
+
+#include <cutils/properties.h>
+#include <log/log.h>
+
+namespace android {
+
+const std::vector<std::string> BackendManager::client_devices_ = {
+    "kirin",
+    "mediatek-drm",
+};
+
+BackendManager &BackendManager::GetInstance() {
+  static BackendManager backend_manager;
+
+  return backend_manager;
+}
+
+int BackendManager::RegisterBackend(const std::string &name,
+                                    backend_constructor_t backend_constructor) {
+  available_backends_[name] = std::move(backend_constructor);
+  return 0;
+}
+
+int BackendManager::SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display) {
+  std::string driver_name(display->drm()->GetName());
+  char backend_override[PROPERTY_VALUE_MAX];
+  property_get("vendor.hwc.backend_override", backend_override,
+               driver_name.c_str());
+  std::string backend_name(std::move(backend_override));
+
+  display->set_backend(GetBackendByName(backend_name));
+  if (!display->backend()) {
+    ALOGE("Failed to set backend '%s' for '%s' and driver '%s'",
+          backend_name.c_str(), display->connector()->name().c_str(),
+          driver_name.c_str());
+    return -EINVAL;
+  }
+
+  ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set",
+        backend_name.c_str(), display->connector()->name().c_str(),
+        driver_name.c_str());
+
+  return 0;
+}
+
+std::unique_ptr<Backend> BackendManager::GetBackendByName(std::string &name) {
+  if (!available_backends_.size()) {
+    ALOGE("No backends are specified");
+    return nullptr;
+  }
+
+  auto it = available_backends_.find(name);
+  if (it == available_backends_.end()) {
+    auto it = std::find(client_devices_.begin(), client_devices_.end(), name);
+    name = it == client_devices_.end() ? "generic" : "client";
+  }
+
+  return available_backends_[name]();
+}
+}  // namespace android
diff --git a/backend/BackendManager.h b/backend/BackendManager.h
new file mode 100644
index 0000000..e86c098
--- /dev/null
+++ b/backend/BackendManager.h
@@ -0,0 +1,57 @@
+/*
+ * 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_BACKEND_MANAGER_H
+#define ANDROID_BACKEND_MANAGER_H
+
+#include <functional>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "Backend.h"
+
+#define REGISTER_BACKEND(name_str_, backend_)                               \
+  static int                                                                \
+      backend = BackendManager::GetInstance()                               \
+                    .RegisterBackend(name_str_,                             \
+                                     []() -> std::unique_ptr<Backend> {     \
+                                       return std::make_unique<backend_>(); \
+                                     });
+
+namespace android {
+
+class BackendManager {
+ public:
+  using backend_constructor_t = std::function<std::unique_ptr<Backend>()>;
+  static BackendManager &GetInstance();
+  int RegisterBackend(const std::string &name,
+                      backend_constructor_t backend_constructor);
+  int SetBackendForDisplay(DrmHwcTwo::HwcDisplay *display);
+  std::unique_ptr<Backend> GetBackendByName(std::string &name);
+  HWC2::Error ValidateDisplay(DrmHwcTwo::HwcDisplay *display,
+                              uint32_t *num_types, uint32_t *num_requests);
+
+ private:
+  BackendManager() = default;
+
+  static const std::vector<std::string> client_devices_;
+
+  std::map<std::string, backend_constructor_t> available_backends_;
+};
+}  // namespace android
+
+#endif
diff --git a/backend/BackendRCarDu.cpp b/backend/BackendRCarDu.cpp
new file mode 100644
index 0000000..e85fa71
--- /dev/null
+++ b/backend/BackendRCarDu.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#include "BackendRCarDu.h"
+
+#include "BackendManager.h"
+#include "bufferinfo/BufferInfoGetter.h"
+#include "drm_fourcc.h"
+
+namespace android {
+
+bool BackendRCarDu::IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+                                  DrmHwcTwo::HwcLayer *layer) {
+  hwc_drm_bo_t bo;
+
+  int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(layer->buffer(),
+                                                           &bo);
+  if (ret)
+    return true;
+
+  if (bo.format == DRM_FORMAT_ABGR8888)
+    return true;
+
+  if (layer->RequireScalingOrPhasing())
+    return true;
+
+  return Backend::IsClientLayer(display, layer);
+}
+
+REGISTER_BACKEND("rcar-du", BackendRCarDu);
+
+}  // namespace android
\ No newline at end of file
diff --git a/backend/BackendRCarDu.h b/backend/BackendRCarDu.h
new file mode 100644
index 0000000..8a1011a
--- /dev/null
+++ b/backend/BackendRCarDu.h
@@ -0,0 +1,31 @@
+/*
+ * 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 HWC_DISPLAY_BACKEND_RCAR_DU_H
+#define HWC_DISPLAY_BACKEND_RCAR_DU_H
+
+#include "Backend.h"
+
+namespace android {
+
+class BackendRCarDu : public Backend {
+ public:
+  bool IsClientLayer(DrmHwcTwo::HwcDisplay *display,
+                     DrmHwcTwo::HwcLayer *layer) override;
+};
+}  // namespace android
+
+#endif
diff --git a/bufferinfo/BufferInfoGetter.cpp b/bufferinfo/BufferInfoGetter.cpp
new file mode 100644
index 0000000..afdc50e
--- /dev/null
+++ b/bufferinfo/BufferInfoGetter.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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-buffer-info-getter"
+
+#include "BufferInfoGetter.h"
+
+#if PLATFORM_SDK_VERSION >= 30
+#include "BufferInfoMapperMetadata.h"
+#endif
+
+#include <cutils/properties.h>
+#include <gralloc_handle.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+namespace android {
+
+BufferInfoGetter *BufferInfoGetter::GetInstance() {
+  static std::unique_ptr<BufferInfoGetter> inst;
+  if (inst == nullptr) {
+#if PLATFORM_SDK_VERSION >= 30
+    inst.reset(BufferInfoMapperMetadata::CreateInstance());
+    if (inst == nullptr) {
+      ALOGW(
+          "Generic buffer getter is not available. Falling back to legacy...");
+#endif
+      inst.reset(LegacyBufferInfoGetter::CreateInstance());
+#if PLATFORM_SDK_VERSION >= 30
+    }
+#endif
+  }
+
+  return inst.get();
+}
+
+bool BufferInfoGetter::IsHandleUsable(buffer_handle_t handle) {
+  hwc_drm_bo_t bo;
+  memset(&bo, 0, sizeof(hwc_drm_bo_t));
+
+  if (ConvertBoInfo(handle, &bo) != 0)
+    return false;
+
+  if (bo.prime_fds[0] == 0)
+    return false;
+
+  return true;
+}
+
+int LegacyBufferInfoGetter::Init() {
+  int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+                          (const hw_module_t **)&gralloc_);
+  if (ret) {
+    ALOGE("Failed to open gralloc module");
+    return ret;
+  }
+
+  ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name,
+        gralloc_->common.author);
+
+  return 0;
+}
+
+uint32_t LegacyBufferInfoGetter::ConvertHalFormatToDrm(uint32_t hal_format) {
+  switch (hal_format) {
+    case HAL_PIXEL_FORMAT_RGB_888:
+      return DRM_FORMAT_BGR888;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+      return DRM_FORMAT_ARGB8888;
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+      return DRM_FORMAT_XBGR8888;
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+      return DRM_FORMAT_ABGR8888;
+    case HAL_PIXEL_FORMAT_RGB_565:
+      return DRM_FORMAT_BGR565;
+    case HAL_PIXEL_FORMAT_YV12:
+      return DRM_FORMAT_YVU420;
+    default:
+      ALOGE("Cannot convert hal format to drm format %u", hal_format);
+      return DRM_FORMAT_INVALID;
+  }
+}
+
+bool BufferInfoGetter::IsDrmFormatRgb(uint32_t drm_format) {
+  switch (drm_format) {
+    case DRM_FORMAT_ARGB8888:
+    case DRM_FORMAT_XBGR8888:
+    case DRM_FORMAT_ABGR8888:
+    case DRM_FORMAT_BGR888:
+    case DRM_FORMAT_BGR565:
+      return true;
+    default:
+      return false;
+  }
+}
+
+__attribute__((weak)) LegacyBufferInfoGetter *
+LegacyBufferInfoGetter::CreateInstance() {
+  ALOGE("No legacy buffer info getters available");
+  return nullptr;
+}
+
+}  // namespace android
diff --git a/bufferinfo/BufferInfoGetter.h b/bufferinfo/BufferInfoGetter.h
new file mode 100644
index 0000000..fad3d16
--- /dev/null
+++ b/bufferinfo/BufferInfoGetter.h
@@ -0,0 +1,76 @@
+/*
+ * 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_BUFFERINFOGETTER_H_
+#define ANDROID_BUFFERINFOGETTER_H_
+
+#include <drm/drm_fourcc.h>
+#include <hardware/gralloc.h>
+
+#include "drm/DrmDevice.h"
+#include "drmhwcgralloc.h"
+
+#ifndef DRM_FORMAT_INVALID
+#define DRM_FORMAT_INVALID 0
+#endif
+
+namespace android {
+
+class BufferInfoGetter {
+ public:
+  virtual ~BufferInfoGetter() {
+  }
+
+  virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0;
+
+  bool IsHandleUsable(buffer_handle_t handle);
+
+  static BufferInfoGetter *GetInstance();
+
+  static bool IsDrmFormatRgb(uint32_t drm_format);
+};
+
+class LegacyBufferInfoGetter : public BufferInfoGetter {
+ public:
+  using BufferInfoGetter::BufferInfoGetter;
+
+  int Init();
+
+  int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override = 0;
+
+  static LegacyBufferInfoGetter *CreateInstance();
+
+  static uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
+  const gralloc_module_t *gralloc_;
+};
+
+#define LEGACY_BUFFER_INFO_GETTER(getter_)                           \
+  LegacyBufferInfoGetter *LegacyBufferInfoGetter::CreateInstance() { \
+    auto *instance = new getter_();                                  \
+    if (!instance)                                                   \
+      return NULL;                                                   \
+                                                                     \
+    int ret = instance->Init();                                      \
+    if (ret) {                                                       \
+      ALOGE("Failed to initialize the " #getter_ " getter %d", ret); \
+      delete instance;                                               \
+      return NULL;                                                   \
+    }                                                                \
+    return instance;                                                 \
+  }
+
+}  // namespace android
+#endif
diff --git a/bufferinfo/BufferInfoMapperMetadata.cpp b/bufferinfo/BufferInfoMapperMetadata.cpp
new file mode 100644
index 0000000..3aabeb5
--- /dev/null
+++ b/bufferinfo/BufferInfoMapperMetadata.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#if PLATFORM_SDK_VERSION >= 30
+
+#define LOG_TAG "hwc-bufferinfo-mappermetadata"
+
+#include "BufferInfoMapperMetadata.h"
+
+#include <drm/drm_fourcc.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <ui/GraphicBufferMapper.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
+namespace android {
+
+BufferInfoGetter *BufferInfoMapperMetadata::CreateInstance() {
+  if (GraphicBufferMapper::getInstance().getMapperVersion() <
+      GraphicBufferMapper::GRALLOC_4)
+    return nullptr;
+
+  return new BufferInfoMapperMetadata();
+}
+
+/* The implementation below makes assumptions on the order and number of file
+ * descriptors that Gralloc places in the native_handle_t and as such it very
+ * likely needs to be adapted to match the particular Gralloc implementation
+ * used in the system. For this reason it is been declared as a weak symbol,
+ * so that it can be overridden.
+ */
+int __attribute__((weak))
+BufferInfoMapperMetadata::GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+  int num_fds = handle->numFds;
+
+  if (num_fds >= 1 && num_fds <= 2) {
+    if (IsDrmFormatRgb(bo->format)) {
+      bo->prime_fds[0] = handle->data[0];
+    } else {
+      bo->prime_fds[0] = bo->prime_fds[1] = bo->prime_fds[2] = handle->data[0];
+    }
+    if (bo->prime_fds[0] <= 0) {
+      ALOGE("Encountered invalid fd %d", bo->prime_fds[0]);
+      return android::BAD_VALUE;
+    }
+
+  } else if (num_fds >= 3) {
+    bo->prime_fds[0] = handle->data[0];
+    bo->prime_fds[1] = handle->data[1];
+    bo->prime_fds[2] = handle->data[2];
+    for (int i = 0; i < 3; i++) {
+      if (bo->prime_fds[i] <= 0) {
+        ALOGE("Encountered invalid fd %d", bo->prime_fds[i]);
+        return android::BAD_VALUE;
+      }
+    }
+  }
+  return 0;
+}
+
+int BufferInfoMapperMetadata::ConvertBoInfo(buffer_handle_t handle,
+                                            hwc_drm_bo_t *bo) {
+  GraphicBufferMapper &mapper = GraphicBufferMapper::getInstance();
+  if (!handle)
+    return -EINVAL;
+
+  uint64_t usage = 0;
+  int err = mapper.getUsage(handle, &usage);
+  if (err) {
+    ALOGE("Failed to get usage err=%d", err);
+    return err;
+  }
+  bo->usage = static_cast<uint32_t>(usage);
+
+  ui::PixelFormat hal_format;
+  err = mapper.getPixelFormatRequested(handle, &hal_format);
+  if (err) {
+    ALOGE("Failed to get HAL Pixel Format err=%d", err);
+    return err;
+  }
+  bo->hal_format = static_cast<uint32_t>(hal_format);
+
+  err = mapper.getPixelFormatFourCC(handle, &bo->format);
+  if (err) {
+    ALOGE("Failed to get FourCC format err=%d", err);
+    return err;
+  }
+
+  err = mapper.getPixelFormatModifier(handle, &bo->modifiers[0]);
+  if (err) {
+    ALOGE("Failed to get DRM Modifier err=%d", err);
+    return err;
+  }
+  bo->with_modifiers = true;
+
+  uint64_t width = 0;
+  err = mapper.getWidth(handle, &width);
+  if (err) {
+    ALOGE("Failed to get Width err=%d", err);
+    return err;
+  }
+  bo->width = static_cast<uint32_t>(width);
+
+  uint64_t height = 0;
+  err = mapper.getHeight(handle, &height);
+  if (err) {
+    ALOGE("Failed to get Height err=%d", err);
+    return err;
+  }
+  bo->height = static_cast<uint32_t>(height);
+
+  std::vector<ui::PlaneLayout> layouts;
+  err = mapper.getPlaneLayouts(handle, &layouts);
+  if (err) {
+    ALOGE("Failed to get Plane Layouts err=%d", err);
+    return err;
+  }
+
+  for (uint32_t i = 0; i < layouts.size(); i++) {
+    bo->modifiers[i] = bo->modifiers[0];
+    bo->pitches[i] = layouts[i].strideInBytes;
+    bo->offsets[i] = layouts[i].offsetInBytes;
+  }
+
+  return GetFds(handle, bo);
+}
+
+}  // namespace android
+
+#endif
diff --git a/platform/platformminigbm.h b/bufferinfo/BufferInfoMapperMetadata.h
similarity index 63%
copy from platform/platformminigbm.h
copy to bufferinfo/BufferInfoMapperMetadata.h
index 053b2aa..d335705 100644
--- a/platform/platformminigbm.h
+++ b/bufferinfo/BufferInfoMapperMetadata.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,23 +14,23 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_
-#define ANDROID_PLATFORM_DRM_MINIGBM_H_
+#ifndef PLATFORMIMAGINATION_H
+#define PLATFORMIMAGINATION_H
 
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
-
-#include <hardware/gralloc.h>
+#include "bufferinfo/BufferInfoGetter.h"
 
 namespace android {
 
-class DrmMinigbmImporter : public DrmGenericImporter {
+class BufferInfoMapperMetadata : public BufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
-  int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
-};
+  using BufferInfoGetter::BufferInfoGetter;
 
+  int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
+
+  int GetFds(buffer_handle_t handle, hwc_drm_bo_t *bo);
+
+  static BufferInfoGetter *CreateInstance();
+};
 }  // namespace android
 
-#endif
+#endif  // PLATFORMIMAGINATION_H
diff --git a/bufferinfo/legacy/BufferInfoImagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp
new file mode 100644
index 0000000..84c177e
--- /dev/null
+++ b/bufferinfo/legacy/BufferInfoImagination.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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-bufferinfo-imagination"
+
+#include "BufferInfoImagination.h"
+
+#include <log/log.h>
+#include <xf86drm.h>
+
+#include "img_gralloc1_public.h"
+
+namespace android {
+
+LEGACY_BUFFER_INFO_GETTER(BufferInfoImagination);
+
+int BufferInfoImagination::ConvertBoInfo(buffer_handle_t handle,
+                                         hwc_drm_bo_t *bo) {
+  IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle;
+  if (!hnd)
+    return -EINVAL;
+
+  /* Extra bits are responsible for buffer compression and memory layout */
+  if (hnd->iFormat & ~0x10f) {
+    ALOGV("Special buffer formats are not supported");
+    return -EINVAL;
+  }
+
+  bo->width = hnd->iWidth;
+  bo->height = hnd->iHeight;
+  bo->usage = hnd->usage;
+  bo->prime_fds[0] = hnd->fd[0];
+  bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3;
+  bo->hal_format = hnd->iFormat;
+
+  switch (hnd->iFormat) {
+#ifdef HAL_PIXEL_FORMAT_BGRX_8888
+    case HAL_PIXEL_FORMAT_BGRX_8888:
+      bo->format = DRM_FORMAT_XRGB8888;
+      break;
+#endif
+    default:
+      bo->format = ConvertHalFormatToDrm(hnd->iFormat & 0xf);
+      if (bo->format == DRM_FORMAT_INVALID) {
+        ALOGV("Cannot convert hal format to drm format %u", hnd->iFormat);
+        return -EINVAL;
+      }
+  }
+
+  return 0;
+}
+
+}  // namespace android
diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoImagination.h
similarity index 68%
copy from platform/platformminigbm.h
copy to bufferinfo/legacy/BufferInfoImagination.h
index 053b2aa..765b279 100644
--- a/platform/platformminigbm.h
+++ b/bufferinfo/legacy/BufferInfoImagination.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,23 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_
-#define ANDROID_PLATFORM_DRM_MINIGBM_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
+#ifndef BUFFERINFOIMAGINATION_H
+#define BUFFERINFOIMAGINATION_H
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class DrmMinigbmImporter : public DrmGenericImporter {
+class BufferInfoImagination : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
+
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
 };
-
 }  // namespace android
 
-#endif
+#endif  // PLATFORMIMAGINATION_H
diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp
new file mode 100644
index 0000000..3f6a6fd
--- /dev/null
+++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp
@@ -0,0 +1,195 @@
+/*
+ * 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-bufferinfo-libdrm"
+
+#include "BufferInfoLibdrm.h"
+
+#include <cutils/properties.h>
+#include <gralloc_handle.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+namespace android {
+
+LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm);
+
+enum chroma_order {
+  YCbCr,
+  YCrCb,
+};
+
+struct droid_yuv_format {
+  /* Lookup keys */
+  int native;                     /* HAL_PIXEL_FORMAT_ */
+  enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
+  int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
+
+  /* Result */
+  int fourcc; /* DRM_FORMAT_ */
+};
+
+/* The following table is used to look up a DRI image FourCC based
+ * on native format and information contained in android_ycbcr struct. */
+static const struct droid_yuv_format droid_yuv_formats[] = {
+    /* Native format, YCrCb, Chroma step, DRI image FourCC */
+    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12},
+    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420},
+    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420},
+    {HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420},
+    /* HACK: See droid_create_image_from_prime_fds() and
+     * https://issuetracker.google.com/32077885. */
+    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12},
+    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420},
+    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420},
+    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV},
+    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888},
+};
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static int get_fourcc_yuv(int native, enum chroma_order chroma_order,
+                          int chroma_step) {
+  for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
+    if (droid_yuv_formats[i].native == native &&
+        droid_yuv_formats[i].chroma_order == chroma_order &&
+        droid_yuv_formats[i].chroma_step == chroma_step)
+      return droid_yuv_formats[i].fourcc;
+
+  return -1;
+}
+
+static bool is_yuv(int native) {
+  for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
+    if (droid_yuv_formats[i].native == native)
+      return true;
+
+  return false;
+}
+
+bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle,
+                                       hwc_drm_bo_t *bo) {
+  struct android_ycbcr ycbcr;
+  enum chroma_order chroma_order;
+  int ret;
+
+  if (!gralloc_->lock_ycbcr) {
+    static std::once_flag once;
+    std::call_once(once,
+                   []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
+    return false;
+  }
+
+  memset(&ycbcr, 0, sizeof(ycbcr));
+  ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
+  if (ret) {
+    ALOGW("gralloc->lock_ycbcr failed: %d", ret);
+    return false;
+  }
+  gralloc_->unlock(gralloc_, handle);
+
+  /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
+   * it will return the .y/.cb/.cr pointers based on a NULL pointer,
+   * so they can be interpreted as offsets. */
+  bo->offsets[0] = (size_t)ycbcr.y;
+  /* We assume here that all the planes are located in one DMA-buf. */
+  if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
+    chroma_order = YCrCb;
+    bo->offsets[1] = (size_t)ycbcr.cr;
+    bo->offsets[2] = (size_t)ycbcr.cb;
+  } else {
+    chroma_order = YCbCr;
+    bo->offsets[1] = (size_t)ycbcr.cb;
+    bo->offsets[2] = (size_t)ycbcr.cr;
+  }
+
+  /* .ystride is the line length (in bytes) of the Y plane,
+   * .cstride is the line length (in bytes) of any of the remaining
+   * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
+   * planar formats. */
+  bo->pitches[0] = ycbcr.ystride;
+  bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;
+
+  /* .chroma_step is the byte distance between the same chroma channel
+   * values of subsequent pixels, assumed to be the same for Cb and Cr. */
+  bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step);
+  if (bo->format == -1) {
+    ALOGW(
+        "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
+        "%d",
+        bo->hal_format, chroma_order == YCbCr ? "YCbCr" : "YCrCb",
+        (int)ycbcr.chroma_step);
+    return false;
+  }
+
+  /*
+   * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
+   * the single-fd case cannot happen.  So handle eithe single
+   * fd or fd-per-plane case:
+   */
+  if (num_fds == 1) {
+    bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
+  } else {
+    int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
+    if (num_fds != expected_planes)
+      return false;
+  }
+
+  return true;
+}
+
+int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+  gralloc_handle_t *gr_handle = gralloc_handle(handle);
+  if (!gr_handle)
+    return -EINVAL;
+
+  bo->width = gr_handle->width;
+  bo->height = gr_handle->height;
+  bo->hal_format = gr_handle->format;
+
+#if GRALLOC_HANDLE_VERSION < 4
+  static std::once_flag once;
+  std::call_once(once, []() {
+    ALOGE(
+        "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
+  });
+#endif
+#if GRALLOC_HANDLE_VERSION == 4
+  bo->modifiers[0] = gr_handle->modifier;
+  bo->with_modifiers = gr_handle->modifier != DRM_FORMAT_MOD_NONE &&
+                       gr_handle->modifier != DRM_FORMAT_MOD_INVALID;
+#endif
+
+  bo->usage = gr_handle->usage;
+  bo->prime_fds[0] = gr_handle->prime_fd;
+
+  if (is_yuv(gr_handle->format)) {
+    if (!GetYuvPlaneInfo(handle->numFds, handle, bo))
+      return -EINVAL;
+  } else {
+    bo->pitches[0] = gr_handle->stride;
+    bo->offsets[0] = 0;
+    bo->format = ConvertHalFormatToDrm(gr_handle->format);
+    if (bo->format == DRM_FORMAT_INVALID)
+      return -EINVAL;
+  }
+
+  return 0;
+}
+
+}  // namespace android
diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoLibdrm.h
similarity index 66%
copy from platform/platformminigbm.h
copy to bufferinfo/legacy/BufferInfoLibdrm.h
index 053b2aa..4d37d00 100644
--- a/platform/platformminigbm.h
+++ b/bufferinfo/legacy/BufferInfoLibdrm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,21 +14,22 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_
-#define ANDROID_PLATFORM_DRM_MINIGBM_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
+#ifndef BUFFERINFOLIBDRM_H_
+#define BUFFERINFOLIBDRM_H_
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class DrmMinigbmImporter : public DrmGenericImporter {
+class BufferInfoLibdrm : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
+
+ private:
+  bool GetYuvPlaneInfo(int num_fds, buffer_handle_t handle, hwc_drm_bo_t *bo);
 };
 
 }  // namespace android
diff --git a/bufferinfo/legacy/BufferInfoMaliHisi.cpp b/bufferinfo/legacy/BufferInfoMaliHisi.cpp
new file mode 100644
index 0000000..ab5579c
--- /dev/null
+++ b/bufferinfo/legacy/BufferInfoMaliHisi.cpp
@@ -0,0 +1,128 @@
+/*
+ * 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-bufferinfo-mali-hisi"
+
+#include "BufferInfoMaliHisi.h"
+
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cinttypes>
+
+#include "gralloc_priv.h"
+
+#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
+
+namespace android {
+
+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliHisi);
+
+#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \
+    defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)
+uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers(uint64_t flags,
+                                                                bool is_rgb) {
+  uint64_t features = 0UL;
+
+  if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC)
+    features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16;
+
+  if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK)
+    features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE);
+
+  if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
+    features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8;
+
+  if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
+    features |= AFBC_FORMAT_MOD_TILED;
+
+  if (features) {
+    if (is_rgb)
+      features |= AFBC_FORMAT_MOD_YTR;
+
+    return DRM_FORMAT_MOD_ARM_AFBC(features);
+  }
+
+  return 0;
+}
+#else
+uint64_t BufferInfoMaliHisi::ConvertGrallocFormatToDrmModifiers(
+    uint64_t /* flags */, bool /* is_rgb */) {
+  return 0;
+}
+#endif
+
+int BufferInfoMaliHisi::ConvertBoInfo(buffer_handle_t handle,
+                                      hwc_drm_bo_t *bo) {
+  bool is_rgb;
+
+  private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
+      handle);
+  if (!hnd)
+    return -EINVAL;
+
+  if (!(hnd->usage & GRALLOC_USAGE_HW_FB))
+    return -EINVAL;
+
+  uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
+  if (fmt == DRM_FORMAT_INVALID)
+    return -EINVAL;
+
+  is_rgb = IsDrmFormatRgb(fmt);
+  bo->modifiers[0] = ConvertGrallocFormatToDrmModifiers(hnd->internal_format,
+                                                        is_rgb);
+
+  bo->width = hnd->width;
+  bo->height = hnd->height;
+  bo->hal_format = hnd->req_format;
+  bo->format = fmt;
+  bo->usage = hnd->usage;
+  bo->pitches[0] = hnd->byte_stride;
+  bo->prime_fds[0] = hnd->share_fd;
+  bo->offsets[0] = 0;
+
+  switch (fmt) {
+    case DRM_FORMAT_YVU420: {
+      int align = 128;
+      if (hnd->usage &
+          (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
+        align = 16;
+      int adjusted_height = MALI_ALIGN(hnd->height, 2);
+      int y_size = adjusted_height * hnd->byte_stride;
+      int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align);
+      int v_size = vu_stride * (adjusted_height / 2);
+
+      /* V plane*/
+      bo->prime_fds[1] = hnd->share_fd;
+      bo->pitches[1] = vu_stride;
+      bo->offsets[1] = y_size;
+      /* U plane */
+      bo->prime_fds[2] = hnd->share_fd;
+      bo->pitches[2] = vu_stride;
+      bo->offsets[2] = y_size + v_size;
+      break;
+    }
+    default:
+      break;
+  }
+
+  bo->with_modifiers = true;
+
+  return 0;
+}
+
+}  // namespace android
diff --git a/platform/platformhisi.h b/bufferinfo/legacy/BufferInfoMaliHisi.h
similarity index 68%
rename from platform/platformhisi.h
rename to bufferinfo/legacy/BufferInfoMaliHisi.h
index f127bdb..698a0d3 100644
--- a/platform/platformhisi.h
+++ b/bufferinfo/legacy/BufferInfoMaliHisi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,29 +14,23 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_HISI_H_
-#define ANDROID_PLATFORM_HISI_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
-
-#include <stdatomic.h>
+#ifndef BUFFERINFOMALIHISI_H_
+#define BUFFERINFOMALIHISI_H_
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class HisiImporter : public DrmGenericImporter {
+class BufferInfoMaliHisi : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
 
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
 
  private:
   uint64_t ConvertGrallocFormatToDrmModifiers(uint64_t flags, bool is_rgb);
-
-  bool IsDrmFormatRgb(uint32_t drm_format);
 };
 }  // namespace android
 
diff --git a/bufferinfo/legacy/BufferInfoMaliMediatek.cpp b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp
new file mode 100644
index 0000000..ce47343
--- /dev/null
+++ b/bufferinfo/legacy/BufferInfoMaliMediatek.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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-bufferinfo-mali-mediatek"
+
+#include "BufferInfoMaliMediatek.h"
+
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <stdatomic.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cinttypes>
+
+#include "gralloc_priv.h"
+
+namespace android {
+
+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMediatek);
+
+int BufferInfoMaliMediatek::ConvertBoInfo(buffer_handle_t handle,
+                                          hwc_drm_bo_t *bo) {
+  private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
+      handle);
+  if (!hnd)
+    return -EINVAL;
+
+  uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
+  if (fmt == DRM_FORMAT_INVALID)
+    return -EINVAL;
+
+  bo->width = hnd->width;
+  bo->height = hnd->height;
+  bo->hal_format = hnd->req_format;
+  bo->format = fmt;
+  bo->usage = hnd->consumer_usage | hnd->producer_usage;
+  bo->prime_fds[0] = hnd->share_fd;
+  bo->pitches[0] = hnd->byte_stride;
+  bo->offsets[0] = 0;
+
+  return 0;
+}
+
+}  // namespace android
diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoMaliMediatek.h
similarity index 69%
copy from platform/platformminigbm.h
copy to bufferinfo/legacy/BufferInfoMaliMediatek.h
index 053b2aa..1204818 100644
--- a/platform/platformminigbm.h
+++ b/bufferinfo/legacy/BufferInfoMaliMediatek.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * 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.
@@ -14,23 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_
-#define ANDROID_PLATFORM_DRM_MINIGBM_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
+#ifndef BUFFERINFOMALIMTK_H_
+#define BUFFERINFOMALIMTK_H_
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class DrmMinigbmImporter : public DrmGenericImporter {
+class BufferInfoMaliMediatek : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
+
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
 };
-
 }  // namespace android
 
 #endif
diff --git a/platform/platformmeson.cpp b/bufferinfo/legacy/BufferInfoMaliMeson.cpp
similarity index 68%
rename from platform/platformmeson.cpp
rename to bufferinfo/legacy/BufferInfoMaliMeson.cpp
index ad3aff1..b6896e1 100644
--- a/platform/platformmeson.cpp
+++ b/bufferinfo/legacy/BufferInfoMaliMeson.cpp
@@ -14,40 +14,26 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "hwc-platform-meson"
+#define LOG_TAG "hwc-bufferinfo-mali-meson"
 
-#include "platformmeson.h"
-#include "drmdevice.h"
-#include "platform.h"
+#include "BufferInfoMaliMeson.h"
 
-#include <stdatomic.h>
+#include <log/log.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
+
 #include <cinttypes>
 
-#include <hardware/gralloc.h>
-#include <log/log.h>
 #include "gralloc_priv.h"
 
 namespace android {
 
-Importer *Importer::CreateInstance(DrmDevice *drm) {
-  MesonImporter *importer = new MesonImporter(drm);
-  if (!importer)
-    return NULL;
-
-  int ret = importer->Init();
-  if (ret) {
-    ALOGE("Failed to initialize the meson importer %d", ret);
-    delete importer;
-    return NULL;
-  }
-  return importer;
-}
+LEGACY_BUFFER_INFO_GETTER(BufferInfoMaliMeson);
 
 #if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \
     defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)
-uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags) {
+uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers(
+    uint64_t flags) {
   uint64_t features = 0UL;
 
   if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC) {
@@ -69,13 +55,14 @@
   return 0;
 }
 #else
-uint64_t MesonImporter::ConvertGrallocFormatToDrmModifiers(
+uint64_t BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers(
     uint64_t /* flags */) {
   return 0;
 }
 #endif
 
-int MesonImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+int BufferInfoMaliMeson::ConvertBoInfo(buffer_handle_t handle,
+                                       hwc_drm_bo_t *bo) {
   private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
       handle);
   if (!hnd)
@@ -88,7 +75,7 @@
   if (fmt == DRM_FORMAT_INVALID)
     return -EINVAL;
 
-  bo->modifiers[0] = MesonImporter::ConvertGrallocFormatToDrmModifiers(
+  bo->modifiers[0] = BufferInfoMaliMeson::ConvertGrallocFormatToDrmModifiers(
       hnd->internal_format);
 
   bo->width = hnd->width;
@@ -96,7 +83,6 @@
   bo->hal_format = hnd->req_format;
   bo->format = fmt;
   bo->usage = hnd->usage;
-  bo->pixel_stride = hnd->stride;
   bo->prime_fds[0] = hnd->share_fd;
   bo->pitches[0] = hnd->byte_stride;
   bo->offsets[0] = 0;
@@ -106,9 +92,4 @@
   return 0;
 }
 
-std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
-  std::unique_ptr<Planner> planner(new Planner);
-  planner->AddStage<PlanStageGreedy>();
-  return planner;
-}
 }  // namespace android
diff --git a/platform/platformmeson.h b/bufferinfo/legacy/BufferInfoMaliMeson.h
similarity index 75%
rename from platform/platformmeson.h
rename to bufferinfo/legacy/BufferInfoMaliMeson.h
index f29b796..ce5d3f9 100644
--- a/platform/platformmeson.h
+++ b/bufferinfo/legacy/BufferInfoMaliMeson.h
@@ -14,23 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_HISI_H_
-#define ANDROID_PLATFORM_HISI_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
-
-#include <stdatomic.h>
+#ifndef BUFFERINFOMALIHISI_H_
+#define BUFFERINFOMALIHISI_H_
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class MesonImporter : public DrmGenericImporter {
+class BufferInfoMaliMeson : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
-
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
 
  private:
diff --git a/bufferinfo/legacy/BufferInfoMinigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp
new file mode 100644
index 0000000..860de08
--- /dev/null
+++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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-bufferinfo-minigbm"
+
+#include "BufferInfoMinigbm.h"
+
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include "cros_gralloc_handle.h"
+
+namespace android {
+
+LEGACY_BUFFER_INFO_GETTER(BufferInfoMinigbm);
+
+int BufferInfoMinigbm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
+  cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle;
+  if (!gr_handle)
+    return -EINVAL;
+
+  bo->width = gr_handle->width;
+  bo->height = gr_handle->height;
+  bo->hal_format = gr_handle->droid_format;
+  bo->format = gr_handle->format;
+  bo->usage = gr_handle->usage;
+  bo->prime_fds[0] = gr_handle->fds[0];
+  bo->pitches[0] = gr_handle->strides[0];
+  bo->offsets[0] = gr_handle->offsets[0];
+
+  return 0;
+}
+
+}  // namespace android
diff --git a/platform/platformminigbm.h b/bufferinfo/legacy/BufferInfoMinigbm.h
similarity index 74%
rename from platform/platformminigbm.h
rename to bufferinfo/legacy/BufferInfoMinigbm.h
index 053b2aa..bff9d74 100644
--- a/platform/platformminigbm.h
+++ b/bufferinfo/legacy/BufferInfoMinigbm.h
@@ -14,20 +14,18 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PLATFORM_DRM_MINIGBM_H_
-#define ANDROID_PLATFORM_DRM_MINIGBM_H_
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
+#ifndef BUFFERINFOMINIGBM_H_
+#define BUFFERINFOMINIGBM_H_
 
 #include <hardware/gralloc.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+
 namespace android {
 
-class DrmMinigbmImporter : public DrmGenericImporter {
+class BufferInfoMinigbm : public LegacyBufferInfoGetter {
  public:
-  using DrmGenericImporter::DrmGenericImporter;
+  using LegacyBufferInfoGetter::LegacyBufferInfoGetter;
   int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
 };
 
diff --git a/compositor/drmdisplaycomposition.cpp b/compositor/DrmDisplayComposition.cpp
similarity index 97%
rename from compositor/drmdisplaycomposition.cpp
rename to compositor/DrmDisplayComposition.cpp
index b710fe1..4d2e19a 100644
--- a/compositor/drmdisplaycomposition.cpp
+++ b/compositor/DrmDisplayComposition.cpp
@@ -16,21 +16,19 @@
 
 #define LOG_TAG "hwc-drm-display-composition"
 
-#include "drmdisplaycomposition.h"
-#include "drmcrtc.h"
-#include "drmdevice.h"
-#include "drmdisplaycompositor.h"
-#include "drmplane.h"
-#include "platform.h"
+#include "DrmDisplayComposition.h"
 
+#include <log/log.h>
 #include <stdlib.h>
+#include <sync/sync.h>
+#include <xf86drmMode.h>
 
 #include <algorithm>
 #include <unordered_set>
 
-#include <log/log.h>
-#include <sync/sync.h>
-#include <xf86drmMode.h>
+#include "DrmDisplayCompositor.h"
+#include "Planner.h"
+#include "drm/DrmDevice.h"
 
 namespace android {
 
diff --git a/include/drmdisplaycomposition.h b/compositor/DrmDisplayComposition.h
similarity index 98%
rename from include/drmdisplaycomposition.h
rename to compositor/DrmDisplayComposition.h
index 2a5b1a4..73a9024 100644
--- a/include/drmdisplaycomposition.h
+++ b/compositor/DrmDisplayComposition.h
@@ -17,15 +17,15 @@
 #ifndef ANDROID_DRM_DISPLAY_COMPOSITION_H_
 #define ANDROID_DRM_DISPLAY_COMPOSITION_H_
 
-#include "drmcrtc.h"
-#include "drmhwcomposer.h"
-#include "drmplane.h"
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
 
 #include <sstream>
 #include <vector>
 
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
+#include "drm/DrmCrtc.h"
+#include "drm/DrmPlane.h"
+#include "drmhwcomposer.h"
 
 namespace android {
 
diff --git a/compositor/drmdisplaycompositor.cpp b/compositor/DrmDisplayCompositor.cpp
similarity index 92%
rename from compositor/drmdisplaycompositor.cpp
rename to compositor/DrmDisplayCompositor.cpp
index e6f6922..ba0d56b 100644
--- a/compositor/drmdisplaycompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -17,29 +17,39 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #define LOG_TAG "hwc-drm-display-compositor"
 
-#include "drmdisplaycompositor.h"
-
-#include <pthread.h>
-#include <sched.h>
-#include <stdlib.h>
-#include <time.h>
-#include <sstream>
-#include <vector>
+#include "DrmDisplayCompositor.h"
 
 #include <drm/drm_mode.h>
 #include <log/log.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdlib.h>
 #include <sync/sync.h>
+#include <time.h>
 #include <utils/Trace.h>
 
-#include "autolock.h"
-#include "drmcrtc.h"
-#include "drmdevice.h"
-#include "drmplane.h"
+#include <array>
+#include <sstream>
+#include <vector>
+
+#include "drm/DrmCrtc.h"
+#include "drm/DrmDevice.h"
+#include "drm/DrmPlane.h"
+#include "utils/autolock.h"
 
 static const uint32_t kWaitWritebackFence = 100;  // ms
 
 namespace android {
 
+std::ostream &operator<<(std::ostream &str, FlatteningState state) {
+  std::array<const char *, 6> flattenting_state_str = {
+      "None",   "Not needed", "SF Requested", "Squashed by GPU",
+      "Serial", "Concurrent",
+  };
+
+  return str << flattenting_state_str[static_cast<int>(state)];
+}
+
 class CompositorVsyncCallback : public VsyncCallback {
  public:
   CompositorVsyncCallback(DrmDisplayCompositor *compositor)
@@ -63,7 +73,9 @@
       dump_frames_composited_(0),
       dump_last_timestamp_ns_(0),
       flatten_countdown_(FLATTEN_COUNTDOWN_INIT),
-      writeback_fence_(-1) {
+      writeback_fence_(-1),
+      flattening_state_(FlatteningState::kNone),
+      frames_flattened_(0) {
   struct timespec ts;
   if (clock_gettime(CLOCK_MONOTONIC, &ts))
     return;
@@ -143,6 +155,19 @@
   return comp;
 }
 
+FlatteningState DrmDisplayCompositor::GetFlatteningState() const {
+  return flattening_state_;
+}
+
+uint32_t DrmDisplayCompositor::GetFlattenedFramesCount() const {
+  return frames_flattened_;
+}
+
+bool DrmDisplayCompositor::ShouldFlattenOnClient() const {
+  return flattening_state_ == FlatteningState::kClientRequested ||
+         flattening_state_ == FlatteningState::kClientDone;
+}
+
 std::tuple<uint32_t, uint32_t, int>
 DrmDisplayCompositor::GetActiveModeResolution() {
   DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
@@ -605,6 +630,11 @@
   active_composition_.swap(composition);
 
   flatten_countdown_ = FLATTEN_COUNTDOWN_INIT;
+  if (flattening_state_ != FlatteningState::kClientRequested) {
+    SetFlattening(FlatteningState::kNone);
+  } else {
+    SetFlattening(FlatteningState::kClientDone);
+  }
   vsync_worker_.VSyncControl(!writeback);
 }
 
@@ -761,6 +791,54 @@
   return 0;
 }
 
+void DrmDisplayCompositor::SetFlattening(FlatteningState new_state) {
+  if (flattening_state_ != new_state) {
+    switch (flattening_state_) {
+      case FlatteningState::kClientDone:
+      case FlatteningState::kConcurrent:
+      case FlatteningState::kSerial:
+        ++frames_flattened_;
+        break;
+      case FlatteningState::kClientRequested:
+      case FlatteningState::kNone:
+      case FlatteningState::kNotNeeded:
+        break;
+    }
+  }
+  flattening_state_ = new_state;
+}
+
+bool DrmDisplayCompositor::IsFlatteningNeeded() const {
+  return CountdownExpired() && active_composition_->layers().size() >= 2;
+}
+
+int DrmDisplayCompositor::FlattenOnClient() {
+  const std::lock_guard<std::mutex> lock(refresh_callback_lock);
+
+  if (refresh_callback_hook_ && refresh_callback_data_) {
+    {
+      AutoLock lock(&lock_, __func__);
+      if (!IsFlatteningNeeded()) {
+        if (flattening_state_ != FlatteningState::kClientDone) {
+          ALOGV("Flattening is not needed");
+          SetFlattening(FlatteningState::kNotNeeded);
+        }
+        return -EALREADY;
+      }
+    }
+
+    ALOGV(
+        "No writeback connector available, "
+        "falling back to client composition");
+    SetFlattening(FlatteningState::kClientRequested);
+    refresh_callback_hook_(refresh_callback_data_, display_);
+    return 0;
+  } else {
+    ALOGV("No writeback connector available");
+    return -EINVAL;
+  }
+}
+
 // Flatten a scene by enabling the writeback connector attached
 // to the same CRTC as the one driving the display.
 int DrmDisplayCompositor::FlattenSerial(DrmConnector *writeback_conn) {
@@ -776,8 +854,9 @@
   int ret = lock.Lock();
   if (ret)
     return ret;
-  if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+  if (!IsFlatteningNeeded()) {
     ALOGV("Flattening is not needed");
+    SetFlattening(FlatteningState::kNotNeeded);
     return -EALREADY;
   }
 
@@ -884,8 +963,9 @@
   ret = lock.Lock();
   if (ret)
     return ret;
-  if (!CountdownExpired() || active_composition_->layers().size() < 2) {
+  if (!IsFlatteningNeeded()) {
     ALOGV("Flattening is not needed");
+    SetFlattening(FlatteningState::kNotNeeded);
     return -EALREADY;
   }
   DrmCrtc *crtc = active_composition_->crtc();
@@ -955,13 +1035,16 @@
   DrmConnector *writeback_conn = resource_manager_->AvailableWritebackConnector(
       display_);
   if (!active_composition_ || !writeback_conn) {
-    ALOGV("No writeback connector available");
-    return -EINVAL;
+    // Try to fallback to GPU composition on client, since it is more
+    // power-efficient than composition on device side
+    return FlattenOnClient();
   }
 
   if (writeback_conn->display() != display_) {
+    SetFlattening(FlatteningState::kConcurrent);
     return FlattenConcurrent(writeback_conn);
   } else {
+    SetFlattening(FlatteningState::kSerial);
     return FlattenSerial(writeback_conn);
   }
 
diff --git a/include/drmdisplaycompositor.h b/compositor/DrmDisplayCompositor.h
similarity index 78%
rename from include/drmdisplaycompositor.h
rename to compositor/DrmDisplayCompositor.h
index 477f226..ab3f867 100644
--- a/include/drmdisplaycompositor.h
+++ b/compositor/DrmDisplayCompositor.h
@@ -17,19 +17,20 @@
 #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_
 #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_
 
-#include "drmdisplaycomposition.h"
-#include "drmframebuffer.h"
-#include "drmhwcomposer.h"
-#include "resourcemanager.h"
-#include "vsyncworker.h"
-
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
 #include <pthread.h>
+
 #include <memory>
 #include <sstream>
 #include <tuple>
 
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
+#include "DrmDisplayComposition.h"
+#include "DrmFramebuffer.h"
+#include "Planner.h"
+#include "drm/ResourceManager.h"
+#include "drm/VSyncWorker.h"
+#include "drmhwcomposer.h"
 
 // One for the front, one for the back, and one for cases where we need to
 // squash a frame that the hw can't display with hw overlays.
@@ -41,6 +42,17 @@
 
 namespace android {
 
+enum class FlatteningState {
+  kNone,
+  kNotNeeded,
+  kClientRequested,
+  kClientDone,
+  kSerial,
+  kConcurrent
+};
+
+std::ostream &operator<<(std::ostream &str, FlatteningState state);
+
 class DrmDisplayCompositor {
  public:
   DrmDisplayCompositor();
@@ -48,6 +60,17 @@
 
   int Init(ResourceManager *resource_manager, int display);
 
+  hwc2_callback_data_t refresh_callback_data_ = NULL;
+  HWC2_PFN_REFRESH refresh_callback_hook_ = NULL;
+  std::mutex refresh_callback_lock;
+
+  void SetRefreshCallback(hwc2_callback_data_t data,
+                          hwc2_function_pointer_t hook) {
+    const std::lock_guard<std::mutex> lock(refresh_callback_lock);
+    refresh_callback_data_ = data;
+    refresh_callback_hook_ = reinterpret_cast<HWC2_PFN_REFRESH>(hook);
+  }
+
   std::unique_ptr<DrmDisplayComposition> CreateComposition() const;
   std::unique_ptr<DrmDisplayComposition> CreateInitializedComposition() const;
   int ApplyComposition(std::unique_ptr<DrmDisplayComposition> composition);
@@ -62,6 +85,10 @@
     return active_composition_->take_out_fence();
   }
 
+  FlatteningState GetFlatteningState() const;
+  uint32_t GetFlattenedFramesCount() const;
+  bool ShouldFlattenOnClient() const;
+
   std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
 
  private:
@@ -90,7 +117,11 @@
 
   void ApplyFrame(std::unique_ptr<DrmDisplayComposition> composition,
                   int status, bool writeback = false);
+
+  void SetFlattening(FlatteningState new_state);
+  bool IsFlatteningNeeded() const;
   int FlattenActiveComposition();
+  int FlattenOnClient();
   int FlattenSerial(DrmConnector *writeback_conn);
   int FlattenConcurrent(DrmConnector *writeback_conn);
   int FlattenOnDisplay(std::unique_ptr<DrmDisplayComposition> &src,
@@ -126,6 +157,11 @@
   int64_t flatten_countdown_;
   std::unique_ptr<Planner> planner_;
   int writeback_fence_;
+
+  FlatteningState flattening_state_;
+  uint32_t frames_flattened_;
+
+  std::function<void(int)> refresh_display_cb_;
 };
 }  // namespace android
 
diff --git a/platform/platform.cpp b/compositor/Planner.cpp
similarity index 90%
rename from platform/platform.cpp
rename to compositor/Planner.cpp
index b7a47c7..f4b5c51 100644
--- a/platform/platform.cpp
+++ b/compositor/Planner.cpp
@@ -16,13 +16,20 @@
 
 #define LOG_TAG "hwc-platform"
 
-#include "platform.h"
-#include "drmdevice.h"
+#include "Planner.h"
 
 #include <log/log.h>
 
+#include "drm/DrmDevice.h"
+
 namespace android {
 
+std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
+  std::unique_ptr<Planner> planner(new Planner);
+  planner->AddStage<PlanStageGreedy>();
+  return planner;
+}
+
 std::vector<DrmPlane *> Planner::GetUsablePlanes(
     DrmCrtc *crtc, std::vector<DrmPlane *> *primary_planes,
     std::vector<DrmPlane *> *overlay_planes) {
@@ -77,6 +84,13 @@
       ALOGE("Expected a valid blend mode on plane %d", plane->id());
   }
 
+  uint32_t format = layer->buffer->format;
+  if (!plane->IsFormatSupported(format)) {
+    ALOGE("Plane %d does not supports %c%c%c%c format", plane->id(), format,
+          format >> 8, format >> 16, format >> 24);
+    return -EINVAL;
+  }
+
   return ret;
 }
 
diff --git a/include/platform.h b/compositor/Planner.h
similarity index 81%
rename from include/platform.h
rename to compositor/Planner.h
index 6775e29..09034ff 100644
--- a/include/platform.h
+++ b/compositor/Planner.h
@@ -17,46 +17,19 @@
 #ifndef ANDROID_DRM_PLATFORM_H_
 #define ANDROID_DRM_PLATFORM_H_
 
-#include "drmdisplaycomposition.h"
-#include "drmhwcomposer.h"
-
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 
 #include <map>
 #include <vector>
 
+#include "compositor/DrmDisplayComposition.h"
+#include "drmhwcomposer.h"
+
 namespace android {
 
 class DrmDevice;
 
-class Importer {
- public:
-  virtual ~Importer() {
-  }
-
-  // Creates a platform-specific importer instance
-  static Importer *CreateInstance(DrmDevice *drm);
-
-  // 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(buffer_handle_t handle, 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;
-
-  // Checks if importer can import the buffer.
-  virtual bool CanImportBuffer(buffer_handle_t handle) = 0;
-
-  // Convert platform-dependent buffer format to drm_hwc internal format.
-  virtual int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) = 0;
-};
-
 class Planner {
  public:
   class PlanStage {
diff --git a/drm/drmconnector.cpp b/drm/DrmConnector.cpp
similarity index 89%
rename from drm/drmconnector.cpp
rename to drm/DrmConnector.cpp
index 7cde7cd..f1b6c1b 100644
--- a/drm/drmconnector.cpp
+++ b/drm/DrmConnector.cpp
@@ -16,17 +16,17 @@
 
 #define LOG_TAG "hwc-drm-connector"
 
-#include "drmconnector.h"
-#include "drmdevice.h"
+#include "DrmConnector.h"
 
 #include <errno.h>
+#include <log/log.h>
 #include <stdint.h>
+#include <xf86drmMode.h>
 
 #include <array>
 #include <sstream>
 
-#include <log/log.h>
-#include <xf86drmMode.h>
+#include "DrmDevice.h"
 
 namespace android {
 
@@ -58,6 +58,7 @@
     ALOGE("Could not get CRTC_ID property\n");
     return ret;
   }
+  ret = UpdateEdidProperty();
   if (writeback()) {
     ret = drm_->GetConnectorProperty(*this, "WRITEBACK_PIXEL_FORMATS",
                                      &writeback_pixel_formats_);
@@ -81,6 +82,30 @@
   return 0;
 }
 
+int DrmConnector::UpdateEdidProperty() {
+  int ret = drm_->GetConnectorProperty(*this, "EDID", &edid_property_);
+  if (ret) {
+    ALOGW("Could not get EDID property\n");
+  }
+  return ret;
+}
+
+int DrmConnector::GetEdidBlob(drmModePropertyBlobPtr &blob) {
+  uint64_t blob_id;
+  int ret = UpdateEdidProperty();
+  if (ret) {
+    return ret;
+  }
+
+  std::tie(ret, blob_id) = edid_property().value();
+  if (ret) {
+    return ret;
+  }
+
+  blob = drmModeGetPropertyBlob(drm_->fd(), blob_id);
+  return !blob;
+}
+
 uint32_t DrmConnector::id() const {
   return id_;
 }
@@ -191,6 +216,10 @@
   return crtc_id_property_;
 }
 
+const DrmProperty &DrmConnector::edid_property() const {
+  return edid_property_;
+}
+
 const DrmProperty &DrmConnector::writeback_pixel_formats() const {
   return writeback_pixel_formats_;
 }
diff --git a/include/drmconnector.h b/drm/DrmConnector.h
similarity index 91%
rename from include/drmconnector.h
rename to drm/DrmConnector.h
index c9fd7ab..8533af8 100644
--- a/include/drmconnector.h
+++ b/drm/DrmConnector.h
@@ -17,15 +17,16 @@
 #ifndef ANDROID_DRM_CONNECTOR_H_
 #define ANDROID_DRM_CONNECTOR_H_
 
-#include "drmencoder.h"
-#include "drmmode.h"
-#include "drmproperty.h"
-
 #include <stdint.h>
 #include <xf86drmMode.h>
+
 #include <string>
 #include <vector>
 
+#include "DrmEncoder.h"
+#include "DrmMode.h"
+#include "DrmProperty.h"
+
 namespace android {
 
 class DrmDevice;
@@ -39,6 +40,8 @@
   DrmConnector &operator=(const DrmProperty &) = delete;
 
   int Init();
+  int UpdateEdidProperty();
+  int GetEdidBlob(drmModePropertyBlobPtr &blob);
 
   uint32_t id() const;
 
@@ -62,6 +65,7 @@
 
   const DrmProperty &dpms_property() const;
   const DrmProperty &crtc_id_property() const;
+  const DrmProperty &edid_property() const;
   const DrmProperty &writeback_pixel_formats() const;
   const DrmProperty &writeback_fb_id() const;
   const DrmProperty &writeback_out_fence() const;
@@ -100,6 +104,7 @@
 
   DrmProperty dpms_property_;
   DrmProperty crtc_id_property_;
+  DrmProperty edid_property_;
   DrmProperty writeback_pixel_formats_;
   DrmProperty writeback_fb_id_;
   DrmProperty writeback_out_fence_;
diff --git a/drm/drmcrtc.cpp b/drm/DrmCrtc.cpp
similarity index 97%
rename from drm/drmcrtc.cpp
rename to drm/DrmCrtc.cpp
index b627291..4ce8cfc 100644
--- a/drm/drmcrtc.cpp
+++ b/drm/DrmCrtc.cpp
@@ -16,13 +16,13 @@
 
 #define LOG_TAG "hwc-drm-crtc"
 
-#include "drmcrtc.h"
-#include "drmdevice.h"
+#include "DrmCrtc.h"
 
+#include <log/log.h>
 #include <stdint.h>
 #include <xf86drmMode.h>
 
-#include <log/log.h>
+#include "DrmDevice.h"
 
 namespace android {
 
diff --git a/include/drmcrtc.h b/drm/DrmCrtc.h
similarity index 96%
rename from include/drmcrtc.h
rename to drm/DrmCrtc.h
index 3075f9b..7972bef 100644
--- a/include/drmcrtc.h
+++ b/drm/DrmCrtc.h
@@ -17,12 +17,12 @@
 #ifndef ANDROID_DRM_CRTC_H_
 #define ANDROID_DRM_CRTC_H_
 
-#include "drmmode.h"
-#include "drmproperty.h"
-
 #include <stdint.h>
 #include <xf86drmMode.h>
 
+#include "DrmMode.h"
+#include "DrmProperty.h"
+
 namespace android {
 
 class DrmDevice;
diff --git a/drm/drmdevice.cpp b/drm/DrmDevice.cpp
similarity index 96%
rename from drm/drmdevice.cpp
rename to drm/DrmDevice.cpp
index bcb9ddd..bf1a5e2 100644
--- a/drm/drmdevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -16,27 +16,22 @@
 
 #define LOG_TAG "hwc-drm-device"
 
-#include "drmdevice.h"
-#include "drmconnector.h"
-#include "drmcrtc.h"
-#include "drmencoder.h"
-#include "drmeventlistener.h"
-#include "drmplane.h"
+#include "DrmDevice.h"
 
+#include <cutils/properties.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <log/log.h>
 #include <stdint.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
-#include <cinttypes>
 
 #include <algorithm>
 #include <array>
+#include <cinttypes>
+#include <sstream>
 #include <string>
 
-#include <cutils/properties.h>
-#include <log/log.h>
-
 static void trim_left(std::string &str) {
   str.erase(std::begin(str),
             std::find_if(std::begin(str), std::end(str),
@@ -59,7 +54,7 @@
 
 static std::vector<std::string> read_primary_display_order_prop() {
   std::array<char, PROPERTY_VALUE_MAX> display_order_buf;
-  property_get("hwc.drm.primary_display_order", display_order_buf.data(),
+  property_get("vendor.hwc.drm.primary_display_order", display_order_buf.data(),
                "...");
 
   std::vector<std::string> display_order;
@@ -126,7 +121,7 @@
   /* TODO: Use drmOpenControl here instead */
   fd_.Set(open(path, O_RDWR));
   if (fd() < 0) {
-    ALOGE("Failed to open dri- %s", strerror(-errno));
+    ALOGE("Failed to open dri %s: %s", path, strerror(errno));
     return std::make_tuple(-ENODEV, 0);
   }
 
@@ -254,7 +249,7 @@
   }
 
   // Primary display priority:
-  // 1) hwc.drm.primary_display_order property
+  // 1) vendor.hwc.drm.primary_display_order property
   // 2) internal connectors
   // 3) anything else
   std::vector<DrmConnector *>
@@ -267,8 +262,8 @@
     found_primary = true;
   } else {
     ALOGE(
-        "Failed to find primary display from \"hwc.drm.primary_display_order\" "
-        "property");
+        "Failed to find primary display from "
+        "\"vendor.hwc.drm.primary_display_order\" property");
   }
 
   // If no priority display were found then pick first available as primary and
@@ -570,4 +565,16 @@
   return GetProperty(connector.id(), DRM_MODE_OBJECT_CONNECTOR, prop_name,
                      property);
 }
+
+const std::string DrmDevice::GetName() const {
+  auto ver = drmGetVersion(fd_.get());
+  if (!ver) {
+    ALOGW("Failed to get drm version for fd=%d", fd_.get());
+    return "generic";
+  }
+
+  std::string name(ver->name);
+  drmFreeVersion(ver);
+  return name;
+}
 }  // namespace android
diff --git a/include/drmdevice.h b/drm/DrmDevice.h
similarity index 94%
rename from include/drmdevice.h
rename to drm/DrmDevice.h
index 91dd38b..be68aa6 100644
--- a/include/drmdevice.h
+++ b/drm/DrmDevice.h
@@ -17,16 +17,17 @@
 #ifndef ANDROID_DRM_H_
 #define ANDROID_DRM_H_
 
-#include "drmconnector.h"
-#include "drmcrtc.h"
-#include "drmencoder.h"
-#include "drmeventlistener.h"
-#include "drmplane.h"
-#include "platform.h"
-
 #include <stdint.h>
+
+#include <map>
 #include <tuple>
 
+#include "DrmConnector.h"
+#include "DrmCrtc.h"
+#include "DrmEncoder.h"
+#include "DrmEventListener.h"
+#include "DrmPlane.h"
+
 namespace android {
 
 class DrmDevice {
@@ -70,6 +71,8 @@
   int GetConnectorProperty(const DrmConnector &connector, const char *prop_name,
                            DrmProperty *property);
 
+  const std::string GetName() const;
+
   const std::vector<std::unique_ptr<DrmCrtc>> &crtcs() const;
   uint32_t next_mode_id();
 
diff --git a/drm/drmencoder.cpp b/drm/DrmEncoder.cpp
similarity index 95%
rename from drm/drmencoder.cpp
rename to drm/DrmEncoder.cpp
index c36fca1..bcf0926 100644
--- a/drm/drmencoder.cpp
+++ b/drm/DrmEncoder.cpp
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include "drmencoder.h"
-#include "drmcrtc.h"
-#include "drmdevice.h"
+#include "DrmEncoder.h"
 
 #include <stdint.h>
 #include <xf86drmMode.h>
 
+#include "DrmDevice.h"
+
 namespace android {
 
 DrmEncoder::DrmEncoder(drmModeEncoderPtr e, DrmCrtc *current_crtc,
diff --git a/include/drmencoder.h b/drm/DrmEncoder.h
similarity index 97%
rename from include/drmencoder.h
rename to drm/DrmEncoder.h
index 8a7f682..f4464d0 100644
--- a/include/drmencoder.h
+++ b/drm/DrmEncoder.h
@@ -17,13 +17,14 @@
 #ifndef ANDROID_DRM_ENCODER_H_
 #define ANDROID_DRM_ENCODER_H_
 
-#include "drmcrtc.h"
-
 #include <stdint.h>
 #include <xf86drmMode.h>
+
 #include <set>
 #include <vector>
 
+#include "DrmCrtc.h"
+
 namespace android {
 
 class DrmEncoder {
diff --git a/drm/drmeventlistener.cpp b/drm/DrmEventListener.cpp
similarity index 94%
rename from drm/drmeventlistener.cpp
rename to drm/DrmEventListener.cpp
index 8f655a7..3d95e28 100644
--- a/drm/drmeventlistener.cpp
+++ b/drm/DrmEventListener.cpp
@@ -16,19 +16,19 @@
 
 #define LOG_TAG "hwc-drm-event-listener"
 
-#include "drmeventlistener.h"
-#include "drmdevice.h"
+#include "DrmEventListener.h"
 
 #include <assert.h>
 #include <errno.h>
-#include <linux/netlink.h>
-#include <sys/socket.h>
-
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
+#include <linux/netlink.h>
 #include <log/log.h>
+#include <sys/socket.h>
 #include <xf86drm.h>
 
+#include "DrmDevice.h"
+
 namespace android {
 
 DrmEventListener::DrmEventListener(DrmDevice *drm)
@@ -38,7 +38,7 @@
 int DrmEventListener::Init() {
   uevent_fd_.Set(socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT));
   if (uevent_fd_.get() < 0) {
-    ALOGE("Failed to open uevent socket %d", uevent_fd_.get());
+    ALOGE("Failed to open uevent socket: %s", strerror(errno));
     return uevent_fd_.get();
   }
 
@@ -50,7 +50,7 @@
 
   int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr));
   if (ret) {
-    ALOGE("Failed to bind uevent socket %d", -errno);
+    ALOGE("Failed to bind uevent socket: %s", strerror(errno));
     return -errno;
   }
 
diff --git a/include/drmeventlistener.h b/drm/DrmEventListener.h
similarity index 97%
rename from include/drmeventlistener.h
rename to drm/DrmEventListener.h
index 95672ee..9f9a4ba 100644
--- a/include/drmeventlistener.h
+++ b/drm/DrmEventListener.h
@@ -18,7 +18,7 @@
 #define ANDROID_DRM_EVENT_LISTENER_H_
 
 #include "autofd.h"
-#include "worker.h"
+#include "utils/Worker.h"
 
 namespace android {
 
diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp
new file mode 100644
index 0000000..8ab4fe5
--- /dev/null
+++ b/drm/DrmGenericImporter.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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 <cutils/properties.h>
+#include <gralloc_handle.h>
+#include <hardware/gralloc.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.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;
+}
+
+DrmGenericImporter::~DrmGenericImporter() {
+}
+
+int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) {
+  int ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0],
+                               &bo->gem_handles[0]);
+  if (ret) {
+    ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret);
+    return ret;
+  }
+
+  for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
+    int fd = bo->prime_fds[i];
+    if (fd != 0) {
+      if (fd != bo->prime_fds[0]) {
+        ALOGE("Multiplanar FBs are not supported by this version of composer");
+        return -ENOTSUP;
+      }
+      bo->gem_handles[i] = bo->gem_handles[0];
+    }
+  }
+
+  if (!has_modifier_support_ && bo->modifiers[0]) {
+    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
+          bo->modifiers[0]);
+    return -EINVAL;
+  }
+
+  if (!bo->with_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,
+                                     bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS
+                                                      : 0);
+
+  if (ret) {
+    ALOGE("could not create drm fb %d", ret);
+    return ret;
+  }
+
+  ImportHandle(bo->gem_handles[0]);
+
+  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 (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
+    if (!bo->gem_handles[i])
+      continue;
+
+    if (ReleaseHandle(bo->gem_handles[i])) {
+      ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
+    } else {
+      for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
+        if (bo->gem_handles[j] == bo->gem_handles[i])
+          bo->gem_handles[j] = 0;
+      bo->gem_handles[i] = 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;
+
+  memset(&gem_close, 0, sizeof(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/platform/platformdrmgeneric.h b/drm/DrmGenericImporter.h
similarity index 60%
rename from platform/platformdrmgeneric.h
rename to drm/DrmGenericImporter.h
index f9d923f..ca53762 100644
--- a/platform/platformdrmgeneric.h
+++ b/drm/DrmGenericImporter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -17,13 +17,13 @@
 #ifndef ANDROID_PLATFORM_DRM_GENERIC_H_
 #define ANDROID_PLATFORM_DRM_GENERIC_H_
 
-#include "drmdevice.h"
-#include "platform.h"
-
+#include <drm/drm_fourcc.h>
 #include <hardware/gralloc.h>
+
 #include <map>
 
-#include <drm/drm_fourcc.h>
+#include "drm/DrmDevice.h"
+#include "drmhwcgralloc.h"
 
 #ifndef DRM_FORMAT_INVALID
 #define DRM_FORMAT_INVALID 0
@@ -31,34 +31,43 @@
 
 namespace android {
 
+class Importer {
+ public:
+  virtual ~Importer() {
+  }
+
+  // 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;
 
-  int Init();
-
-  int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
+  int ImportBuffer(hwc_drm_bo_t *bo) override;
   int ReleaseBuffer(hwc_drm_bo_t *bo) override;
-  bool CanImportBuffer(buffer_handle_t handle) override;
   int ImportHandle(uint32_t gem_handle);
   int ReleaseHandle(uint32_t gem_handle);
 
-  int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
-
-  uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
-  uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format);
-
  protected:
   DrmDevice *drm_;
 
  private:
-  const gralloc_module_t *gralloc_;
-  bool exclude_non_hwfb_;
-
   int CloseHandle(uint32_t gem_handle);
   std::map<uint32_t, int> gem_refcount_;
+  bool has_modifier_support_;
 };
+
 }  // namespace android
 
 #endif
diff --git a/drm/drmmode.cpp b/drm/DrmMode.cpp
similarity index 96%
rename from drm/drmmode.cpp
rename to drm/DrmMode.cpp
index c3ab385..6de671a 100644
--- a/drm/drmmode.cpp
+++ b/drm/DrmMode.cpp
@@ -14,12 +14,9 @@
  * limitations under the License.
  */
 
-#include "drmmode.h"
-#include "drmdevice.h"
+#include "DrmMode.h"
 
-#include <stdint.h>
-#include <xf86drmMode.h>
-#include <string>
+#include "DrmDevice.h"
 
 namespace android {
 
diff --git a/include/drmmode.h b/drm/DrmMode.h
similarity index 99%
rename from include/drmmode.h
rename to drm/DrmMode.h
index 4cc06b1..313a8ea 100644
--- a/include/drmmode.h
+++ b/drm/DrmMode.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <xf86drmMode.h>
+
 #include <string>
 
 namespace android {
diff --git a/drm/drmplane.cpp b/drm/DrmPlane.cpp
similarity index 93%
rename from drm/drmplane.cpp
rename to drm/DrmPlane.cpp
index 6f1bf9b..f994252 100644
--- a/drm/drmplane.cpp
+++ b/drm/DrmPlane.cpp
@@ -16,20 +16,23 @@
 
 #define LOG_TAG "hwc-drm-plane"
 
-#include "drmplane.h"
-#include "drmdevice.h"
+#include "DrmPlane.h"
 
 #include <errno.h>
+#include <log/log.h>
 #include <stdint.h>
+
 #include <cinttypes>
 
-#include <log/log.h>
-#include <xf86drmMode.h>
+#include "DrmDevice.h"
 
 namespace android {
 
 DrmPlane::DrmPlane(DrmDevice *drm, drmModePlanePtr p)
-    : drm_(drm), id_(p->plane_id), possible_crtc_mask_(p->possible_crtcs) {
+    : drm_(drm),
+      id_(p->plane_id),
+      possible_crtc_mask_(p->possible_crtcs),
+      formats_(p->formats, p->formats + p->count_formats) {
 }
 
 int DrmPlane::Init() {
@@ -153,6 +156,11 @@
   return type_;
 }
 
+bool DrmPlane::IsFormatSupported(uint32_t format) const {
+  return std::find(std::begin(formats_), std::end(formats_), format) !=
+         std::end(formats_);
+}
+
 const DrmProperty &DrmPlane::crtc_property() const {
   return crtc_property_;
 }
diff --git a/include/drmplane.h b/drm/DrmPlane.h
similarity index 94%
rename from include/drmplane.h
rename to drm/DrmPlane.h
index 43e0e8a..16731a8 100644
--- a/include/drmplane.h
+++ b/drm/DrmPlane.h
@@ -17,13 +17,14 @@
 #ifndef ANDROID_DRM_PLANE_H_
 #define ANDROID_DRM_PLANE_H_
 
-#include "drmcrtc.h"
-#include "drmproperty.h"
-
 #include <stdint.h>
 #include <xf86drmMode.h>
+
 #include <vector>
 
+#include "DrmCrtc.h"
+#include "DrmProperty.h"
+
 namespace android {
 
 class DrmDevice;
@@ -42,6 +43,8 @@
 
   uint32_t type() const;
 
+  bool IsFormatSupported(uint32_t format) const;
+
   const DrmProperty &crtc_property() const;
   const DrmProperty &fb_property() const;
   const DrmProperty &crtc_x_property() const;
@@ -66,6 +69,8 @@
 
   uint32_t type_;
 
+  std::vector<uint32_t> formats_;
+
   DrmProperty crtc_property_;
   DrmProperty fb_property_;
   DrmProperty crtc_x_property_;
diff --git a/drm/drmproperty.cpp b/drm/DrmProperty.cpp
similarity index 98%
rename from drm/drmproperty.cpp
rename to drm/DrmProperty.cpp
index 3aeed13..b60a76e 100644
--- a/drm/drmproperty.cpp
+++ b/drm/DrmProperty.cpp
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-#include "drmproperty.h"
-#include "drmdevice.h"
+#include "DrmProperty.h"
 
 #include <errno.h>
 #include <stdint.h>
+#include <xf86drmMode.h>
+
 #include <string>
 
-#include <xf86drmMode.h>
+#include "DrmDevice.h"
 
 namespace android {
 
diff --git a/include/drmproperty.h b/drm/DrmProperty.h
similarity index 99%
rename from include/drmproperty.h
rename to drm/DrmProperty.h
index 2d92ca1..d293da3 100644
--- a/include/drmproperty.h
+++ b/drm/DrmProperty.h
@@ -19,6 +19,7 @@
 
 #include <stdint.h>
 #include <xf86drmMode.h>
+
 #include <string>
 #include <vector>
 
diff --git a/drm/resourcemanager.cpp b/drm/ResourceManager.cpp
similarity index 73%
rename from drm/resourcemanager.cpp
rename to drm/ResourceManager.cpp
index 6e23561..fc24aea 100644
--- a/drm/resourcemanager.cpp
+++ b/drm/ResourceManager.cpp
@@ -16,12 +16,15 @@
 
 #define LOG_TAG "hwc-resource-manager"
 
-#include "resourcemanager.h"
+#include "ResourceManager.h"
 
 #include <cutils/properties.h>
 #include <log/log.h>
+#include <sys/stat.h>
+
 #include <sstream>
-#include <string>
+
+#include "bufferinfo/BufferInfoGetter.h"
 
 namespace android {
 
@@ -32,7 +35,8 @@
   char path_pattern[PROPERTY_VALUE_MAX];
   // Could be a valid path or it can have at the end of it the wildcard %
   // which means that it will try open all devices until an error is met.
-  int path_len = property_get("hwc.drm.device", path_pattern, "/dev/dri/card0");
+  int path_len = property_get("vendor.hwc.drm.device", path_pattern,
+                              "/dev/dri/card%");
   int ret = 0;
   if (path_pattern[path_len - 1] != '%') {
     ret = AddDrmDevice(std::string(path_pattern));
@@ -41,7 +45,13 @@
     for (int idx = 0; !ret; ++idx) {
       std::ostringstream path;
       path << path_pattern << idx;
-      ret = AddDrmDevice(path.str());
+
+      struct stat buf;
+      if (stat(path.str().c_str(), &buf)) {
+        break;
+      } else if (IsKMSDev(path.str().c_str())) {
+        ret = AddDrmDevice(path.str());
+      }
     }
   }
 
@@ -50,6 +60,15 @@
     return ret ? -EINVAL : ret;
   }
 
+  char scale_with_gpu[PROPERTY_VALUE_MAX];
+  property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0");
+  scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1));
+
+  if (!BufferInfoGetter::GetInstance()) {
+    ALOGE("Failed to initialize BufferInfoGetter");
+    return -EINVAL;
+  }
+
   return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
                        (const hw_module_t **)&gralloc_);
 }
@@ -61,7 +80,7 @@
   if (ret)
     return ret;
   std::shared_ptr<Importer> importer;
-  importer.reset(Importer::CreateInstance(drm.get()));
+  importer.reset(new DrmGenericImporter(drm.get()));
   if (!importer) {
     ALOGE("Failed to create importer instance");
     return -ENODEV;
@@ -90,6 +109,26 @@
   return writeback_conn;
 }
 
+bool ResourceManager::IsKMSDev(const char *path) {
+  int fd = open(path, O_RDWR | O_CLOEXEC);
+  if (fd < 0)
+    return false;
+
+  auto res = drmModeGetResources(fd);
+  if (!res) {
+    close(fd);
+    return false;
+  }
+
+  bool is_kms = res->count_crtcs > 0 && res->count_connectors > 0 &&
+                res->count_encoders > 0;
+
+  drmModeFreeResources(res);
+  close(fd);
+
+  return is_kms;
+}
+
 DrmDevice *ResourceManager::GetDrmDevice(int display) {
   for (auto &drm : drms_) {
     if (drm->HandlesDisplay(display))
diff --git a/include/resourcemanager.h b/drm/ResourceManager.h
similarity index 88%
rename from include/resourcemanager.h
rename to drm/ResourceManager.h
index f10af45..7102cea 100644
--- a/include/resourcemanager.h
+++ b/drm/ResourceManager.h
@@ -17,11 +17,11 @@
 #ifndef RESOURCEMANAGER_H
 #define RESOURCEMANAGER_H
 
-#include "drmdevice.h"
-#include "platform.h"
-
 #include <string.h>
 
+#include "DrmDevice.h"
+#include "DrmGenericImporter.h"
+
 namespace android {
 
 class ResourceManager {
@@ -40,14 +40,20 @@
   int getDisplayCount() const {
     return num_displays_;
   }
+  bool ForcedScalingWithGpu() {
+    return scale_with_gpu_;
+  }
 
  private:
   int AddDrmDevice(std::string path);
+  static bool IsKMSDev(const char *path);
 
   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_;
 };
 }  // namespace android
 
diff --git a/drm/vsyncworker.cpp b/drm/VSyncWorker.cpp
similarity index 75%
rename from drm/vsyncworker.cpp
rename to drm/VSyncWorker.cpp
index 08ab301..b2f7e5f 100644
--- a/drm/vsyncworker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -16,18 +16,13 @@
 
 #define LOG_TAG "hwc-vsync-worker"
 
-#include "vsyncworker.h"
-#include "drmdevice.h"
-#include "worker.h"
+#include "VSyncWorker.h"
 
+#include <log/log.h>
 #include <stdlib.h>
 #include <time.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
-#include <map>
-
-#include <hardware/hardware.h>
-#include <log/log.h>
 
 namespace android {
 
@@ -55,6 +50,14 @@
   Unlock();
 }
 
+void VSyncWorker::RegisterClientCallback(hwc2_callback_data_t data,
+                                         hwc2_function_pointer_t hook) {
+  Lock();
+  vsync_callback_data_ = data;
+  vsync_callback_hook_ = reinterpret_cast<HWC2_PFN_VSYNC>(hook);
+  Unlock();
+}
+
 void VSyncWorker::VSyncControl(bool enabled) {
   Lock();
   enabled_ = enabled;
@@ -156,37 +159,17 @@
                 (int64_t)vblank.reply.tval_usec * 1000;
   }
 
-  /*
-   * VSync could be disabled during routine execution so it could potentially
-   * lead to crash since callback's inner hook could be invalid anymore. We have
-   * no control over lifetime of this hook, therefore we can't rely that it'll
-   * be valid after vsync disabling.
-   *
-   * Blocking VSyncControl to wait until routine
-   * will finish execution is logically correct way to fix this issue, but it
-   * creates visible lags and stutters, so we have to resort to other ways of
-   * mitigating this issue.
-   *
-   * Doing check before attempt to invoke callback drastically shortens the
-   * window when such situation could happen and that allows us to practically
-   * avoid this issue.
-   *
-   * Please note that issue described below is different one and it is related
-   * to RegisterCallback, not to disabling vsync via VSyncControl.
-   */
   if (!enabled_)
     return;
-  /*
-   * There's a race here where a change in callback_ will not take effect until
-   * the next subsequent requested vsync. This is unavoidable since we can't
-   * call the vsync hook while holding the thread lock.
-   *
-   * We could shorten the race window by caching callback_ right before calling
-   * the hook. However, in practice, callback_ is only updated once, so it's not
-   * worth the overhead.
-   */
+
   if (callback)
     callback->Callback(display, timestamp);
+
+  Lock();
+  if (enabled_ && vsync_callback_hook_ && vsync_callback_data_)
+    vsync_callback_hook_(vsync_callback_data_, display, timestamp);
+  Unlock();
+
   last_timestamp_ = timestamp;
 }
 }  // namespace android
diff --git a/include/vsyncworker.h b/drm/VSyncWorker.h
similarity index 84%
rename from include/vsyncworker.h
rename to drm/VSyncWorker.h
index 96f7432..7454b51 100644
--- a/include/vsyncworker.h
+++ b/drm/VSyncWorker.h
@@ -17,14 +17,15 @@
 #ifndef ANDROID_EVENT_WORKER_H_
 #define ANDROID_EVENT_WORKER_H_
 
-#include "drmdevice.h"
-#include "worker.h"
-
-#include <stdint.h>
-#include <map>
-
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer2.h>
+#include <stdint.h>
+
+#include <map>
+
+#include "DrmDevice.h"
+#include "utils/Worker.h"
 
 namespace android {
 
@@ -42,6 +43,8 @@
 
   int Init(DrmDevice *drm, int display);
   void RegisterCallback(std::shared_ptr<VsyncCallback> callback);
+  void RegisterClientCallback(hwc2_callback_data_t data,
+                              hwc2_function_pointer_t hook);
 
   void VSyncControl(bool enabled);
 
@@ -62,6 +65,9 @@
   int display_;
   std::atomic_bool enabled_;
   int64_t last_timestamp_;
+
+  hwc2_callback_data_t vsync_callback_data_ = NULL;
+  HWC2_PFN_VSYNC vsync_callback_hook_ = NULL;
 };
 }  // namespace android
 
diff --git a/include/drmframebuffer.h b/include/DrmFramebuffer.h
similarity index 99%
rename from include/drmframebuffer.h
rename to include/DrmFramebuffer.h
index 9032d3a..33ca0db 100644
--- a/include/drmframebuffer.h
+++ b/include/DrmFramebuffer.h
@@ -18,9 +18,7 @@
 #define ANDROID_DRM_FRAMEBUFFER_
 
 #include <stdint.h>
-
 #include <sync/sync.h>
-
 #include <ui/GraphicBuffer.h>
 
 namespace android {
diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h
index b959714..fc0af64 100644
--- a/include/drmhwcgralloc.h
+++ b/include/drmhwcgralloc.h
@@ -26,7 +26,6 @@
   uint32_t format;     /* DRM_FORMAT_* from drm_fourcc.h */
   uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */
   uint32_t usage;
-  uint32_t pixel_stride;
   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];
diff --git a/include/drmhwcomposer.h b/include/drmhwcomposer.h
index 69313d9..0706ae5 100644
--- a/include/drmhwcomposer.h
+++ b/include/drmhwcomposer.h
@@ -99,8 +99,7 @@
     return *this;
   }
 
-  int CopyBufferHandle(buffer_handle_t handle, int width, int height,
-                       int layerCount, int format, int usage, int stride);
+  int CopyBufferHandle(buffer_handle_t handle);
 
   void Clear();
 
diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp
deleted file mode 100644
index 1aa8160..0000000
--- a/platform/platformdrmgeneric.cpp
+++ /dev/null
@@ -1,252 +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.
- */
-
-#define LOG_TAG "hwc-platform-drm-generic"
-
-#include "platformdrmgeneric.h"
-#include "drmdevice.h"
-#include "platform.h"
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <cutils/properties.h>
-#include <gralloc_handle.h>
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-namespace android {
-
-#ifdef USE_DRM_GENERIC_IMPORTER
-// static
-Importer *Importer::CreateInstance(DrmDevice *drm) {
-  DrmGenericImporter *importer = new DrmGenericImporter(drm);
-  if (!importer)
-    return NULL;
-
-  int ret = importer->Init();
-  if (ret) {
-    ALOGE("Failed to initialize the nv importer %d", ret);
-    delete importer;
-    return NULL;
-  }
-  return importer;
-}
-#endif
-
-DrmGenericImporter::DrmGenericImporter(DrmDevice *drm)
-    : drm_(drm), exclude_non_hwfb_(false) {
-}
-
-DrmGenericImporter::~DrmGenericImporter() {
-}
-
-int DrmGenericImporter::Init() {
-  int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
-                          (const hw_module_t **)&gralloc_);
-  if (ret) {
-    ALOGE("Failed to open gralloc module");
-    return ret;
-  }
-
-  ALOGI("Using %s gralloc module: %s\n", gralloc_->common.name,
-        gralloc_->common.author);
-
-  char exclude_non_hwfb_prop[PROPERTY_VALUE_MAX];
-  property_get("hwc.drm.exclude_non_hwfb_imports", exclude_non_hwfb_prop, "0");
-  exclude_non_hwfb_ = static_cast<bool>(strncmp(exclude_non_hwfb_prop, "0", 1));
-
-  return 0;
-}
-
-uint32_t DrmGenericImporter::ConvertHalFormatToDrm(uint32_t hal_format) {
-  switch (hal_format) {
-    case HAL_PIXEL_FORMAT_RGB_888:
-      return DRM_FORMAT_BGR888;
-    case HAL_PIXEL_FORMAT_BGRA_8888:
-      return DRM_FORMAT_ARGB8888;
-    case HAL_PIXEL_FORMAT_RGBX_8888:
-      return DRM_FORMAT_XBGR8888;
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-      return DRM_FORMAT_ABGR8888;
-    case HAL_PIXEL_FORMAT_RGB_565:
-      return DRM_FORMAT_BGR565;
-    case HAL_PIXEL_FORMAT_YV12:
-      return DRM_FORMAT_YVU420;
-    default:
-      ALOGE("Cannot convert hal format to drm format %u", hal_format);
-      return DRM_FORMAT_INVALID;
-  }
-}
-
-uint32_t DrmGenericImporter::DrmFormatToBitsPerPixel(uint32_t drm_format) {
-  switch (drm_format) {
-    case DRM_FORMAT_ARGB8888:
-    case DRM_FORMAT_XBGR8888:
-    case DRM_FORMAT_ABGR8888:
-      return 32;
-    case DRM_FORMAT_BGR888:
-      return 24;
-    case DRM_FORMAT_BGR565:
-      return 16;
-    case DRM_FORMAT_YVU420:
-      return 12;
-    default:
-      ALOGE("Cannot convert hal format %u to bpp (returning 32)", drm_format);
-      return 32;
-  }
-}
-
-int DrmGenericImporter::ConvertBoInfo(buffer_handle_t handle,
-                                      hwc_drm_bo_t *bo) {
-  gralloc_handle_t *gr_handle = gralloc_handle(handle);
-  if (!gr_handle)
-    return -EINVAL;
-
-  bo->width = gr_handle->width;
-  bo->height = gr_handle->height;
-  bo->hal_format = gr_handle->format;
-  bo->format = ConvertHalFormatToDrm(gr_handle->format);
-  if (bo->format == DRM_FORMAT_INVALID)
-    return -EINVAL;
-  bo->usage = gr_handle->usage;
-  bo->pixel_stride = (gr_handle->stride * 8) /
-                     DrmFormatToBitsPerPixel(bo->format);
-  bo->prime_fds[0] = gr_handle->prime_fd;
-  bo->pitches[0] = gr_handle->stride;
-  bo->offsets[0] = 0;
-
-  return 0;
-}
-
-int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
-  memset(bo, 0, sizeof(hwc_drm_bo_t));
-
-  int ret = ConvertBoInfo(handle, bo);
-  if (ret)
-    return ret;
-
-  ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &bo->gem_handles[0]);
-  if (ret) {
-    ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret);
-    return ret;
-  }
-
-  for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
-    int fd = bo->prime_fds[i];
-    if (fd != 0) {
-      if (fd != bo->prime_fds[0]) {
-        ALOGE("Multiplanar FBs are not supported by this version of composer");
-        return -ENOTSUP;
-      }
-      bo->gem_handles[i] = bo->gem_handles[0];
-    }
-  }
-
-  if (!bo->with_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,
-                                     bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS
-                                                      : 0);
-
-  if (ret) {
-    ALOGE("could not create drm fb %d", ret);
-    return ret;
-  }
-
-  ImportHandle(bo->gem_handles[0]);
-
-  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 (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
-    if (!bo->gem_handles[i])
-      continue;
-
-    if (ReleaseHandle(bo->gem_handles[i])) {
-      ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
-    } else {
-      for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
-        if (bo->gem_handles[j] == bo->gem_handles[i])
-          bo->gem_handles[j] = 0;
-      bo->gem_handles[i] = 0;
-    }
-  }
-  return 0;
-}
-
-bool DrmGenericImporter::CanImportBuffer(buffer_handle_t handle) {
-  hwc_drm_bo_t bo;
-
-  int ret = ConvertBoInfo(handle, &bo);
-  if (ret)
-    return false;
-
-  if (bo.prime_fds[0] == 0)
-    return false;
-
-  if (exclude_non_hwfb_ && !(bo.usage & GRALLOC_USAGE_HW_FB))
-    return false;
-
-  return true;
-}
-
-#ifdef USE_DRM_GENERIC_IMPORTER
-std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
-  std::unique_ptr<Planner> planner(new Planner);
-  planner->AddStage<PlanStageGreedy>();
-  return planner;
-}
-#endif
-
-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;
-
-  memset(&gem_close, 0, sizeof(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;
-}
-}
diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp
deleted file mode 100644
index 1f1478f..0000000
--- a/platform/platformhisi.cpp
+++ /dev/null
@@ -1,197 +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.
- */
-
-#define LOG_TAG "hwc-platform-hisi"
-
-#include "platformhisi.h"
-#include "drmdevice.h"
-#include "platform.h"
-
-#include <stdatomic.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-#include <cinttypes>
-
-#include <hardware/gralloc.h>
-#include <log/log.h>
-#include "gralloc_priv.h"
-
-#define MALI_ALIGN(value, base) (((value) + ((base)-1)) & ~((base)-1))
-
-namespace android {
-
-Importer *Importer::CreateInstance(DrmDevice *drm) {
-  HisiImporter *importer = new HisiImporter(drm);
-  if (!importer)
-    return NULL;
-
-  int ret = importer->Init();
-  if (ret) {
-    ALOGE("Failed to initialize the hisi importer %d", ret);
-    delete importer;
-    return NULL;
-  }
-  return importer;
-}
-
-#if defined(MALI_GRALLOC_INTFMT_AFBC_BASIC) && \
-    defined(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16)
-uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t flags,
-                                                          bool is_rgb) {
-  uint64_t features = 0UL;
-
-  if (flags & MALI_GRALLOC_INTFMT_AFBC_BASIC)
-    features |= AFBC_FORMAT_MOD_BLOCK_SIZE_16x16;
-
-  if (flags & MALI_GRALLOC_INTFMT_AFBC_SPLITBLK)
-    features |= (AFBC_FORMAT_MOD_SPLIT | AFBC_FORMAT_MOD_SPARSE);
-
-  if (flags & MALI_GRALLOC_INTFMT_AFBC_WIDEBLK)
-    features |= AFBC_FORMAT_MOD_BLOCK_SIZE_32x8;
-
-  if (flags & MALI_GRALLOC_INTFMT_AFBC_TILED_HEADERS)
-    features |= AFBC_FORMAT_MOD_TILED;
-
-  if (features) {
-    if (is_rgb)
-      features |= AFBC_FORMAT_MOD_YTR;
-
-    return DRM_FORMAT_MOD_ARM_AFBC(features);
-  }
-
-  return 0;
-}
-#else
-uint64_t HisiImporter::ConvertGrallocFormatToDrmModifiers(uint64_t /* flags */,
-                                                          bool /* is_rgb */) {
-  return 0;
-}
-#endif
-
-bool HisiImporter::IsDrmFormatRgb(uint32_t drm_format) {
-  switch (drm_format) {
-    case DRM_FORMAT_ARGB8888:
-    case DRM_FORMAT_XBGR8888:
-    case DRM_FORMAT_ABGR8888:
-    case DRM_FORMAT_BGR888:
-    case DRM_FORMAT_BGR565:
-      return true;
-    case DRM_FORMAT_YVU420:
-      return false;
-    default:
-      ALOGV("Unsupported format %u assuming rgb?", drm_format);
-      return true;
-  }
-}
-
-int HisiImporter::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
-  bool is_rgb;
-
-  private_handle_t const *hnd = reinterpret_cast<private_handle_t const *>(
-      handle);
-  if (!hnd)
-    return -EINVAL;
-
-  if (!(hnd->usage & GRALLOC_USAGE_HW_FB))
-    return -EINVAL;
-
-  uint32_t fmt = ConvertHalFormatToDrm(hnd->req_format);
-  if (fmt == DRM_FORMAT_INVALID)
-    return -EINVAL;
-
-  is_rgb = HisiImporter::IsDrmFormatRgb(fmt);
-  bo->modifiers[0] = HisiImporter::
-      ConvertGrallocFormatToDrmModifiers(hnd->internal_format, is_rgb);
-
-  bo->width = hnd->width;
-  bo->height = hnd->height;
-  bo->hal_format = hnd->req_format;
-  bo->format = fmt;
-  bo->usage = hnd->usage;
-  bo->pixel_stride = hnd->stride;
-  bo->pitches[0] = hnd->byte_stride;
-  bo->prime_fds[0] = hnd->share_fd;
-  bo->offsets[0] = 0;
-
-  switch (fmt) {
-    case DRM_FORMAT_YVU420: {
-      int align = 128;
-      if (hnd->usage &
-          (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK))
-        align = 16;
-      int adjusted_height = MALI_ALIGN(hnd->height, 2);
-      int y_size = adjusted_height * hnd->byte_stride;
-      int vu_stride = MALI_ALIGN(hnd->byte_stride / 2, align);
-      int v_size = vu_stride * (adjusted_height / 2);
-
-      /* V plane*/
-      bo->prime_fds[1] = hnd->share_fd;
-      bo->pitches[1] = vu_stride;
-      bo->offsets[1] = y_size;
-      /* U plane */
-      bo->prime_fds[2] = hnd->share_fd;
-      bo->pitches[2] = vu_stride;
-      bo->offsets[2] = y_size + v_size;
-      break;
-    }
-    default:
-      break;
-  }
-
-  bo->with_modifiers = true;
-
-  return 0;
-}
-
-class PlanStageHiSi : public Planner::PlanStage {
- public:
-  int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition,
-                      std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
-                      std::vector<DrmPlane *> *planes) {
-    int layers_added = 0;
-    // Fill up as many DRM planes as we can with buffers that have HW_FB usage.
-    // Buffers without HW_FB should have been filtered out with
-    // CanImportBuffer(), if we meet one here, just skip it.
-    for (auto i = layers.begin(); i != layers.end(); i = layers.erase(i)) {
-      if (!(i->second->gralloc_buffer_usage & GRALLOC_USAGE_HW_FB))
-        continue;
-
-      int ret = Emplace(composition, planes, DrmCompositionPlane::Type::kLayer,
-                        crtc, std::make_pair(i->first, i->second));
-      layers_added++;
-      // We don't have any planes left
-      if (ret == -ENOENT)
-        break;
-      else if (ret) {
-        ALOGE("Failed to emplace layer %zu, dropping it", i->first);
-        return ret;
-      }
-    }
-    // If we didn't emplace anything, return an error to ensure we force client
-    // compositing.
-    if (!layers_added)
-      return -EINVAL;
-
-    return 0;
-  }
-};
-
-std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
-  std::unique_ptr<Planner> planner(new Planner);
-  planner->AddStage<PlanStageHiSi>();
-  return planner;
-}
-}  // namespace android
diff --git a/platform/platformimagination.cpp b/platform/platformimagination.cpp
deleted file mode 100644
index ea34ecc..0000000
--- a/platform/platformimagination.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#define LOG_TAG "hwc-platform-imagination"
-
-#include "platformimagination.h"
-#include <log/log.h>
-#include <xf86drm.h>
-
-#include "img_gralloc1_public.h"
-
-namespace android {
-
-Importer *Importer::CreateInstance(DrmDevice *drm) {
-  ImaginationImporter *importer = new ImaginationImporter(drm);
-  if (!importer)
-    return NULL;
-
-  int ret = importer->Init();
-  if (ret) {
-    ALOGE("Failed to initialize the Imagination importer %d", ret);
-    delete importer;
-    return NULL;
-  }
-  return importer;
-}
-
-int ImaginationImporter::ConvertBoInfo(buffer_handle_t handle,
-                                       hwc_drm_bo_t *bo) {
-  IMG_native_handle_t *hnd = (IMG_native_handle_t *)handle;
-  if (!hnd)
-    return -EINVAL;
-
-  /* Extra bits are responsible for buffer compression and memory layout */
-  if (hnd->iFormat & ~0x10f) {
-    ALOGV("Special buffer formats are not supported");
-    return -EINVAL;
-  }
-
-  bo->width = hnd->iWidth;
-  bo->height = hnd->iHeight;
-  bo->usage = hnd->usage;
-  bo->prime_fds[0] = hnd->fd[0];
-  bo->pitches[0] = ALIGN(hnd->iWidth, HW_ALIGN) * hnd->uiBpp >> 3;
-
-  switch (hnd->iFormat) {
-#ifdef HAL_PIXEL_FORMAT_BGRX_8888
-    case HAL_PIXEL_FORMAT_BGRX_8888:
-      bo->format = DRM_FORMAT_XRGB8888;
-      break;
-#endif
-    default:
-      bo->format = ConvertHalFormatToDrm(hnd->iFormat & 0xf);
-      if (bo->format == DRM_FORMAT_INVALID) {
-        ALOGV("Cannot convert hal format to drm format %u", hnd->iFormat);
-        return -EINVAL;
-      }
-  }
-
-  return 0;
-}
-
-std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
-  std::unique_ptr<Planner> planner(new Planner);
-  planner->AddStage<PlanStageGreedy>();
-  return planner;
-}
-}  // namespace android
diff --git a/platform/platformimagination.h b/platform/platformimagination.h
deleted file mode 100644
index f2a7cb7..0000000
--- a/platform/platformimagination.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef PLATFORMIMAGINATION_H
-#define PLATFORMIMAGINATION_H
-
-#include "drmdevice.h"
-#include "platform.h"
-#include "platformdrmgeneric.h"
-
-#include <stdatomic.h>
-
-#include <hardware/gralloc.h>
-
-namespace android {
-
-class ImaginationImporter : public DrmGenericImporter {
- public:
-  using DrmGenericImporter::DrmGenericImporter;
-
-  int ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
-};
-}  // namespace android
-
-#endif  // PLATFORMIMAGINATION_H
diff --git a/platform/platformminigbm.cpp b/platform/platformminigbm.cpp
deleted file mode 100644
index df195d3..0000000
--- a/platform/platformminigbm.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2018 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-minigbm"
-
-#include "platformminigbm.h"
-#include "drmdevice.h"
-#include "platform.h"
-
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-#include "cros_gralloc_handle.h"
-
-namespace android {
-
-Importer *Importer::CreateInstance(DrmDevice *drm) {
-  DrmMinigbmImporter *importer = new DrmMinigbmImporter(drm);
-  if (!importer)
-    return NULL;
-
-  int ret = importer->Init();
-  if (ret) {
-    ALOGE("Failed to initialize the minigbm importer %d", ret);
-    delete importer;
-    return NULL;
-  }
-  return importer;
-}
-
-int DrmMinigbmImporter::ConvertBoInfo(buffer_handle_t handle,
-                                      hwc_drm_bo_t *bo) {
-  cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle;
-  if (!gr_handle)
-    return -EINVAL;
-
-  bo->width = gr_handle->width;
-  bo->height = gr_handle->height;
-  bo->hal_format = gr_handle->droid_format;
-  bo->format = gr_handle->format;
-  bo->usage = gr_handle->usage;
-  bo->pixel_stride = gr_handle->pixel_stride;
-  bo->prime_fds[0] = gr_handle->fds[0];
-  bo->pitches[0] = gr_handle->strides[0];
-  bo->offsets[0] = gr_handle->offsets[0];
-
-  return 0;
-}
-
-std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
-  std::unique_ptr<Planner> planner(new Planner);
-  planner->AddStage<PlanStageGreedy>();
-  return planner;
-}
-
-}  // namespace android
diff --git a/tests/Android.bp b/tests/Android.bp
index 7e550ff..6ffb364 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1,5 +1,14 @@
 
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "external_drm_hwcomposer_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["external_drm_hwcomposer_license"],
+}
+
 cc_test {
     name: "hwc-drm-tests",
 
@@ -9,5 +18,8 @@
     header_libs: ["libhardware_headers"],
     static_libs: ["libdrmhwc_utils"],
     shared_libs: ["hwcomposer.drm"],
-    include_dirs: ["external/drm_hwcomposer/include"],
+    include_dirs: [
+        "external/drm_hwcomposer/include",
+        "external/drm_hwcomposer",
+    ],
 }
diff --git a/tests/worker_test.cpp b/tests/worker_test.cpp
index 82523f0..cb6275e 100644
--- a/tests/worker_test.cpp
+++ b/tests/worker_test.cpp
@@ -1,10 +1,10 @@
+#include "utils/Worker.h"
+
 #include <gtest/gtest.h>
 #include <hardware/hardware.h>
 
 #include <chrono>
 
-#include "worker.h"
-
 using android::Worker;
 
 struct TestWorker : public Worker {
diff --git a/utils/worker.cpp b/utils/Worker.cpp
similarity index 99%
rename from utils/worker.cpp
rename to utils/Worker.cpp
index 0dceb16..1f30588 100644
--- a/utils/worker.cpp
+++ b/utils/Worker.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "worker.h"
+#include "Worker.h"
 
 #include <sys/prctl.h>
 #include <sys/resource.h>
diff --git a/include/worker.h b/utils/Worker.h
similarity index 99%
rename from include/worker.h
rename to utils/Worker.h
index 7909038..73a80da 100644
--- a/include/worker.h
+++ b/utils/Worker.h
@@ -19,10 +19,10 @@
 
 #include <stdint.h>
 #include <stdlib.h>
-#include <string>
 
 #include <condition_variable>
 #include <mutex>
+#include <string>
 #include <thread>
 
 namespace android {
diff --git a/include/autolock.h b/utils/autolock.h
similarity index 100%
rename from include/autolock.h
rename to utils/autolock.h
diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp
index 87e3c42..322efce 100644
--- a/utils/hwcutils.cpp
+++ b/utils/hwcutils.cpp
@@ -17,12 +17,14 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #define LOG_TAG "hwc-drm-utils"
 
-#include "drmhwcomposer.h"
-#include "platform.h"
-
 #include <log/log.h>
+#include <ui/Gralloc.h>
 #include <ui/GraphicBufferMapper.h>
 
+#include "bufferinfo/BufferInfoGetter.h"
+#include "drm/DrmGenericImporter.h"
+#include "drmhwcomposer.h"
+
 #define UNUSED(x) (void)(x)
 
 namespace android {
@@ -44,11 +46,19 @@
 }
 
 int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
-  hwc_drm_bo tmp_bo;
+  hwc_drm_bo tmp_bo{};
 
-  int ret = importer->ImportBuffer(handle, &tmp_bo);
-  if (ret)
+  int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo);
+  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;
+  }
 
   if (importer_ != NULL) {
     importer_->ReleaseBuffer(&bo_);
@@ -61,25 +71,15 @@
   return 0;
 }
 
-int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width,
-                                         int height, int layerCount, int format,
-                                         int usage, int stride) {
+int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle) {
   native_handle_t *handle_copy;
   GraphicBufferMapper &gm(GraphicBufferMapper::get());
   int ret;
 
-#ifdef HWC2_USE_OLD_GB_IMPORT
-  UNUSED(width);
-  UNUSED(height);
-  UNUSED(layerCount);
-  UNUSED(format);
-  UNUSED(usage);
-  UNUSED(stride);
-  ret = gm.importBuffer(handle, const_cast<buffer_handle_t *>(&handle_copy));
-#else
-  ret = gm.importBuffer(handle, width, height, layerCount, format, usage,
-                        stride, const_cast<buffer_handle_t *>(&handle_copy));
-#endif
+  ret = gm.getGrallocMapper().importBuffer(handle,
+                                           const_cast<buffer_handle_t *>(
+                                               &handle_copy));
+
   if (ret) {
     ALOGE("Failed to import buffer handle %d", ret);
     return ret;
@@ -114,13 +114,7 @@
 
   const hwc_drm_bo *bo = buffer.operator->();
 
-  unsigned int layer_count;
-  for (layer_count = 0; layer_count < HWC_DRM_BO_MAX_PLANES; ++layer_count)
-    if (bo->gem_handles[layer_count] == 0)
-      break;
-
-  ret = handle.CopyBufferHandle(sf_handle, bo->width, bo->height, layer_count,
-                                bo->hal_format, bo->usage, bo->pixel_stride);
+  ret = handle.CopyBufferHandle(sf_handle);
   if (ret)
     return ret;