drm_hwcomposer: Make uevent listener standalone

1. DRM event listener doesn't work in this conditions, uevent blocks
   the thread and non-blocking select() doesn't make any sense.
   Remove DRM event handling for now.

2. UEvent listeren is common for all DrmDevices, therefore put it into
   ResourceManager class.

Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/.ci/.common.sh b/.ci/.common.sh
index 21c2b28..d9b5b3c 100644
--- a/.ci/.common.sh
+++ b/.ci/.common.sh
@@ -27,13 +27,13 @@
 drm/DrmCrtc.cpp
 drm/DrmDevice.cpp
 drm/DrmEncoder.cpp
-drm/DrmEventListener.cpp
 drm/DrmFbImporter.cpp
 drm/DrmMode.cpp
 drm/DrmPlane.cpp
 drm/DrmProperty.cpp
 DrmHwcTwo.cpp
 drm/ResourceManager.cpp
+drm/UEventListener.cpp
 drm/VSyncWorker.cpp
 tests/worker_test.cpp
 utils/autolock.cpp
diff --git a/Android.bp b/Android.bp
index ddf66fb..eba92f8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,12 +95,12 @@
         "drm/DrmCrtc.cpp",
         "drm/DrmDevice.cpp",
         "drm/DrmEncoder.cpp",
-        "drm/DrmEventListener.cpp",
         "drm/DrmFbImporter.cpp",
         "drm/DrmMode.cpp",
         "drm/DrmPlane.cpp",
         "drm/DrmProperty.cpp",
         "drm/ResourceManager.cpp",
+        "drm/UEventListener.cpp",
         "drm/VSyncWorker.cpp",
 
         "utils/autolock.cpp",
diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp
index 1f1e594..8b8068c 100644
--- a/DrmHwcTwo.cpp
+++ b/DrmHwcTwo.cpp
@@ -87,11 +87,9 @@
     }
   }
 
-  const auto &drm_devices = resource_manager_.getDrmDevices();
-  for (const auto &device : drm_devices) {
-    // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
-    device->RegisterHotplugHandler(new DrmHotplugHandler(this, device.get()));
-  }
+  resource_manager_.GetUEventListener()->RegisterHotplugHandler(
+      [this] { HandleHotplugUEvent(); });
+
   return ret;
 }
 
@@ -1263,30 +1261,32 @@
   }
 }
 
