2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define LOG_TAG "hwc-uevent-listener"
19 #include "UEventListener.h"
21 #include <linux/netlink.h>
22 #include <sys/socket.h>
29 #include "utils/log.h"
31 /* Originally defined in system/core/libsystem/include/system/graphics.h */
32 #define HAL_PRIORITY_URGENT_DISPLAY (-8)
36 UEventListener::UEventListener()
37 : Worker("uevent-listener", HAL_PRIORITY_URGENT_DISPLAY){};
39 int UEventListener::Init() {
40 uevent_fd_ = UniqueFd(
41 socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
43 // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
44 ALOGE("Failed to open uevent socket: %s", strerror(errno));
48 struct sockaddr_nl addr {};
49 addr.nl_family = AF_NETLINK;
51 addr.nl_groups = 0xFFFFFFFF;
53 int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr));
55 // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
56 ALOGE("Failed to bind uevent socket: %s", strerror(errno));
63 void UEventListener::Routine() {
68 ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
73 ALOGE("Got error reading uevent %zd", ret);
77 if (!hotplug_handler_)
80 bool drm_event = false;
81 bool hotplug_event = false;
82 for (uint32_t i = 0; (ssize_t)i < ret;) {
83 char *event = buffer + i;
84 if (strcmp(event, "DEVTYPE=drm_minor") != 0)
86 else if (strcmp(event, "HOTPLUG=1") != 0)
89 i += strlen(event) + 1;
92 if (drm_event && hotplug_event && hotplug_handler_) {
93 constexpr useconds_t delay_after_uevent_us = 200000;
94 /* We need some delay to ensure DrmConnector::UpdateModes() will query
95 * correct modes list, otherwise at least RPI4 board may report 0 modes */
96 usleep(delay_after_uevent_us);
101 } // namespace android