diff options
author | Sean Paul <seanpaul@chromium.org> | 2015-07-28 14:15:42 -0400 |
---|---|---|
committer | Sean Paul <seanpaul@chromium.org> | 2016-04-01 12:15:23 -0400 |
commit | 3b1c03ab6613789254e0406f015b05ebbe1383ea (patch) | |
tree | 06968556c238f50155fef0669965b9658e7547f5 | |
parent | 4248d744d3be0fdd1233ef620678b581af56468f (diff) | |
download | drm_hwcomposer-3b1c03ab6613789254e0406f015b05ebbe1383ea.tar.gz |
DO NOT MERGE: drm_hwcomposer: Add DrmEventListener worker
This patch adds a worker which listens to drm events. If the
drm event has a handler associated with it, the listener will
call the handler.
BUG=chrome-os-partner:41682
TEST=Tested on ryu with DP
Change-Id: I5d691d191425604766a00be3e72111095d025d06
Signed-off-by: Sean Paul <seanpaul@chromium.org>
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | drmeventlistener.cpp | 135 | ||||
-rw-r--r-- | drmeventlistener.h | 65 | ||||
-rw-r--r-- | drmresources.cpp | 17 | ||||
-rw-r--r-- | drmresources.h | 4 |
5 files changed, 221 insertions, 1 deletions
@@ -47,6 +47,7 @@ LOCAL_SRC_FILES := \ drmdisplaycomposition.cpp \ drmdisplaycompositor.cpp \ drmencoder.cpp \ + drmeventlistener.cpp \ drmmode.cpp \ drmplane.cpp \ drmproperty.cpp \ diff --git a/drmeventlistener.cpp b/drmeventlistener.cpp new file mode 100644 index 0000000..b3e2328 --- /dev/null +++ b/drmeventlistener.cpp @@ -0,0 +1,135 @@ +/* + * 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 "drmresources.h" + +#include <linux/netlink.h> +#include <sys/socket.h> + +#include <cutils/log.h> +#include <xf86drm.h> + +namespace android { + +DrmEventListener::DrmEventListener(DrmResources *drm) + : Worker("drm-event-listener", HAL_PRIORITY_URGENT_DISPLAY), + drm_(drm) { +} + +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()); + return uevent_fd_.get(); + } + + struct sockaddr_nl addr; + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + addr.nl_pid = getpid(); + addr.nl_groups = 0xFFFFFFFF; + + int ret = bind(uevent_fd_.get(), (struct sockaddr *)&addr, sizeof(addr)); + if (ret) { + ALOGE("Failed to bind uevent socket %d", -errno); + return -errno; + } + + 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_ = handler; +} + +void DrmEventListener::FlipHandler(int /* fd */, unsigned int /* sequence */, + unsigned int tv_sec, unsigned int tv_usec, + void *user_data) { + DrmEventHandler *handler = (DrmEventHandler *)user_data; + if (!handler) + return; + + handler->HandleEvent((uint64_t)tv_sec * 1000 * 1000 + tv_usec); + delete handler; +} + +void DrmEventListener::UEventHandler() { + char buffer[1024]; + int ret; + + 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 %d", ret); + + while (true) { + ret = read(uevent_fd_.get(), &buffer, sizeof(buffer)); + if (ret == 0) { + return; + } else if (ret < 0) { + ALOGE("Got error reading uevent %d", ret); + return; + } + + if (!hotplug_handler_) + continue; + + bool drm_event = false, hotplug_event = false; + for (int i = 0; i < ret;) { + char *event = buffer + i; + if (strcmp(event, "DEVTYPE=drm_minor")) + drm_event = true; + else if (strcmp(event, "HOTPLUG=1")) + hotplug_event = true; + + i += strlen(event) + 1; + } + + if (drm_event && hotplug_event) + hotplug_handler_->HandleEvent(timestamp); + } +} + +void DrmEventListener::Routine() { + int ret; + do { + ret = select(max_fd_ + 1, &fds_, NULL, NULL, NULL); + } while (ret == -1 && errno == EINTR); + + if (FD_ISSET(drm_->fd(), &fds_)) { + drmEventContext event_context = { + .version = DRM_EVENT_CONTEXT_VERSION, + .vblank_handler = NULL, + .page_flip_handler = DrmEventListener::FlipHandler}; + drmHandleEvent(drm_->fd(), &event_context); + } + + if (FD_ISSET(uevent_fd_.get(), &fds_)) + UEventHandler(); +} +} diff --git a/drmeventlistener.h b/drmeventlistener.h new file mode 100644 index 0000000..61eefe8 --- /dev/null +++ b/drmeventlistener.h @@ -0,0 +1,65 @@ +/* + * 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 "autofd.h" +#include "worker.h" + +namespace android { + +class DrmResources; + +class DrmEventHandler { + public: + DrmEventHandler() { + } + virtual ~DrmEventHandler() { + } + + virtual void HandleEvent(uint64_t timestamp_us) = 0; +}; + +class DrmEventListener : public Worker { + public: + DrmEventListener(DrmResources *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; + + DrmResources *drm_; + DrmEventHandler *hotplug_handler_ = NULL; +}; +} + +#endif diff --git a/drmresources.cpp b/drmresources.cpp index 80e61ec..81381c3 100644 --- a/drmresources.cpp +++ b/drmresources.cpp @@ -19,6 +19,7 @@ #include "drmconnector.h" #include "drmcrtc.h" #include "drmencoder.h" +#include "drmeventlistener.h" #include "drmplane.h" #include "drmresources.h" @@ -33,7 +34,11 @@ namespace android { -DrmResources::DrmResources() : compositor_(this) { +DrmResources::DrmResources() : compositor_(this), event_listener_(this) { +} + +DrmResources::~DrmResources() { + event_listener_.Exit(); } int DrmResources::Init() { @@ -194,6 +199,12 @@ int DrmResources::Init() { if (ret) return ret; + ret = event_listener_.Init(); + if (ret) { + ALOGE("Can't initialize event listener %d", ret); + return ret; + } + for (auto &conn : connectors_) { ret = CreateDisplayPipe(conn.get()); if (ret) { @@ -363,6 +374,10 @@ DrmCompositor *DrmResources::compositor() { return &compositor_; } +DrmEventListener *DrmResources::event_listener() { + return &event_listener_; +} + int DrmResources::GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name, DrmProperty *property) { drmModeObjectPropertiesPtr props; diff --git a/drmresources.h b/drmresources.h index 6716807..64e6b57 100644 --- a/drmresources.h +++ b/drmresources.h @@ -21,6 +21,7 @@ #include "drmconnector.h" #include "drmcrtc.h" #include "drmencoder.h" +#include "drmeventlistener.h" #include "drmplane.h" #include <stdint.h> @@ -30,6 +31,7 @@ namespace android { class DrmResources { public: DrmResources(); + ~DrmResources(); int Init(); @@ -49,6 +51,7 @@ class DrmResources { DrmCrtc *GetCrtcForDisplay(int display) const; DrmPlane *GetPlane(uint32_t id) const; DrmCompositor *compositor(); + DrmEventListener *event_listener(); int GetPlaneProperty(const DrmPlane &plane, const char *prop_name, DrmProperty *property); @@ -79,6 +82,7 @@ class DrmResources { std::vector<std::unique_ptr<DrmCrtc>> crtcs_; std::vector<std::unique_ptr<DrmPlane>> planes_; DrmCompositor compositor_; + DrmEventListener event_listener_; }; } |