Merge "drm_hwcomposer: remove unnecessary gralloc_drm_bo_t dependency"
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index 3c94e6b..3ab934d 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -32,7 +32,7 @@
 
 namespace android {
 
-struct SquashState;
+class SquashState;
 
 enum DrmCompositionType {
   DRM_COMPOSITION_TYPE_EMPTY,
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 3d39f6e..a81d6cc 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "hwcomposer-drm"
 
 #include "drmhwcomposer.h"
+#include "drmeventlistener.h"
 #include "drmresources.h"
 #include "importer.h"
 #include "virtualcompositorworker.h"
@@ -25,6 +26,7 @@
 
 #include <stdlib.h>
 
+#include <cinttypes>
 #include <map>
 #include <vector>
 #include <sstream>
@@ -124,6 +126,62 @@
   VSyncWorker vsync_worker;
 } hwc_drm_display_t;
 
+class DrmHotplugHandler : public DrmEventHandler {
+ public:
+  void Init(DrmResources *drm, const struct hwc_procs *procs) {
+    drm_ = drm;
+    procs_ = procs;
+  }
+
+  void HandleEvent(uint64_t timestamp_us) {
+    for (auto &conn : drm_->connectors()) {
+      drmModeConnection old_state = conn->state();
+
+      conn->UpdateModes();
+
+      drmModeConnection cur_state = conn->state();
+
+      if (cur_state == old_state)
+        continue;
+
+      ALOGI("%s event @%" PRIu64 " for connector %u\n",
+            cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
+            conn->id());
+
+      if (cur_state == DRM_MODE_CONNECTED) {
+        // Take the first one, then look for the preferred
+        DrmMode mode = *(conn->modes().begin());
+        for (auto &m : conn->modes()) {
+          if (m.type() & DRM_MODE_TYPE_PREFERRED) {
+            mode = m;
+            break;
+          }
+        }
+        ALOGI("Setting mode %dx%d for connector %d\n", mode.h_display(),
+              mode.v_display(), conn->id());
+        int ret = drm_->SetDisplayActiveMode(conn->display(), mode);
+        if (ret) {
+          ALOGE("Failed to set active config %d", ret);
+          return;
+        }
+      } else {
+        int ret = drm_->SetDpmsMode(conn->display(), DRM_MODE_DPMS_OFF);
+        if (ret) {
+          ALOGE("Failed to set dpms mode off %d", ret);
+          return;
+        }
+      }
+
+      procs_->hotplug(procs_, conn->display(),
+                      cur_state == DRM_MODE_CONNECTED ? 1 : 0);
+    }
+  }
+
+ private:
+  DrmResources *drm_ = NULL;
+  const struct hwc_procs *procs_ = NULL;
+};
+
 struct hwc_context_t {
   // map of display:hwc_drm_display_t
   typedef std::map<int, hwc_drm_display_t> DisplayMap;
@@ -141,6 +199,7 @@
   const gralloc_module_t *gralloc;
   DummySwSyncTimeline dummy_timeline;
   VirtualCompositorWorker virtual_compositor_worker;
+  DrmHotplugHandler hotplug_handler;
 };
 
 static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
@@ -626,6 +685,9 @@
 
   for (std::pair<const int, hwc_drm_display> &display_entry : ctx->displays)
     display_entry.second.vsync_worker.SetProcs(procs);
+
+  ctx->hotplug_handler.Init(&ctx->drm, procs);
+  ctx->drm.event_listener()->RegisterHotplugHandler(&ctx->hotplug_handler);
 }
 
 static int hwc_get_display_configs(struct hwc_composer_device_1 *dev,
@@ -742,6 +804,10 @@
     ALOGE("Failed to get connector for display %d", display);
     return -ENODEV;
   }
+
+  if (c->state() != DRM_MODE_CONNECTED)
+    return -ENODEV;
+
   DrmMode mode;
   for (const DrmMode &conn_mode : c->modes()) {
     if (conn_mode.id() == hd->config_ids[index]) {
@@ -758,6 +824,11 @@
     ALOGE("Failed to set active config %d", ret);
     return ret;
   }
+  ret = ctx->drm.SetDpmsMode(display, DRM_MODE_DPMS_ON);
+  if (ret) {
+    ALOGE("Failed to set dpms mode on %d", ret);
+    return ret;
+  }
   return ret;
 }
 
@@ -897,19 +968,19 @@
 }
 
 static struct hw_module_methods_t hwc_module_methods = {
-  open : android::hwc_device_open
+  .open = android::hwc_device_open
 };
 
 hwc_module_t HAL_MODULE_INFO_SYM = {
-  common : {
-    tag : HARDWARE_MODULE_TAG,
-    version_major : 1,
-    version_minor : 0,
-    id : HWC_HARDWARE_MODULE_ID,
-    name : "DRM hwcomposer module",
-    author : "The Android Open Source Project",
-    methods : &hwc_module_methods,
-    dso : NULL,
-    reserved : {0},
+  .common = {
+    .tag = HARDWARE_MODULE_TAG,
+    .version_major = 1,
+    .version_minor = 0,
+    .id = HWC_HARDWARE_MODULE_ID,
+    .name = "DRM hwcomposer module",
+    .author = "The Android Open Source Project",
+    .methods = &hwc_module_methods,
+    .dso = NULL,
+    .reserved = {0},
   }
 };
diff --git a/nvimporter.cpp b/nvimporter.cpp
index d5c3abc..febcb4f 100644
--- a/nvimporter.cpp
+++ b/nvimporter.cpp
@@ -20,6 +20,7 @@
 #include "importer.h"
 #include "nvimporter.h"
 
+#include <cinttypes>
 #include <stdatomic.h>
 #include <xf86drm.h>
 #include <xf86drmMode.h>
@@ -124,7 +125,7 @@
 int NvImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
   NvBuffer_t *buf = (NvBuffer_t *)bo->priv;
   if (!buf) {
-    ALOGE("Freeing bo %ld, buf is NULL!", bo->fb_id);
+    ALOGE("Freeing bo %" PRIu32 ", buf is NULL!", bo->fb_id);
     return 0;
   }
   if (atomic_fetch_sub(&buf->ref, 1) > 1)