OSDN Git Service

drm_hwcomposer: fix sign-compare building error in uevent listener
[android-x86/external-drm_hwcomposer.git] / drm / UEventListener.cpp
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #define LOG_TAG "hwc-uevent-listener"
18
19 #include "UEventListener.h"
20
21 #include <linux/netlink.h>
22 #include <sys/socket.h>
23 #include <xf86drm.h>
24
25 #include <cassert>
26 #include <cerrno>
27 #include <cstring>
28
29 #include "utils/log.h"
30
31 /* Originally defined in system/core/libsystem/include/system/graphics.h */
32 #define HAL_PRIORITY_URGENT_DISPLAY (-8)
33
34 namespace android {
35
36 UEventListener::UEventListener()
37     : Worker("uevent-listener", HAL_PRIORITY_URGENT_DISPLAY){};
38
39 int UEventListener::Init() {
40   uevent_fd_ = UniqueFd(
41       socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
42   if (!uevent_fd_) {
43     // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
44     ALOGE("Failed to open uevent socket: %s", strerror(errno));
45     return -errno;
46   }
47
48   struct sockaddr_nl addr {};
49   addr.nl_family = AF_NETLINK;
50   addr.nl_pid = 0;
51   addr.nl_groups = 0xFFFFFFFF;
52
53   int ret = bind(uevent_fd_.Get(), (struct sockaddr *)&addr, sizeof(addr));
54   if (ret) {
55     // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
56     ALOGE("Failed to bind uevent socket: %s", strerror(errno));
57     return -errno;
58   }
59
60   return InitWorker();
61 }
62
63 void UEventListener::Routine() {
64   char buffer[1024];
65   ssize_t ret = 0;
66
67   while (true) {
68     ret = read(uevent_fd_.Get(), &buffer, sizeof(buffer));
69     if (ret == 0)
70       return;
71
72     if (ret < 0) {
73       ALOGE("Got error reading uevent %zd", ret);
74       return;
75     }
76
77     if (!hotplug_handler_)
78       continue;
79
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)
85         drm_event = true;
86       else if (strcmp(event, "HOTPLUG=1") != 0)
87         hotplug_event = true;
88
89       i += strlen(event) + 1;
90     }
91
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);
97       hotplug_handler_();
98     }
99   }
100 }
101 }  // namespace android