-void DrmHwcTwo::DrmHotplugHandler::HandleEvent(uint64_t timestamp_us) {
-  for (const auto &conn : drm_->connectors()) {
-    drmModeConnection old_state = conn->state();
-    drmModeConnection cur_state = conn->UpdateModes()
-                                      ? DRM_MODE_UNKNOWNCONNECTION
-                                      : conn->state();
+void DrmHwcTwo::HandleHotplugUEvent() {
+  for (const auto &drm : resource_manager_.getDrmDevices()) {
+    for (const auto &conn : drm->connectors()) {
+      drmModeConnection old_state = conn->state();
+      drmModeConnection cur_state = conn->UpdateModes()
+                                        ? DRM_MODE_UNKNOWNCONNECTION
+                                        : conn->state();
 
-    if (cur_state == old_state)
-      continue;
+      if (cur_state == old_state)
+        continue;
 
-    ALOGI("%s event @%" PRIu64 " for connector %u on display %d",
-          cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", timestamp_us,
-          conn->id(), conn->display());
+      ALOGI("%s event for connector %u on display %d",
+            cur_state == DRM_MODE_CONNECTED ? "Plug" : "Unplug", conn->id(),
+            conn->display());
 
-    int display_id = conn->display();
-    if (cur_state == DRM_MODE_CONNECTED) {
-      auto &display = hwc2_->displays_.at(display_id);
-      display.ChosePreferredConfig();
-    } else {
-      auto &display = hwc2_->displays_.at(display_id);
-      display.ClearDisplay();
+      int display_id = conn->display();
+      if (cur_state == DRM_MODE_CONNECTED) {
+        auto &display = displays_.at(display_id);
+        display.ChosePreferredConfig();
+      } else {
+        auto &display = displays_.at(display_id);
+        display.ClearDisplay();
+      }
+
+      HandleDisplayHotplug(display_id, cur_state);
     }
-
-    hwc2_->HandleDisplayHotplug(display_id, cur_state);
   }
 }
 
diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h
index 974c0a8..ed547c0 100644
--- a/DrmHwcTwo.h
+++ b/DrmHwcTwo.h
@@ -359,18 +359,6 @@
     std::string DumpDelta(DrmHwcTwo::HwcDisplay::Stats delta);
   };
 
-  class DrmHotplugHandler : public DrmEventHandler {
-   public:
-    DrmHotplugHandler(DrmHwcTwo *hwc2, DrmDevice *drm)
-        : hwc2_(hwc2), drm_(drm) {
-    }
-    void HandleEvent(uint64_t timestamp_us);
-
-   private:
-    DrmHwcTwo *hwc2_;
-    DrmDevice *drm_;
-  };
-
  private:
   static DrmHwcTwo *toDrmHwcTwo(hwc2_device_t *dev) {
     return static_cast<DrmHwcTwo *>(dev);
@@ -439,6 +427,8 @@
   void HandleDisplayHotplug(hwc2_display_t displayid, int state);
   void HandleInitialHotplugState(DrmDevice *drmDevice);
 
+  void HandleHotplugUEvent();
+
   ResourceManager resource_manager_;
   std::map<hwc2_display_t, HwcDisplay> displays_;
 
diff --git a/bufferinfo/legacy/BufferInfoImagination.cpp b/bufferinfo/legacy/BufferInfoImagination.cpp
index d646072..691dd14 100644
--- a/bufferinfo/legacy/BufferInfoImagination.cpp
+++ b/bufferinfo/legacy/BufferInfoImagination.cpp
@@ -20,6 +20,8 @@
 
 #include <xf86drm.h>
 
+#include <cerrno>
+
 #include "img_gralloc1_public.h"
 #include "utils/log.h"
 
diff --git a/bufferinfo/legacy/BufferInfoLibdrm.cpp b/bufferinfo/legacy/BufferInfoLibdrm.cpp
index da89eb5..6243d8d 100644
--- a/bufferinfo/legacy/BufferInfoLibdrm.cpp
+++ b/bufferinfo/legacy/BufferInfoLibdrm.cpp
@@ -23,6 +23,8 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
+#include <mutex>
+
 #include "utils/log.h"
 #include "utils/properties.h"
 
diff --git a/bufferinfo/legacy/BufferInfoMinigbm.cpp b/bufferinfo/legacy/BufferInfoMinigbm.cpp
index d030dff..1657ea6 100644
--- a/bufferinfo/legacy/BufferInfoMinigbm.cpp
+++ b/bufferinfo/legacy/BufferInfoMinigbm.cpp
@@ -21,6 +21,8 @@
 #include <xf86drm.h>
 #include <xf86drmMode.h>
 
+#include <cerrno>
+
 #include "cros_gralloc_handle.h"
 #include "utils/log.h"
 
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index 1753ddc..0f5f581 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -111,15 +111,11 @@
   return primary_candidates;
 }
 
-DrmDevice::DrmDevice() : event_listener_(this) {
+DrmDevice::DrmDevice() {
   self.reset(this);
   mDrmFbImporter = std::make_unique<DrmFbImporter>(self);
 }
 
-DrmDevice::~DrmDevice() {
-  event_listener_.Exit();
-}
-
 std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) {
   /* TODO: Use drmOpenControl here instead */
   fd_ = UniqueFd(open(path, O_RDWR | O_CLOEXEC));
@@ -326,12 +322,6 @@
   if (ret)
     return std::make_tuple(ret, 0);
 
-  ret = event_listener_.Init();
-  if (ret) {
-    ALOGE("Can't initialize event listener %d", ret);
-    return std::make_tuple(ret, 0);
-  }
-
   for (auto &conn : connectors_) {
     ret = CreateDisplayPipe(conn.get());
     if (ret) {
@@ -526,10 +516,6 @@
       });
 }
 
-DrmEventListener *DrmDevice::event_listener() {
-  return &event_listener_;
-}
-
 int DrmDevice::GetProperty(uint32_t obj_id, uint32_t obj_type,
                            const char *prop_name, DrmProperty *property) const {
   drmModeObjectPropertiesPtr props = nullptr;
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index 81c60cd..c08c766 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -25,7 +25,6 @@
 #include "DrmConnector.h"
 #include "DrmCrtc.h"
 #include "DrmEncoder.h"
-#include "DrmEventListener.h"
 #include "DrmFbImporter.h"
 #include "DrmPlane.h"
 #include "utils/UniqueFd.h"
@@ -38,7 +37,7 @@
 class DrmDevice {
  public:
   DrmDevice();
-  ~DrmDevice();
+  ~DrmDevice() = default;
 
   std::tuple<int, int> Init(const char *path, int num_displays);
 
@@ -67,7 +66,6 @@
   DrmConnector *AvailableWritebackConnector(int display) const;
   DrmCrtc *GetCrtcForDisplay(int display) const;
   DrmPlane *GetPlane(uint32_t id) const;
-  DrmEventListener *event_listener();
 
   int GetCrtcProperty(const DrmCrtc &crtc, const char *prop_name,
                       DrmProperty *property) const;
@@ -83,9 +81,6 @@
       -> DrmModeUserPropertyBlobUnique;
 
   bool HandlesDisplay(int display) const;
-  void RegisterHotplugHandler(DrmEventHandler *handler) {
-    event_listener_.RegisterHotplugHandler(handler);
-  }
 
   bool HasAddFb2ModifiersSupport() const {
     return HasAddFb2ModifiersSupport_;
@@ -114,7 +109,6 @@
   std::vector<std::unique_ptr<DrmEncoder>> encoders_;
   std::vector<std::unique_ptr<DrmCrtc>> crtcs_;
   std::vector<std::unique_ptr<DrmPlane>> planes_;
-  DrmEventListener event_listener_;
 
   std::pair<uint32_t, uint32_t> min_resolution_;
   std::pair<uint32_t, uint32_t> max_resolution_;
diff --git a/drm/DrmEventListener.cpp b/drm/DrmEventListener.cpp
deleted file mode 100644
index 53e7032..0000000
--- a/drm/DrmEventListener.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2016 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-drm-event-listener"
-
-#include "DrmEventListener.h"
-
-#include <linux/netlink.h>
-#include <sys/socket.h>
-#include <xf86drm.h>
-
-#include <cassert>
-#include <cerrno>
-#include <cstring>
-
-#include "DrmDevice.h"
-#include "utils/log.h"
-
-/* Originally defined in system/core/libsystem/include/system/graphics.h */
-#define HAL_PRIORITY_URGENT_DISPLAY (-8)
-
-namespace android {
-
-DrmEventListener::DrmEventListener(DrmDevice *drm)
-    : Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY), drm_(drm) {
-}
-
-int DrmEventListener::Init() {
-  uevent_fd_ = UniqueFd(
-      socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
-  if (!uevent_fd_) {
-    ALOGE("Failed to open uevent socket: %s", strerror(errno));
-    return -errno;
-  }
-
-  struct sockaddr_nl addr {};
-  addr.nl_family = AF_NETLINK;
-  addr.nl_pid = 0;
-  addr.nl_groups = 0xFFFFFFFF;
-
-  int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr));
-  if (ret) {
-    ALOGE("Failed to bind uevent socket: %s", strerror(errno));
-    return -errno;
-  }
-
-  // NOLINTNEXTLINE(readability-isolate-declaration)
-  FD_ZERO(&fds_);
-  FD_SET(drm_->fd(), &fds_);
-  FD_SET(uevent_fd_.Get(), &fds_);
-  max_fd_ = std::max(drm_->fd(), uevent_fd_.Get());
-
-  return InitWorker();
-}
-
-void DrmEventListener::RegisterHotplugHandler(DrmEventHandler *handler) {
-  assert(!hotplug_handler_);
-  hotplug_handler_.reset(handler);
-}
-
-void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */,
-                                   unsigned int tv_sec, unsigned int tv_usec,
-                                   void *user_data) {
-  auto *handler = (DrmEventHandler *)user_data;
-  if (!handler)
-    return;
-
-  handler->HandleEvent((uint64_t)tv_sec * 1000 * 1000 + tv_usec);
-  delete handler;  // NOLINT(cppcoreguidelines-owning-memory)
-}
-
-void DrmEventListener::UEventHandler() {
-  char buffer[1024];
-  ssize_t ret = 0;
-
-  struct timespec ts {};
-
-  uint64_t timestamp = 0;
-  ret = clock_gettime(CLOCK_MONOTONIC, &ts);
-  if (!ret)
-    timestamp = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
-  else
-    ALOGE("Failed to get monotonic clock on hotplug %zd", ret);
-
-  while (true) {
-    ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
-    if (ret == 0)
-      return;
-
-    if (ret < 0) {
-      ALOGE("Got error reading uevent %zd", ret);
-      return;
-    }
-
-    if (!hotplug_handler_)
-      continue;
-
-    bool drm_event = false;
-    bool hotplug_event = false;
-    for (uint32_t i = 0; i < ret;) {
-      char *event = buffer + i;
-      if (strcmp(event, "DEVTYPE=drm_minor") != 0)
-        drm_event = true;
-      else if (strcmp(event, "HOTPLUG=1") != 0)
-        hotplug_event = true;
-
-      i += strlen(event) + 1;
-    }
-
-    if (drm_event && hotplug_event)
-      hotplug_handler_->HandleEvent(timestamp);
-  }
-}
-
-void DrmEventListener::Routine() {
-  int ret = 0;
-  do {
-    ret = select(max_fd_ + 1, &fds_, nullptr, nullptr, nullptr);
-  } while (ret == -1 && errno == EINTR);
-
-  if (FD_ISSET(drm_->fd(), &fds_)) {
-    drmEventContext event_context =
-        {.version = 2,
-         .vblank_handler = nullptr,
-         .page_flip_handler = DrmEventListener::FlipHandler};
-    drmHandleEvent(drm_->fd(), &event_context);
-  }
-
-  if (FD_ISSET(uevent_fd_.Get(), &fds_))
-    UEventHandler();
-}
-}  // namespace android
diff --git a/drm/DrmEventListener.h b/drm/DrmEventListener.h
deleted file mode 100644
index f1f7310..0000000
--- a/drm/DrmEventListener.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2016 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_DRM_EVENT_LISTENER_H_
-#define ANDROID_DRM_EVENT_LISTENER_H_
-
-#include "utils/UniqueFd.h"
-#include "utils/Worker.h"
-
-namespace android {
-
-class DrmDevice;
-
-class DrmEventHandler {
- public:
-  DrmEventHandler() {
-  }
-  virtual ~DrmEventHandler() {
-  }
-
-  virtual void HandleEvent(uint64_t timestamp_us) = 0;
-};
-
-class DrmEventListener : public Worker {
- public:
-  DrmEventListener(DrmDevice *drm);
-  virtual ~DrmEventListener() {
-  }
-
-  int Init();
-
-  void RegisterHotplugHandler(DrmEventHandler *handler);
-
-  static void FlipHandler(int fd, unsigned int sequence, unsigned int tv_sec,
-                          unsigned int tv_usec, void *user_data);
-
- protected:
-  virtual void Routine();
-
- private:
-  void UEventHandler();
-
-  fd_set fds_{};
-  UniqueFd uevent_fd_;
-  int max_fd_ = -1;
-
-  DrmDevice *drm_;
-  std::unique_ptr<DrmEventHandler> hotplug_handler_;
-};
-}  // namespace android
-
-#endif
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index c55d6b8..8baa4cb 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -70,6 +70,12 @@
     return -EINVAL;
   }
 
+  ret = uevent_listener_.Init();
+  if (ret) {
+    ALOGE("Can't initialize event listener %d", ret);
+    return ret;
+  }
+
   return 0;
 }
 
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index d9e0712..5ffe92c 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include "DrmDevice.h"
+#include "UEventListener.h"
 #include "DrmFbImporter.h"
 
 namespace android {
@@ -29,6 +30,10 @@
   ResourceManager();
   ResourceManager(const ResourceManager &) = delete;
   ResourceManager &operator=(const ResourceManager &) = delete;
+  ~ResourceManager() {
+    uevent_listener_.Exit();
+  }
+
   int Init();
   DrmDevice *GetDrmDevice(int display);
   const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const {
@@ -41,6 +46,10 @@
     return scale_with_gpu_;
   }
 
+  UEventListener *GetUEventListener() {
+    return &uevent_listener_;
+  }
+
  private:
   int AddDrmDevice(std::string const &path);
 
@@ -48,6 +57,8 @@
   std::vector<std::unique_ptr<DrmDevice>> drms_;
 
   bool scale_with_gpu_{};
+
+  UEventListener uevent_listener_;
 };
 }  // namespace android
 
