aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Stratiienko <roman.o.stratiienko@globallogic.com>2022-02-18 16:51:53 +0200
committerRoman Stratiienko <roman.o.stratiienko@globallogic.com>2022-02-18 17:16:00 +0200
commitbd9731713b79f80b2fa1bf180b663649c9d357a5 (patch)
tree1256204708f87e61c547959ef2dd7e77d8499630
parent2c63b3337380dd35ee0c658c05e27bcd89239b10 (diff)
downloaddrm_hwcomposer-bd9731713b79f80b2fa1bf180b663649c9d357a5.tar.gz
drm_hwcomposer: Add test utility to listen for uevents
Dumping uevents is useful for debugging purposes. 1. Extract logic related to uevent socket into utils/UEvent.h class. 2. Use it by both UEventListener.cpp and tests/uevent_print.cpp. Bump clang-tidy level of UEventListener.cpp to normal. Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
-rw-r--r--.ci/Makefile7
-rw-r--r--drm/UEventListener.cpp67
-rw-r--r--drm/UEventListener.h4
-rw-r--r--tests/Android.bp14
-rw-r--r--tests/uevent_print.cpp25
-rw-r--r--utils/UEvent.h85
6 files changed, 143 insertions, 59 deletions
diff --git a/.ci/Makefile b/.ci/Makefile
index cadbde6..a0e4b73 100644
--- a/.ci/Makefile
+++ b/.ci/Makefile
@@ -26,7 +26,6 @@ TIDY_FILES_OVERRIDE := \
drm/DrmProperty.h:COARSE \
drm/DrmUnique.h:FINE \
drm/DrmProperty.cpp:COARSE \
- drm/UEventListener.cpp:COARSE \
drm/VSyncWorker.cpp:COARSE \
hwc2_device/DrmHwcTwo.cpp:COARSE \
hwc2_device/DrmHwcTwo.h:COARSE \
@@ -85,7 +84,7 @@ clean:
# Build
-BUILD_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/*' -path '*.cpp')
+BUILD_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/test_include/*' -path '*.cpp')
SKIP_FILES_path := $(foreach file,$(SKIP_FILES),$(SRC_DIR)/$(file))
BUILD_FILES := $(subst ./,,$(filter-out $(SKIP_FILES_path),$(BUILD_FILES_AUTO)))
@@ -108,7 +107,7 @@ $(OUT_DIR)/%.d: $(SRC_DIR)/%.cpp
$(CLANG) $(CXXARGS) $< -MM -MT $(OUT_DIR)/$(patsubst %.cpp,%.o,$<) -o $@
# TIDY
-TIDY_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/*' \( -path '*.cpp' -o -path '*.h' \))
+TIDY_FILES_AUTO := $(shell find -L $(SRC_DIR) -not -path '*/\.*' -not -path '*/tests/test_include/*' \( -path '*.cpp' -o -path '*.h' \))
TIDY_FILES_AUTO_filtered := $(filter-out $(SKIP_FILES_path),$(TIDY_FILES_AUTO))
@@ -145,7 +144,7 @@ $$(_TARG): _TARG := $$(_TARG)
$$(_TARG): TIDY_ARGS := $$(TIDY_ARGS)
$$(_TARG): $$(_DEP)
mkdir -p $$(dir $$(_TARG))
- $$(CLANG_TIDY) $$(_DEP) $$(TIDY_ARGS) -- -x c++ $$(CXXARGS)
+ $$(CLANG_TIDY) $$(_DEP) $$(TIDY_ARGS) -- -x c++ $$(CXXARGS) -Wno-pragma-once-outside-header
touch $$(_TARG)
endef
diff --git a/drm/UEventListener.cpp b/drm/UEventListener.cpp
index 8d33ad2..b56b8e1 100644
--- a/drm/UEventListener.cpp
+++ b/drm/UEventListener.cpp
@@ -18,82 +18,43 @@
#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)
+/* Originally defined in system/core/libsystem/include/system/graphics.h as
+ * #define HAL_PRIORITY_URGENT_DISPLAY (-8)*/
+constexpr int kHalPriorityUrgentDisplay = -8;
namespace android {
UEventListener::UEventListener()
- : Worker("uevent-listener", HAL_PRIORITY_URGENT_DISPLAY){};
+ : Worker("uevent-listener", kHalPriorityUrgentDisplay){};
int UEventListener::Init() {
- uevent_fd_ = UniqueFd(
- socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
- if (!uevent_fd_) {
- // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
- 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) {
- // NOLINTNEXTLINE(concurrency-mt-unsafe): Fixme
- ALOGE("Failed to bind uevent socket: %s", strerror(errno));
- return -errno;
+ uevent_ = UEvent::CreateInstance();
+ if (!uevent_) {
+ return -ENODEV;
}
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;
+ auto uevent_str = uevent_->ReadNext();
- if (ret < 0) {
- ALOGE("Got error reading uevent %zd", ret);
- return;
- }
-
- if (!hotplug_handler_)
+ if (!hotplug_handler_ || !uevent_str)
continue;
- bool drm_event = false;
- bool hotplug_event = false;
- for (uint32_t i = 0; (ssize_t)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;
- }
+ bool drm_event = uevent_str->find("DEVTYPE=drm_minor") != std::string::npos;
+ bool hotplug_event = uevent_str->find("HOTPLUG=1") != std::string::npos;
- if (drm_event && hotplug_event && hotplug_handler_) {
- constexpr useconds_t delay_after_uevent_us = 200000;
+ if (drm_event && hotplug_event) {
+ constexpr useconds_t kDelayAfterUeventUs = 200000;
/* We need some delay to ensure DrmConnector::UpdateModes() will query
* correct modes list, otherwise at least RPI4 board may report 0 modes */
- usleep(delay_after_uevent_us);
+ usleep(kDelayAfterUeventUs);
hotplug_handler_();
}
}
diff --git a/drm/UEventListener.h b/drm/UEventListener.h
index 0724443..c8b8582 100644
--- a/drm/UEventListener.h
+++ b/drm/UEventListener.h
@@ -19,7 +19,7 @@
#include <functional>
-#include "utils/UniqueFd.h"
+#include "utils/UEvent.h"
#include "utils/Worker.h"
namespace android {
@@ -39,7 +39,7 @@ class UEventListener : public Worker {
void Routine() override;
private:
- UniqueFd uevent_fd_;
+ std::unique_ptr<UEvent> uevent_;
std::function<void()> hotplug_handler_;
};
diff --git a/tests/Android.bp b/tests/Android.bp
index 56f8c4f..e56ff5c 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -33,3 +33,17 @@ cc_test {
"external/drm_hwcomposer/include",
],
}
+
+// Tool for listening and dumping uevents
+cc_test {
+ name: "hwc-drm-uevent-print",
+
+ srcs: ["uevent_print.cpp"],
+
+ vendor: true,
+ header_libs: ["libhardware_headers"],
+ shared_libs: ["liblog"],
+ include_dirs: [
+ "external/drm_hwcomposer",
+ ],
+}
diff --git a/tests/uevent_print.cpp b/tests/uevent_print.cpp
new file mode 100644
index 0000000..6ffbbfb
--- /dev/null
+++ b/tests/uevent_print.cpp
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+
+#include <iostream>
+
+#include "utils/UEvent.h"
+
+int main() {
+ auto uevent = android::UEvent::CreateInstance();
+ if (!uevent) {
+ std::cout << "Can't initialize UEvent class" << std::endl;
+ return -ENODEV;
+ }
+
+ int number = 0;
+ for (;;) {
+ auto msg = uevent->ReadNext();
+ if (!msg) {
+ continue;
+ }
+
+ std::cout << "New event #" << number++ << std::endl
+ << *msg << std::endl
+ << std::endl;
+ }
+}
diff --git a/utils/UEvent.h b/utils/UEvent.h
new file mode 100644
index 0000000..17b3cab
--- /dev/null
+++ b/utils/UEvent.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <linux/netlink.h>
+#include <sys/socket.h>
+
+#include <cerrno>
+#include <memory>
+#include <optional>
+#include <string>
+
+#include "UniqueFd.h"
+#include "log.h"
+
+namespace android {
+
+class UEvent {
+ public:
+ static auto CreateInstance() -> std::unique_ptr<UEvent> {
+ auto fd = UniqueFd(
+ socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT));
+
+ if (!fd) {
+ ALOGE("Failed to open uevent socket: errno=%i", errno);
+ return {};
+ }
+
+ struct sockaddr_nl addr {};
+ addr.nl_family = AF_NETLINK;
+ addr.nl_pid = 0;
+ addr.nl_groups = UINT32_MAX;
+
+ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast)
+ int ret = bind(fd.Get(), (struct sockaddr *)&addr, sizeof(addr));
+ if (ret != 0) {
+ ALOGE("Failed to bind uevent socket: errno=%i", errno);
+ return {};
+ }
+
+ return std::unique_ptr<UEvent>(new UEvent(fd));
+ }
+
+ auto ReadNext() -> std::optional<std::string> {
+ constexpr int kUEventBufferSize = 1024;
+ char buffer[kUEventBufferSize];
+ ssize_t ret = 0;
+ ret = read(fd_.Get(), &buffer, sizeof(buffer));
+ if (ret == 0)
+ return {};
+
+ if (ret < 0) {
+ ALOGE("Got error reading uevent %zd", ret);
+ return {};
+ }
+
+ for (int i = 0; i < ret - 1; i++) {
+ if (buffer[i] == '\0') {
+ buffer[i] = '\n';
+ }
+ }
+
+ return std::string(buffer);
+ }
+
+ private:
+ explicit UEvent(UniqueFd &fd) : fd_(std::move(fd)){};
+ UniqueFd fd_;
+};
+
+} // namespace android