From f6fe82c4118d067419ee58a648654acc03e87f69 Mon Sep 17 00:00:00 2001 From: Konsta Date: Fri, 21 Mar 2025 14:55:10 +0200 Subject: [PATCH] hdmi: connection: add rpi specific aidl hal * Needed for AIDL HDMI-CEC HAL to work. Some functions that were in the HIDL HDMI-CEC HAL have been moved to separate HDMI connection HAL in the AIDL versions. Only returns connection status of HDMI ports on Pi. onHotplugEvent is not implemented. * Use hardware/interfaces/tv/hdmi/connection/aidl/ as reference. --- device.mk | 3 +- hdmi/connection/Android.bp | 22 ++++ hdmi/connection/HdmiConnection.cpp | 119 ++++++++++++++++++ hdmi/connection/HdmiConnection.h | 62 +++++++++ ...hardware.tv.hdmi.connection-service.rpi.rc | 5 + ...ardware.tv.hdmi.connection-service.rpi.xml | 10 ++ hdmi/connection/main.cpp | 37 ++++++ sepolicy/file.te | 1 + sepolicy/file_contexts | 3 + sepolicy/hal_tv_hdmi_connection_default.te | 1 + 10 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 hdmi/connection/Android.bp create mode 100644 hdmi/connection/HdmiConnection.cpp create mode 100644 hdmi/connection/HdmiConnection.h create mode 100644 hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.rc create mode 100644 hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.xml create mode 100644 hdmi/connection/main.cpp create mode 100644 sepolicy/hal_tv_hdmi_connection_default.te diff --git a/device.mk b/device.mk index f10e982..2fc888c 100644 --- a/device.mk +++ b/device.mk @@ -138,7 +138,8 @@ PRODUCT_COPY_FILES += \ # CEC PRODUCT_PACKAGES += \ - android.hardware.tv.hdmi.cec-service.rpi + android.hardware.tv.hdmi.cec-service.rpi \ + android.hardware.tv.hdmi.connection-service.rpi PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.hdmi.cec.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.hdmi.cec.xml diff --git a/hdmi/connection/Android.bp b/hdmi/connection/Android.bp new file mode 100644 index 0000000..9b2a684 --- /dev/null +++ b/hdmi/connection/Android.bp @@ -0,0 +1,22 @@ +// Copyright (C) 2022 The Android Open Source Project +// Copyright (C) 2025 KonstaKANG +// +// SPDX-License-Identifier: Apache-2.0 + +cc_binary { + name: "android.hardware.tv.hdmi.connection-service.rpi", + relative_install_path: "hw", + init_rc: ["android.hardware.tv.hdmi.connection-service.rpi.rc"], + vintf_fragments: ["android.hardware.tv.hdmi.connection-service.rpi.xml"], + vendor: true, + srcs: [ + "HdmiConnection.cpp", + "main.cpp", + ], + shared_libs: [ + "android.hardware.tv.hdmi.connection-V1-ndk", + "libbase", + "libbinder_ndk", + "liblog", + ], +} diff --git a/hdmi/connection/HdmiConnection.cpp b/hdmi/connection/HdmiConnection.cpp new file mode 100644 index 0000000..abe4cb8 --- /dev/null +++ b/hdmi/connection/HdmiConnection.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2025 KonstaKANG + * + * 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 "android.hardware.tv.hdmi.connection-service.rpi" + +#include "HdmiConnection.h" + +#include +#include + +using android::base::ReadFileToString; +using ndk::ScopedAStatus; +using std::string; + +namespace android { +namespace hardware { +namespace tv { +namespace hdmi { +namespace connection { +namespace implementation { + +static const string drmCard = "card0"; + +HdmiConnection::HdmiConnection() { + mCallback = nullptr; + + for (int i = 0; i < 2; i++) { + mPortInfos.push_back( + {.type = HdmiPortType::OUTPUT, + .portId = i, + .cecSupported = true, + .arcSupported = false, + .eArcSupported = false, + .physicalAddress = 0xFFFF}); + mHpdSignal.push_back(HpdSignal::HDMI_HPD_PHYSICAL); + } +} + +HdmiConnection::~HdmiConnection() { + if (mCallback != nullptr) { + mCallback = nullptr; + } +} + +ScopedAStatus HdmiConnection::getPortInfo(std::vector* _aidl_return) { + *_aidl_return = mPortInfos; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiConnection::isConnected(int32_t portId, bool* _aidl_return) { + if (portId != 0 && portId != 1) { + *_aidl_return = false; + return ScopedAStatus::ok(); + } + + bool connected = false; + string hdmiStatusPath = "/sys/class/drm/" + drmCard + "-HDMI-A-" + to_string(portId + 1) + "/status"; + if (!access(hdmiStatusPath.c_str(), R_OK)) { + string connectedValue; + if (ReadFileToString(hdmiStatusPath, &connectedValue)) { + connected = !connectedValue.compare("connected\n"); + } + } + LOG(INFO) << "portId: " << portId << ", connected: " << connected; + + *_aidl_return = connected; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiConnection::setCallback(const std::shared_ptr& callback) { + if (mCallback != nullptr) { + mCallback = nullptr; + } + + if (callback != nullptr) { + mCallback = callback; + } + + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiConnection::setHpdSignal(HpdSignal signal, int32_t portId) { + if (portId != 0 && portId != 1) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + mHpdSignal.at(portId) = signal; + return ScopedAStatus::ok(); +} + +ScopedAStatus HdmiConnection::getHpdSignal(int32_t portId, HpdSignal* _aidl_return) { + if (portId != 0 && portId != 1) { + return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + + *_aidl_return = mHpdSignal.at(portId); + return ScopedAStatus::ok(); +} + +} // namespace implementation +} // namespace connection +} // namespace hdmi +} // namespace tv +} // namespace hardware +} // namespace android diff --git a/hdmi/connection/HdmiConnection.h b/hdmi/connection/HdmiConnection.h new file mode 100644 index 0000000..716b9da --- /dev/null +++ b/hdmi/connection/HdmiConnection.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2025 KonstaKANG + * + * 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. + */ + +#include +#include +#include +#include + +using namespace std; + +namespace android { +namespace hardware { +namespace tv { +namespace hdmi { +namespace connection { +namespace implementation { + +using ::aidl::android::hardware::tv::hdmi::connection::BnHdmiConnection; +using ::aidl::android::hardware::tv::hdmi::connection::HdmiPortInfo; +using ::aidl::android::hardware::tv::hdmi::connection::HdmiPortType; +using ::aidl::android::hardware::tv::hdmi::connection::HpdSignal; +using ::aidl::android::hardware::tv::hdmi::connection::IHdmiConnection; +using ::aidl::android::hardware::tv::hdmi::connection::IHdmiConnectionCallback; +using ::aidl::android::hardware::tv::hdmi::connection::Result; + +struct HdmiConnection : public BnHdmiConnection { + HdmiConnection(); + ~HdmiConnection(); + ::ndk::ScopedAStatus getPortInfo(std::vector* _aidl_return) override; + ::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override; + ::ndk::ScopedAStatus setCallback( + const std::shared_ptr& callback) override; + ::ndk::ScopedAStatus setHpdSignal(HpdSignal signal, int32_t portId) override; + ::ndk::ScopedAStatus getHpdSignal(int32_t portId, HpdSignal* _aidl_return) override; + + private: + std::vector mPortInfos; + std::vector mHpdSignal; + + std::shared_ptr mCallback; +}; + +} // namespace implementation +} // namespace connection +} // namespace hdmi +} // Namespace tv +} // namespace hardware +} // namespace android diff --git a/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.rc b/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.rc new file mode 100644 index 0000000..7087f19 --- /dev/null +++ b/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.rc @@ -0,0 +1,5 @@ +service vendor.hdmi-default /vendor/bin/hw/android.hardware.tv.hdmi.connection-service.rpi + interface aidl android.hardware.tv.hdmi.connection.IHdmiConnection/default + class hal + user system + group system diff --git a/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.xml b/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.xml new file mode 100644 index 0000000..144fef1 --- /dev/null +++ b/hdmi/connection/android.hardware.tv.hdmi.connection-service.rpi.xml @@ -0,0 +1,10 @@ + + + android.hardware.tv.hdmi.connection + 1 + + IHdmiConnection + default + + + diff --git a/hdmi/connection/main.cpp b/hdmi/connection/main.cpp new file mode 100644 index 0000000..2b1f991 --- /dev/null +++ b/hdmi/connection/main.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2025 KonstaKANG + * + * 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. + */ + +#include "HdmiConnection.h" + +#include +#include +#include + +using android::hardware::tv::hdmi::connection::implementation::HdmiConnection; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + + std::shared_ptr hdmiAidl = ndk::SharedRefBase::make(); + const std::string instance = std::string() + HdmiConnection::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(hdmiAidl->asBinder().get(), instance.c_str()); + CHECK_EQ(status, STATUS_OK); + + ABinderProcess_joinThreadPool(); + return EXIT_FAILURE; // should not reach +} diff --git a/sepolicy/file.te b/sepolicy/file.te index 3afd706..8c3f935 100644 --- a/sepolicy/file.te +++ b/sepolicy/file.te @@ -1 +1,2 @@ type mediadrm_vendor_data_file, file_type, data_file_type; +type sysfs_hdmi, file_type, sysfs_type; diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts index 81179c9..d391ade 100644 --- a/sepolicy/file_contexts +++ b/sepolicy/file_contexts @@ -4,7 +4,10 @@ # CEC /dev/cec0 u:object_r:cec_device:s0 /dev/cec1 u:object_r:cec_device:s0 +/sys/devices/platform/gpu/drm/card0/card0-HDMI-A-1/status u:object_r:sysfs_hdmi:s0 +/sys/devices/platform/gpu/drm/card0/card0-HDMI-A-2/status u:object_r:sysfs_hdmi:s0 /vendor/bin/hw/android\.hardware\.tv\.hdmi\.cec-service\.rpi u:object_r:hal_tv_hdmi_cec_default_exec:s0 +/vendor/bin/hw/android\.hardware\.tv\.hdmi\.connection-service\.rpi u:object_r:hal_tv_hdmi_connection_default_exec:s0 # DRM /data/vendor/mediadrm(/.*)? u:object_r:mediadrm_vendor_data_file:s0 diff --git a/sepolicy/hal_tv_hdmi_connection_default.te b/sepolicy/hal_tv_hdmi_connection_default.te new file mode 100644 index 0000000..d016287 --- /dev/null +++ b/sepolicy/hal_tv_hdmi_connection_default.te @@ -0,0 +1 @@ +allow hal_tv_hdmi_connection_default sysfs_hdmi:file r_file_perms;