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/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