diff --git a/drm/UEventListener.cpp b/drm/UEventListener.cpp
new file mode 100644
index 0000000..eae0608
--- /dev/null
+++ b/drm/UEventListener.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2016 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-uevent-listener"
+
+#include "UEventListener.h"
+
+#include <linux/netlink.h>
+#include <sys/socket.h>
+#include <xf86drm.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+
+#include "utils/log.h"
+
+/* Originally defined in system/core/libsystem/include/system/graphics.h */
+#define HAL_PRIORITY_URGENT_DISPLAY (-8)
+
+namespace android {
+
+UEventListener::UEventListener()
+    : Worker("uevent-listener", HAL_PRIORITY_URGENT_DISPLAY){};
+
+int UEventListener::Init() {
+  uevent_fd_ = UniqueFd(
+      socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
+  if (!uevent_fd_) {
+    ALOGE("Failed to open uevent socket: %s", strerror(errno));
+    return -errno;
+  }
+
+  struct sockaddr_nl addr {};
+  addr.nl_family = AF_NETLINK;
+  addr.nl_pid = 0;
+  addr.nl_groups = 0xFFFFFFFF;
+
+  int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr));
+  if (ret) {
+    ALOGE("Failed to bind uevent socket: %s", strerror(errno));
+    return -errno;
+  }
+
+  return InitWorker();
+}
+
+void UEventListener::Routine() {
+  char buffer[1024];
+  ssize_t ret = 0;
+
+  while (true) {
+    ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
+    if (ret == 0)
+      return;
+
+    if (ret < 0) {
+      ALOGE("Got error reading uevent %zd", ret);
+      return;
+    }
+
+    if (!hotplug_handler_)
+      continue;
+
+    bool drm_event = false;
+    bool hotplug_event = false;
+    for (uint32_t i = 0; i < ret;) {
+      char *event = buffer + i;
+      if (strcmp(event, "DEVTYPE=drm_minor") != 0)
+        drm_event = true;
+      else if (strcmp(event, "HOTPLUG=1") != 0)
+        hotplug_event = true;
+
+      i += strlen(event) + 1;
+    }
+
+    if (drm_event && hotplug_event && hotplug_handler_) {
+      hotplug_handler_();
+    }
+  }
+}
+}  // namespace android
diff --git a/drm/UEventListener.h b/drm/UEventListener.h
new file mode 100644
index 0000000..048eb40
--- /dev/null
+++ b/drm/UEventListener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 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_UEVENT_LISTENER_H_
+#define ANDROID_UEVENT_LISTENER_H_
+
+#include <functional>
+
+#include "utils/UniqueFd.h"
+#include "utils/Worker.h"
+
+namespace android {
+
+class UEventListener : public Worker {
+ public:
+  UEventListener();
+  virtual ~UEventListener() = default;
+
+  int Init();
+
+  void RegisterHotplugHandler(std::function<void()> hotplug_handler) {
+    hotplug_handler_ = hotplug_handler;
+  }
+
+ protected:
+  virtual void Routine();
+
+ private:
+  UniqueFd uevent_fd_;
+
+  std::function<void()> hotplug_handler_;
+};
+}  // namespace android
+
+#endif