From 6ba0ca17676254c61748470a9b4d7edd108a440c Mon Sep 17 00:00:00 2001 From: ikavas409_comcast Date: Mon, 25 May 2026 14:21:13 +0000 Subject: [PATCH 01/10] RDKEMW-17873: HDMI-CEC Polaris HAL Migration Added factory pattern to support AIDL HAL and Polaris HAL. Co-authored-by: Sidhanth B H Co-authored-by: kdarma930_comcast Co-authored-by: Vinod Damodaran --- ccec/src/DriverImpl.cpp | 74 +-- ccec/src/DriverImpl.hpp | 5 + ccec/src/Makefile | 46 +- ccec/src/Makefile.am | 12 +- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 462 +++++++++++++++++++ ccec/src/factoryImpl/HDMICecAidlHAL.h | 86 ++++ ccec/src/factoryImpl/HDMICecHalFactory.cpp | 138 ++++++ ccec/src/factoryImpl/HDMICecHalFactory.h | 41 ++ ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 161 +++++++ ccec/src/factoryImpl/HDMICecRdkVHAL.h | 109 +++++ ccec/src/factoryImpl/IHDMICecHal.h | 189 ++++++++ ccec/src/factoryImpl/ServiceManagerCheck.cpp | 255 ++++++++++ ccec/src/factoryImpl/ServiceManagerCheck.h | 28 ++ 13 files changed, 1573 insertions(+), 33 deletions(-) create mode 100644 ccec/src/factoryImpl/HDMICecAidlHAL.cpp create mode 100644 ccec/src/factoryImpl/HDMICecAidlHAL.h create mode 100644 ccec/src/factoryImpl/HDMICecHalFactory.cpp create mode 100644 ccec/src/factoryImpl/HDMICecHalFactory.h create mode 100644 ccec/src/factoryImpl/HDMICecRdkVHAL.cpp create mode 100644 ccec/src/factoryImpl/HDMICecRdkVHAL.h create mode 100644 ccec/src/factoryImpl/IHDMICecHal.h create mode 100644 ccec/src/factoryImpl/ServiceManagerCheck.cpp create mode 100644 ccec/src/factoryImpl/ServiceManagerCheck.h diff --git a/ccec/src/DriverImpl.cpp b/ccec/src/DriverImpl.cpp index ec6c7989..850eb426 100644 --- a/ccec/src/DriverImpl.cpp +++ b/ccec/src/DriverImpl.cpp @@ -36,9 +36,12 @@ #include #include #include +#include +#include #include #include #include +#include #include "osal/EventQueue.hpp" #include "osal/Exception.hpp" @@ -46,6 +49,7 @@ #include "ccec/Exception.hpp" #include "DriverImpl.hpp" #include "ccec/OpCode.hpp" +#include "factoryImpl/HDMICecHalFactory.h" using CCEC_OSAL::AutoLock; @@ -86,6 +90,7 @@ void DriverImpl::DriverTransmitCallback(int handle, void *callbackData, int resu DriverImpl::DriverImpl() : status(CLOSED), nativeHandle(0) { + mHal = HDMICecHalFactory::Create(); CCEC_LOG( LOG_DEBUG, "Creating DriverImpl done\r\n"); } @@ -108,6 +113,7 @@ DriverImpl::~DriverImpl() void DriverImpl::open(void) noexcept(false) { {AutoLock lock_(mutex); + CCEC_LOG( LOG_INFO, "DriverImpl::open invoked\r\n"); if (status != CLOSED) { #if 0 throw InvalidStateException(); @@ -116,14 +122,17 @@ void DriverImpl::open(void) noexcept(false) #endif } - int err = HdmiCecOpen(&nativeHandle); + int err = mHal->open(&nativeHandle); + CCEC_LOG( LOG_INFO, "DriverImpl::open mHal->open returned %d, handle=%d\r\n", err, nativeHandle); if (err != HDMI_CEC_IO_SUCCESS) { throw IOException(); } - HdmiCecSetRxCallback(nativeHandle, DriverReceiveCallback, 0); - HdmiCecSetTxCallback(nativeHandle, DriverTransmitCallback, 0); + mHal->setRxCallback(nativeHandle, DriverReceiveCallback, 0); + mHal->setTxCallback(nativeHandle, DriverTransmitCallback, 0); + status = OPENED; + CCEC_LOG( LOG_INFO, "DriverImpl::open completed successfully\r\n"); } } @@ -143,7 +152,7 @@ void DriverImpl::close(void) noexcept(false) /* Use NULL as sentinel */ rQueue.offer(0); - int err = HdmiCecClose(nativeHandle); + int err = mHal->close(nativeHandle); if (err != HDMI_CEC_IO_SUCCESS) { status = CLOSED; throw IOException(); @@ -203,13 +212,19 @@ void DriverImpl::writeAsync(const CECFrame &frame) noexcept(false) frame.getBuffer(&buf, &length); printFrameDetails(frame); - {AutoLock lock_(mutex); - if (status != OPENED) { + { + AutoLock lock_(mutex); + if (status != OPENED) { throw InvalidStateException(); } + + if(mHal->skipFrameOfUnsupportedLength(length)) { + return; + } + CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTxAsync\r\n"); - int err = HdmiCecTxAsync(nativeHandle, buf, length); + int err = mHal->txAsync(nativeHandle, buf, length); CCEC_LOG( LOG_DEBUG, ">>>>>>> >>>>> >>>> >> >> >\r\n"); @@ -222,10 +237,9 @@ void DriverImpl::writeAsync(const CECFrame &frame) noexcept(false) if (err != HDMI_CEC_IO_SUCCESS) { throw IOException(); } + } - } - - CCEC_LOG( LOG_DEBUG, "Send Async Completed\r\n"); + CCEC_LOG( LOG_DEBUG, "Send Async Completed\r\n"); } @@ -241,14 +255,20 @@ void DriverImpl::write(const CECFrame &frame) noexcept(false) frame.getBuffer(&buf, &length); printFrameDetails(frame); - {AutoLock lock_(mutex); + { + AutoLock lock_(mutex); if (status != OPENED) { throw InvalidStateException(); } + + if(mHal->emulateAckForPollFrames(buf, length)) { + return; + } + int sendResult = HDMI_CEC_IO_SUCCESS; CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTx\r\n"); - int err = HdmiCecTx(nativeHandle, buf, length, &sendResult); + int err = mHal->tx(nativeHandle, buf, length, &sendResult); CCEC_LOG( LOG_DEBUG, ">>>>>>> >>>>> >>>> >> >> >\r\n"); @@ -262,16 +282,16 @@ void DriverImpl::write(const CECFrame &frame) noexcept(false) throw IOException(); } - if (sendResult != HDMI_CEC_IO_SUCCESS) { - if ((sendResult == HDMI_CEC_IO_INVALID_HANDLE) || - (sendResult == HDMI_CEC_IO_INVALID_ARGUMENT) || - (sendResult == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) || - (sendResult == HDMI_CEC_IO_SENT_FAILED) || - (sendResult == HDMI_CEC_IO_GENERAL_ERROR) ) - { - throw IOException(); - } - } + if (sendResult != HDMI_CEC_IO_SUCCESS) { + if ((sendResult == HDMI_CEC_IO_INVALID_HANDLE) || + (sendResult == HDMI_CEC_IO_INVALID_ARGUMENT) || + (sendResult == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) || + (sendResult == HDMI_CEC_IO_SENT_FAILED) || + (sendResult == HDMI_CEC_IO_GENERAL_ERROR)) + { + throw IOException(); + } + } if (((frame.at(0) & 0x0F) != 0x0F) && sendResult == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) { throw CECNoAckException(); @@ -293,7 +313,7 @@ int DriverImpl::getLogicalAddress(int devType) int logicalAddress = 0; CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress called for devType : %d \r\n", devType); - HdmiCecGetLogicalAddress(nativeHandle, &logicalAddress); + mHal->getLogicalAddress(nativeHandle, &logicalAddress); CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress got logical Address : %d \r\n", logicalAddress); return logicalAddress; @@ -305,7 +325,7 @@ void DriverImpl::getPhysicalAddress(unsigned int *physicalAddress) {AutoLock lock_(mutex); CCEC_LOG( LOG_DEBUG, "DriverImpl::getPhysicalAddress called \r\n"); - HdmiCecGetPhysicalAddress(nativeHandle,physicalAddress); + mHal->getPhysicalAddress(nativeHandle, physicalAddress); CCEC_LOG( LOG_DEBUG, "DriverImpl::getPhysicalAddress got physical Address : %x \r\n", *physicalAddress); return ; @@ -315,14 +335,13 @@ void DriverImpl::getPhysicalAddress(unsigned int *physicalAddress) void DriverImpl::removeLogicalAddress(const LogicalAddress &source) { -// int LA[15] = {0}; {AutoLock lock_(mutex); if (status != OPENED) { throw InvalidStateException(); } logicalAddresses.remove(source); - HdmiCecRemoveLogicalAddress(nativeHandle, source.toInt()); + mHal->removeLogicalAddress(nativeHandle, source.toInt()); } } @@ -334,7 +353,7 @@ bool DriverImpl::addLogicalAddress(const LogicalAddress &source) throw InvalidStateException(); } - int retErr = HdmiCecAddLogicalAddress(nativeHandle, source.toInt()); + int retErr = mHal->addLogicalAddress(nativeHandle, source.toInt()); if (retErr == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) { throw AddressNotAvailableException(); @@ -420,6 +439,5 @@ void DriverImpl::printFrameDetails(const CECFrame &frame) noexcept(false) { CCEC_END_NAMESPACE - /** @} */ /** @} */ diff --git a/ccec/src/DriverImpl.hpp b/ccec/src/DriverImpl.hpp index 59daaf57..aeb88127 100644 --- a/ccec/src/DriverImpl.hpp +++ b/ccec/src/DriverImpl.hpp @@ -31,6 +31,7 @@ #define HDMI_CCEC_DRIVER_IMPL_HPP_ #include +#include #include "osal/Mutex.hpp" #include "osal/EventQueue.hpp" @@ -38,6 +39,7 @@ #include "osal/ConditionVariable.hpp" #include "ccec/Driver.hpp" #include "ccec/Header.hpp" +#include "factoryImpl/IHDMICecHal.h" using CCEC_OSAL::EventQueue; using CCEC_OSAL::Mutex; @@ -87,6 +89,8 @@ class DriverImpl : public Driver mutable Mutex mutex; std::list logicalAddresses; + std::unique_ptr mHal; + DriverImpl(const DriverImpl &); /* Not allowed */ DriverImpl & operator = (const DriverImpl &); /* Not allowed */ @@ -99,3 +103,4 @@ CCEC_END_NAMESPACE /** @} */ /** @} */ + diff --git a/ccec/src/Makefile b/ccec/src/Makefile index baa6637b..e1c545d1 100755 --- a/ccec/src/Makefile +++ b/ccec/src/Makefile @@ -30,11 +30,39 @@ OBJS:= CECFrame.o \ LibCCEC.o \ OpCode.o \ Util.o \ + factoryImpl/HDMICecHalFactory.o \ + factoryImpl/HDMICecRdkVHAL.o \ + factoryImpl/HDMICecAidlHAL.o \ + factoryImpl/ServiceManagerCheck.o \ + +# Calculate AIDL include path relative to workspace +AIDL_GEN_DIR := $(shell cd ../../.. && pwd)/aidl/rdk-halif-aidl/gen/hdmicec/current +AIDL_H_DIR := $(AIDL_GEN_DIR)/h +BINDER_IDL_DIR := $(shell cd ../../.. && pwd)/aidl/rdk-halif-aidl/build-tools/linux_binder_idl +BINDER_INCLUDE := $(BINDER_IDL_DIR)/android/native/libs/binder/include +BINDER_NDK_INCLUDE := $(BINDER_IDL_DIR)/android/native/libs/binder/ndk/include_cpp +BINDER_UTILS_INCLUDE := $(BINDER_IDL_DIR)/android/core/libutils/include +BINDER_CUTILS_INCLUDE := $(BINDER_IDL_DIR)/android/core/libcutils/include +BINDER_LOG_INCLUDE := $(BINDER_IDL_DIR)/android/logging/liblog/include +BINDER_BASE_INCLUDE := $(BINDER_IDL_DIR)/android/libbase/include +BINDER_BUILD_DIR := $(BINDER_IDL_DIR)/aidl-generator/out + +# Calculate include directory path explicitly +CCEC_INCLUDE_DIR := $(shell cd .. && pwd)/include INCLUDE = -I.\ - -I../include \ + -I$(CCEC_INCLUDE_DIR) \ -I../../osal/include \ -I../drivers/include \ + -IfactoryImpl \ + -I$(AIDL_H_DIR) \ + -I$(BINDER_INCLUDE) \ + -I$(BINDER_NDK_INCLUDE) \ + -I$(BINDER_UTILS_INCLUDE) \ + -I$(BINDER_CUTILS_INCLUDE) \ + -I$(BINDER_LOG_INCLUDE) \ + -I$(BINDER_BASE_INCLUDE) \ + -I$(BINDER_IDL_DIR)/android/native/include \ CFLAGS+= $(INCLUDE) @@ -42,7 +70,17 @@ CFLAGS+= $(INCLUDE) LDFLAGS+= -L$(OPENSOURCE_BASE)/lib LDFLAGS+=-L$(GLIB_LIBRARY_PATH)/ LDFLAGS+=$(GLIBS) -LDFLAGS += -L. -lpthread +LDFLAGS += -L. -lpthread -L../../osal/src/install/lib -lRCECOSHal +# Binder libraries - link if they exist +ifneq ($(wildcard $(BINDER_BUILD_DIR)/libbinder.a),) +LDFLAGS += -L$(BINDER_BUILD_DIR) -lbinder +endif +ifneq ($(wildcard $(BINDER_BUILD_DIR)/libutils.a),) +LDFLAGS += -L$(BINDER_BUILD_DIR) -lutils +endif +ifneq ($(wildcard $(BINDER_BUILD_DIR)/liblog.a),) +LDFLAGS += -L$(BINDER_BUILD_DIR) -llog +endif all: clean library @echo "Build Finished...." @@ -50,7 +88,7 @@ all: clean library library: $(OBJS) @echo "Building $(LIBNAMEFULL) ...." mkdir -p install/lib - $(CXX) $(OBJS) $(CFLAGS) -shared -o install/lib/$(LIBNAMEFULL) + $(CXX) $(OBJS) $(CFLAGS) $(LDFLAGS) -shared -o install/lib/$(LIBNAMEFULL) %.o: %.cpp @echo "Building $@ ...." @@ -59,3 +97,5 @@ library: $(OBJS) clean: @echo "Cleaning the directory..." @$(RM) $(OBJS) install + + diff --git a/ccec/src/Makefile.am b/ccec/src/Makefile.am index b7e49a07..7600cae7 100644 --- a/ccec/src/Makefile.am +++ b/ccec/src/Makefile.am @@ -23,6 +23,7 @@ lib_LTLIBRARIES = libRCEC.la AM_LDFLAGS = -ltelemetry_msgsender +# Main RCEC library libRCEC_la_SOURCES = CECFrame.cpp \ Util.cpp \ DriverImpl.cpp \ @@ -31,7 +32,14 @@ libRCEC_la_SOURCES = CECFrame.cpp \ OpCode.cpp \ Connection.cpp \ Driver.cpp \ - MessageDecoder.cpp + MessageDecoder.cpp \ + factoryImpl/HDMICecHalFactory.cpp \ + factoryImpl/HDMICecRdkVHAL.cpp \ + factoryImpl/HDMICecAidlHAL.cpp \ + factoryImpl/ServiceManagerCheck.cpp libRCEC_la_LDFLAGS = -lpthread -libRCEC_la_LIBADD = -lRCECOSHal -L${top_builddir}/osal/src/.libs +libRCEC_la_LIBADD = ${top_builddir}/osal/src/libRCECOSHal.la + + + diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp new file mode 100644 index 00000000..4040d1a4 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -0,0 +1,462 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 "HDMICecAidlHAL.h" + +#include +#include +#include +#include +#include +#include + +#include "ccec/Util.hpp" +#include "ccec/Exception.hpp" + +using CCEC_OSAL::AutoLock; +using android::sp; +using android::String16; +using android::defaultServiceManager; +using android::interface_cast; +using namespace com::rdk::hal::hdmicec; + +/** + * @brief HDMI CEC AIDL Event Listener — bridges binder callbacks to the + * C-style callback function pointers stored in HDMICecAidlHAL. + */ +class HDMICecAidlHALEventListener : public BnHdmiCecEventListener { +public: + HDMICecAidlHALEventListener(HDMICecAidlHAL *AidlHal) + : mAidlHal(AidlHal) {} + + android::binder::Status onMessageReceived(const std::vector& message) override { + if (mAidlHal && !message.empty()) { + std::vector mutableMessage(message); + mAidlHal->dispatchRx(reinterpret_cast(mutableMessage.data()), + static_cast(mutableMessage.size())); + } + return android::binder::Status::ok(); + } + + android::binder::Status onStateChanged(State oldState, State newState) override { + // Handle state changes if needed + return android::binder::Status::ok(); + } + + android::binder::Status onMessageSent(const std::vector& message, SendMessageStatus status) override { + if (mAidlHal) { + int result = (status == SendMessageStatus::ACK_STATE_0) ? 1 : + (status == SendMessageStatus::ACK_STATE_1) ? 2 : 3; + mAidlHal->dispatchTx(result); + } + return android::binder::Status::ok(); + } + +private: + HDMICecAidlHAL *mAidlHal; +}; + +HDMICecAidlHAL::HDMICecAidlHAL() + : mAidlService(nullptr), + mAidlController(nullptr), + mEventListener(nullptr), + mRxCb(nullptr), + mTxCb(nullptr), + mRxCbData(nullptr), + mTxCbData(nullptr) +{ +} + +HDMICecAidlHAL::~HDMICecAidlHAL() +{ + AutoLock lock_(mAidlMutex); + mAidlController = nullptr; + mAidlService = nullptr; + mEventListener = nullptr; +} + +bool HDMICecAidlHAL::parseLogicalAddressField(const std::string& line, const char* field, int& value) +{ + const size_t keyPos = line.find(field); + if (keyPos == std::string::npos) { + return false; + } + + const size_t valueStart = line.find_first_not_of(" \t", keyPos + strlen(field)); + if (valueStart == std::string::npos) { + return false; + } + + char* endPtr = nullptr; + const long parsed = std::strtol(line.c_str() + valueStart, &endPtr, 10); + if (endPtr == (line.c_str() + valueStart)) { + return false; + } + + value = static_cast(parsed); + return true; +} + +bool HDMICecAidlHAL::isPresentInVdeviceTopology(const uint8_t destination) +{ + std::ifstream topology(kVdeviceTopologyDump); + if (!topology.is_open()) { + return false; + } + + std::string line; + while (std::getline(topology, line)) { + int logicalAddr = -1; + if (parseLogicalAddressField(line, "Logical-1:", logicalAddr) && logicalAddr == static_cast(destination)) { + return true; + } + + logicalAddr = -1; + if (parseLogicalAddressField(line, "Logical-2:", logicalAddr) && logicalAddr == static_cast(destination)) { + return true; + } + } + + return false; +} + +android::sp HDMICecAidlHAL::getAidlService() +{ + AutoLock lock_(mAidlMutex); + if (mAidlService == nullptr) { + initAidlService(); + } + return mAidlService; +} + +void HDMICecAidlHAL::initAidlService() +{ + android::ProcessState::self()->startThreadPool(); + + sp sm = defaultServiceManager(); + if (sm != nullptr) { + mAidlService = interface_cast( + sm->getService(String16(IHdmiCec::serviceName().c_str()))); + if (mAidlService == nullptr) { + CCEC_LOG(LOG_EXP, "Failed to get AIDL HdmiCec service\r\n"); + throw IOException(); + } + CCEC_LOG(LOG_DEBUG, "Successfully obtained AIDL HdmiCec service\r\n"); + } else { + CCEC_LOG(LOG_EXP, "Failed to get service manager\n"); + throw IOException(); + } +} + +int HDMICecAidlHAL::open(int *handle) +{ + CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::open invoked\n"); + + android::sp service = getAidlService(); + if (service == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::open failed: IHdmiCec service unavailable\r\n"); + throw IOException(); + } + + // Create event listener + mEventListener = new HDMICecAidlHALEventListener(this); + + // Open AIDL interface + android::sp controller; + android::binder::Status status = service->open(mEventListener, &controller); + if (!status.isOk() || controller == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::open failed: service->open status not OK or controller is null\r\n"); + throw IOException(); + } + + mAidlController = controller; + + *handle = 1; /* Dummy handle — AIDL uses controller object */ + + CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::open completed successfully\r\n"); + return 0; +} + +int HDMICecAidlHAL::close(int handle) +{ + CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::close invoked\n"); + (void)handle; + + if (mAidlController != nullptr) { + android::sp service = getAidlService(); + if (service != nullptr) { + bool result = false; + android::binder::Status status = service->close(mAidlController, &result); + if (!status.isOk()) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::close failed: service->close status not OK\n"); + throw IOException(); + } + if (!result) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::close failed: service->close returned false\n"); + throw IOException(); + } + } + mAidlController = nullptr; + } + + mEventListener = nullptr; + + CCEC_LOG(LOG_DEBUG, "Successfully closed AIDL HdmiCec interface\r\n"); + return 0; +} + +int HDMICecAidlHAL::addLogicalAddress(int handle, int logicalAddresses) +{ + if (mAidlController == nullptr) { + throw IOException(); + } + + std::vector addresses; + addresses.push_back(logicalAddresses); + bool result = false; + android::binder::Status status = mAidlController->addLogicalAddresses(addresses, &result); + + if (!status.isOk()) { + CCEC_LOG(LOG_EXP, "Failed to add logical address via AIDL: %s\r\n", status.toString8().c_str()); + throw IOException(); + } + + if (!result) { + throw AddressNotAvailableException(); + } + + CCEC_LOG(LOG_DEBUG, "Successfully added logical address via AIDL\n"); + return 0; +} + +int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) +{ + if (mAidlController == nullptr) { + throw IOException(); + } + + std::vector addresses; + addresses.push_back(logicalAddresses); + bool result = false; + android::binder::Status status = mAidlController->removeLogicalAddresses(addresses, &result); + if (!status.isOk() || !result) { + CCEC_LOG(LOG_EXP, "Failed to remove logical address via AIDL: %s\n", status.toString8().c_str()); + throw IOException(); + } + + CCEC_LOG(LOG_DEBUG, "Successfully removed logical address via AIDL\n"); + return 0; +} + +int HDMICecAidlHAL::getLogicalAddress(int handle, int *logicalAddress) +{ + if (logicalAddress == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::getLogicalAddress invalid output pointer\r\n"); + throw IOException(); + } + + *logicalAddress = 0; + + if (mAidlService == nullptr) { + android::sp service = getAidlService(); + if (service == nullptr) { + throw IOException(); + } + mAidlService = service; + } + + std::vector addresses; + android::binder::Status status = mAidlService->getLogicalAddresses(&addresses); + if (status.isOk() && addresses.size() > 0) { + *logicalAddress = addresses[0]; + } + + CCEC_LOG( LOG_DEBUG, "HDMICecAidlHAL::getLogicalAddress completed\r\n"); + + return 0; +} + +int HDMICecAidlHAL::getPhysicalAddress(int handle, unsigned int *physicalAddress) +{ + if (physicalAddress != nullptr) { + *physicalAddress = 0; + } + + CCEC_LOG( LOG_DEBUG, "HDMICecAidlHAL::getPhysicalAddress completed\r\n"); + + return 0; +} + +void HDMICecAidlHAL::dispatchRx(unsigned char *buf, int len) +{ + if (mRxCb == nullptr) { + CCEC_LOG(LOG_DEBUG, "HDMICecAidlHAL::dispatchRx callback not registered\r\n"); + return; + } + + mRxCb(0, mRxCbData, buf, len); +} + +void HDMICecAidlHAL::dispatchTx(int result) +{ + if (mTxCb == nullptr) { + CCEC_LOG(LOG_DEBUG, "HDMICecAidlHAL::dispatchTx callback not registered\r\n"); + return; + } + + mTxCb(0, mTxCbData, result); +} + +int HDMICecAidlHAL::setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) +{ + (void)handle; + + mRxCb = cbfunc; + mRxCbData = data; + + CCEC_LOG(LOG_DEBUG, "HDMICecAidlHAL::setRxCallback invoked\r\n"); + return 0; +} + +int HDMICecAidlHAL::setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) +{ + (void)handle; + + mTxCb = cbfunc; + mTxCbData = data; + + CCEC_LOG(LOG_DEBUG, "HDMICecAidlHAL::setTxCallback invoked\r\n"); + return 0; +} + +int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *result) +{ + if (mAidlController == nullptr) { + throw IOException(); + } + + if (result == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::tx invalid result pointer\n"); + throw IOException(); + } + + if (buf == nullptr || len <= 0) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::tx invalid buffer or length\n"); + throw IOException(); + } + + std::vector message(buf, buf + len); + SendMessageStatus sendStatus; + android::binder::Status status = mAidlController->sendMessage(message, &sendStatus); + if (!status.isOk()) { + CCEC_LOG(LOG_ERROR, "AIDL sendMessage failed: %s\r\n", status.toString8().c_str()); + throw IOException(); + } + + // Map AIDL SendMessageStatus to HAL error codes + *result = 0; // HDMI_CEC_IO_SUCCESS + if (sendStatus == SendMessageStatus::ACK_STATE_0) { + *result = 1; // HDMI_CEC_IO_SENT_AND_ACKD + } else if (sendStatus == SendMessageStatus::ACK_STATE_1) { + *result = 2; // HDMI_CEC_IO_SENT_BUT_NOT_ACKD + } else if (sendStatus == SendMessageStatus::BUSY){ + *result = 3; // HDMI_CEC_IO_SENT_FAILED + throw IOException(); + } + + CCEC_LOG( LOG_DEBUG, "AIDL sendMessage DONE, result %x\r\n", *result); + + return 0; +} + +int HDMICecAidlHAL::txAsync(int handle, const unsigned char *buf, int len) +{ + if (mAidlController == nullptr) { + throw IOException(); + } + if (buf == nullptr || len <= 0) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::txAsync invalid buffer or length\n"); + throw IOException(); + } + + std::vector message(buf, buf + len); + SendMessageStatus sendStatus; + android::binder::Status status = mAidlController->sendMessage(message, &sendStatus); + if (!status.isOk()) { + CCEC_LOG(LOG_ERROR, "AIDL sendMessage failed: %s\r\n", status.toString8().c_str()); + throw IOException(); + } + + if (sendStatus == SendMessageStatus::BUSY) { + CCEC_LOG(LOG_ERROR, "AIDL sendMessage busy in txAsync\r\n"); + throw IOException(); + } + + CCEC_LOG( LOG_DEBUG, "AIDL sendMessage completed, status: %d\r\n", static_cast(sendStatus)); + + CCEC_LOG( LOG_DEBUG, "Send Async Completed\n"); + + return 0; +} + +bool HDMICecAidlHAL::skipFrameOfUnsupportedLength(size_t length) { + if (length < kAidlMinCecFrameSize || length > kAidlMaxCecFrameSize) { + /* AIDL sendMessage accepts only 2..16 byte CEC frames. */ + CCEC_LOG(LOG_WARN, + "DriverImpl::writeAsync skipping unsupported CEC frame length=%zu on AIDL backend (valid range: 2..16).\r\n", + length); + return true; + } + + return false; +} + +bool HDMICecAidlHAL::emulateAckForPollFrames(const unsigned char *buf, int len) +{ + if (len <= 1) { + /* + * Poll frame (header only): emulate ACK based on vdevice topology file. + * This keeps HdmiCecSource ping-based discovery working on AIDL backend. + */ + const uint8_t destination = (buf != NULL) ? (buf[0] & 0x0F) : 0xFF; + const bool addressPresent = (destination <= 0x0E) ? isPresentInVdeviceTopology(destination) : false; + + if (addressPresent) { + CCEC_LOG(LOG_DEBUG, + "DriverImpl::write poll-frame destination=0x%X present in topology. Emulating ack.\r\n", + destination); + return true; + } + + CCEC_LOG(LOG_DEBUG, + "DriverImpl::write poll-frame destination=0x%X not present in topology. Returning no-ack.\r\n", + destination); + throw CECNoAckException(); + } + + if (static_cast(len) > kAidlMaxCecFrameSize) { + CCEC_LOG(LOG_EXP, + "DriverImpl::write blocking unsupported CEC frame length=%zu on AIDL backend (valid range: 2..16).\r\n", + static_cast(len)); + throw IOException(); + } + + return false; +} + diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.h b/ccec/src/factoryImpl/HDMICecAidlHAL.h new file mode 100644 index 00000000..3cd28163 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.h @@ -0,0 +1,86 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 HDMI_CEC_AIDL_HAL_H +#define HDMI_CEC_AIDL_HAL_H + +#include "IHDMICecHal.h" + + #include + #include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "osal/Mutex.hpp" + +using CCEC_OSAL::Mutex; + +class HDMICecAidlHALEventListener; + +class HDMICecAidlHAL : public IHDMICecHal { +public: + HDMICecAidlHAL(); + ~HDMICecAidlHAL() override; + + int open(int *handle) override; + int close(int handle) override; + int addLogicalAddress(int handle, int logicalAddresses) override; + int removeLogicalAddress(int handle, int logicalAddresses) override; + int getLogicalAddress(int handle, int *logicalAddress) override; + int getPhysicalAddress(int handle, unsigned int *physicalAddress) override; + int setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) override; + int setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) override; + int tx(int handle, const unsigned char *buf, int len, int *result) override; + int txAsync(int handle, const unsigned char *buf, int len) override; + bool skipFrameOfUnsupportedLength(size_t length) override; + bool emulateAckForPollFrames(const unsigned char *buf, int len) override; + +private: + const size_t kAidlMinCecFrameSize = 2; + const size_t kAidlMaxCecFrameSize = 16; + static constexpr const char* kVdeviceTopologyDump = "/tmp/hdmi_cec_device_list_info.txt"; + + bool parseLogicalAddressField(const std::string& line, const char* field, int& value); + bool isPresentInVdeviceTopology(const uint8_t destination); + android::sp getAidlService(); + void initAidlService(); + void dispatchRx(unsigned char *buf, int len); + void dispatchTx(int result); + + android::sp mAidlService; + android::sp mAidlController; + android::sp mEventListener; + HdmiCecRxCallback_t mRxCb; + HdmiCecTxCallback_t mTxCb; + void* mRxCbData; + void* mTxCbData; + mutable Mutex mAidlMutex; + + friend class HDMICecAidlHALEventListener; +}; + +#endif // HDMI_CEC_AIDL_HAL_H + diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.cpp b/ccec/src/factoryImpl/HDMICecHalFactory.cpp new file mode 100644 index 00000000..15f078f7 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecHalFactory.cpp @@ -0,0 +1,138 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 "HDMICecHalFactory.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ServiceManagerCheck.h" +#include "HDMICecAidlHAL.h" +#include "HDMICecRdkVHAL.h" +#include "ccec/Util.hpp" + +using namespace com::rdk::hal::hdmicec; + +static const android::String16 mServiceManagerName("manager"); +HDMICecHalFactory::BackendType HDMICecHalFactory::mBackendType = HDMICecHalFactory::BackendType::UNKNOWN; + +bool HDMICecHalFactory::isAidlServiceAvailable() +{ + CCEC_LOG(LOG_INFO, "HDMICecHalFactory::isAidlServiceAvailable invoked\r\n"); + + if (mBackendType == HDMICecHalFactory::BackendType::AIDL) { + return true; + } else if (mBackendType == HDMICecHalFactory::BackendType::LEGACY) { + return false; + } + + if (!isServiceManagerAvailable()) { + CCEC_LOG(LOG_INFO, "Binder driver not available; assuming legacy HDMI CEC HAL\r\n"); + mBackendType = HDMICecHalFactory::BackendType::LEGACY; + return false; + } + + android::sp serviceManager = android::defaultServiceManager(); + if (serviceManager == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecHalFactory::isAidlServiceAvailable failed: IServiceManager unavailable\r\n"); + mBackendType = HDMICecHalFactory::BackendType::LEGACY; + return false; + } + + CCEC_LOG(LOG_INFO, "Successfully obtained IServiceManager\r\n"); + + const android::String16 expectedServiceName(IHdmiCec::serviceName().c_str()); + android::Vector services = serviceManager->listServices(); + size_t discoveredServiceCount = 0; + bool matched = false; + + for (size_t index = 0; index < services.size(); ++index) { + if (services[index] != mServiceManagerName) { + ++discoveredServiceCount; + } + } + + CCEC_LOG(LOG_INFO, "HDMICecHalFactory::isAidlServiceAvailable discovered %zu binder services\r\n", discoveredServiceCount); + if (discoveredServiceCount == 0) { + CCEC_LOG(LOG_INFO, + "HDMICecHalFactory::isAidlServiceAvailable found no binder services beyond the ServiceManager entry while searching for '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = HDMICecHalFactory::BackendType::LEGACY; + return false; + } + + CCEC_LOG(LOG_INFO, + "HDMICecHalFactory::isAidlServiceAvailable inspecting %zu registered binder services for '%s'\r\n", + discoveredServiceCount, android::String8(expectedServiceName).string()); + + for (size_t index = 0; index < services.size(); ++index) { + if (services[index] == mServiceManagerName) { + continue; + } + + const android::String8 discoveredServiceName(services[index]); + if (services[index] == expectedServiceName) { + matched = true; + } + + CCEC_LOG(LOG_INFO, + "HDMICecHalFactory::isAidlServiceAvailable discovered binder service[%zu]='%s'\r\n", + index, + discoveredServiceName.string()); + } + + if (matched) { + CCEC_LOG(LOG_INFO, + "HDMICecHalFactory::isAidlServiceAvailable found HDMI CEC AIDL service '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = HDMICecHalFactory::BackendType::AIDL; + return true; + } + + CCEC_LOG(LOG_INFO, + "HDMICecHalFactory::isAidlServiceAvailable did not find HDMI CEC AIDL service '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = HDMICecHalFactory::BackendType::LEGACY; + return false; +} + +std::unique_ptr HDMICecHalFactory::Create() +{ + CCEC_LOG(LOG_INFO, "HDMICecHalFactory::Create invoked\r\n"); + + if (isAidlServiceAvailable()) { + CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is available — using HDMICecAidlHAL\r\n"); + return std::make_unique(); + } + + CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is not available — using legacy HDMICecRdkVHAL\r\n"); + return std::make_unique(); +} + diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.h b/ccec/src/factoryImpl/HDMICecHalFactory.h new file mode 100644 index 00000000..ee8a6602 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecHalFactory.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 HDMI_CEC_HAL_FACTORY_H +#define HDMI_CEC_HAL_FACTORY_H + +#include "IHDMICecHal.h" +#include + +class HDMICecHalFactory { +public: + static std::unique_ptr Create(); + +private: + enum class BackendType { + UNKNOWN, + LEGACY, + AIDL + }; + + static BackendType mBackendType; + static bool isAidlServiceAvailable(); +}; + +#endif // HDMI_CEC_HAL_FACTORY_H diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp new file mode 100644 index 00000000..c19e05f6 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -0,0 +1,161 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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. +*/ + +/* + * HDMICecRdkVHAL.cpp — Legacy C HAL implementation of HDMICecHal. + * + * Each function wraps the corresponding HdmiCec* C API from hdmi_cec_driver.h. + */ + +#include +#include "HDMICecRdkVHAL.h" +#include "ccec/Util.hpp" + +/* ----------------------------------------------------------------------- + * open + * Calls HdmiCecOpen() to initialise the driver and obtain a handle. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::open(int *handle) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::open\r\n"); + int ret = ::HdmiCecOpen(handle); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::open ret=%d handle=%d\r\n", ret, (handle ? *handle : -1)); + return ret; +} + +/* ----------------------------------------------------------------------- + * close + * Calls HdmiCecClose() to release driver resources. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::close(int handle) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::close handle=%d\r\n", handle); + int ret = ::HdmiCecClose(handle); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::close ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * setRxCallback + * Calls HdmiCecSetRxCallback() to register the incoming-message callback. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::setRxCallback handle=%d\r\n", handle); + int ret = ::HdmiCecSetRxCallback(handle, cbfunc, data); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setRxCallback ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * setTxCallback + * Calls HdmiCecSetTxCallback() to register the transmit-status callback. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::setTxCallback handle=%d\r\n", handle); + int ret = ::HdmiCecSetTxCallback(handle, cbfunc, data); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setTxCallback ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * tx + * Calls HdmiCecTx() for a synchronous transmit; blocks until ACK/NACK. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::tx(int handle, const unsigned char *buf, int len, int *result) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::tx handle=%d len=%d\r\n", handle, len); + int ret = ::HdmiCecTx(handle, buf, len, result); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::tx ret=%d sendResult=%d\r\n", ret, (result ? *result : -1)); + return ret; +} + +/* ----------------------------------------------------------------------- + * txAsync + * Calls HdmiCecTxAsync() for a fire-and-forget transmit. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::txAsync(int handle, const unsigned char *buf, int len) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::txAsync handle=%d len=%d\r\n", handle, len); + int ret = ::HdmiCecTxAsync(handle, buf, len); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::txAsync ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * addLogicalAddress + * Calls HdmiCecAddLogicalAddress() to claim a logical address on the bus. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::addLogicalAddress(int handle, int logicalAddress) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::addLogicalAddress handle=%d addr=%d\r\n", handle, logicalAddress); + int ret = ::HdmiCecAddLogicalAddress(handle, logicalAddress); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::addLogicalAddress ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * removeLogicalAddress + * Calls HdmiCecRemoveLogicalAddress() to release a previously claimed + * logical address. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::removeLogicalAddress(int handle, int logicalAddress) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::removeLogicalAddress handle=%d addr=%d\r\n", handle, logicalAddress); + int ret = ::HdmiCecRemoveLogicalAddress(handle, logicalAddress); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::removeLogicalAddress ret=%d\r\n", ret); + return ret; +} + +/* ----------------------------------------------------------------------- + * getLogicalAddress + * Calls HdmiCecGetLogicalAddress() to retrieve the current logical address. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::getLogicalAddress(int handle, int *logicalAddress) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::getLogicalAddress handle=%d\r\n", handle); + int ret = ::HdmiCecGetLogicalAddress(handle, logicalAddress); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getLogicalAddress ret=%d addr=%d\r\n", + ret, (logicalAddress ? *logicalAddress : -1)); + return ret; +} + +/* ----------------------------------------------------------------------- + * getPhysicalAddress + * Calls HdmiCecGetPhysicalAddress() to retrieve the device physical address. + * -------------------------------------------------------------------- */ +int HDMICecRdkVHAL::getPhysicalAddress(int handle, unsigned int *physicalAddress) +{ + CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::getPhysicalAddress handle=%d\r\n", handle); + int ret = ::HdmiCecGetPhysicalAddress(handle, physicalAddress); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getPhysicalAddress ret=%d addr=0x%x\r\n", + ret, (physicalAddress ? *physicalAddress : 0)); + return ret; +} + +bool HDMICecRdkVHAL::skipFrameOfUnsupportedLength(size_t length) { + return false; +} + +bool HDMICecRdkVHAL::emulateAckForPollFrames(const unsigned char *buf, int len) +{ + // No emulation for HDMICecRdkVHAL + return false; +} diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.h b/ccec/src/factoryImpl/HDMICecRdkVHAL.h new file mode 100644 index 00000000..adbbac79 --- /dev/null +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.h @@ -0,0 +1,109 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 HDMI_CEC_RDK_V_HAL_H +#define HDMI_CEC_RDK_V_HAL_H + +#include "IHDMICecHal.h" + +/** + * @brief Legacy (C HAL) implementation of IHDMICecHal. + * + * Each override delegates directly to the corresponding HdmiCec* C function + * from hdmi_cec_driver.h. + */ +class HDMICecRdkVHAL : public IHDMICecHal { +public: + /** + * @brief Open the HDMI CEC HAL driver. + * Calls HdmiCecOpen(). + */ + int open(int *handle) override; + + /** + * @brief Close the HDMI CEC HAL driver. + * Calls HdmiCecClose(). + */ + int close(int handle) override; + + /** + * @brief Register the receive callback. + * Calls HdmiCecSetRxCallback(). + */ + int setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) override; + + /** + * @brief Register the transmit-status callback. + * Calls HdmiCecSetTxCallback(). + */ + int setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) override; + + /** + * @brief Synchronous CEC transmit. + * Calls HdmiCecTx(). The send result is written to *result. + */ + int tx(int handle, const unsigned char *buf, int len, int *result) override; + + /** + * @brief Asynchronous CEC transmit. + * Calls HdmiCecTxAsync(). Result is delivered via the TxCallback. + */ + int txAsync(int handle, const unsigned char *buf, int len) override; + + /** + * @brief Add a logical address. + * Calls HdmiCecAddLogicalAddress(). + */ + int addLogicalAddress(int handle, int logicalAddress) override; + + /** + * @brief Remove a logical address. + * Calls HdmiCecRemoveLogicalAddress(). + */ + int removeLogicalAddress(int handle, int logicalAddress) override; + + /** + * @brief Get the device logical address. + * Calls HdmiCecGetLogicalAddress(). + */ + int getLogicalAddress(int handle, int *logicalAddress) override; + + /** + * @brief Get the device physical address. + * Calls HdmiCecGetPhysicalAddress(). + */ + int getPhysicalAddress(int handle, unsigned int *physicalAddress) override; + + /** + * @brief Determine if a received frame of the given length should be skipped + * because its length is unsupported by the legacy HAL. + */ + bool skipFrameOfUnsupportedLength(size_t length) override; + + /** + * @brief Emulate ACK for Poll messages, which the legacy HAL does not support. + * This allows the driver to treat Poll frames as if they were ACKed, + * ensuring proper handling of device presence on the bus. + */ + bool emulateAckForPollFrames(const unsigned char *buf, int len) override; +}; + +#endif // HDMI_CEC_RDK_V_HAL_H + + diff --git a/ccec/src/factoryImpl/IHDMICecHal.h b/ccec/src/factoryImpl/IHDMICecHal.h new file mode 100644 index 00000000..55b0b1c8 --- /dev/null +++ b/ccec/src/factoryImpl/IHDMICecHal.h @@ -0,0 +1,189 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 I_HDMI_CEC_HAL_H +#define I_HDMI_CEC_HAL_H + +#include +#include "ccec/drivers/hdmi_cec_driver.h" + +/** + * @brief Abstract base class for HDMI CEC hardware abstraction. + * + * Each virtual function maps 1:1 to a HAL operation. Subclasses provide + * either a legacy (C HAL) implementation or an AIDL (binder) implementation. + * + * - Legacy subclass: delegates directly to HdmiCec* C functions. + * - AIDL subclass: communicates with the Android HDMI CEC AIDL service. + */ +class IHDMICecHal { +public: + virtual ~IHDMICecHal() = default; + + /** + * @brief Open the HDMI CEC HAL driver. + * + * Legacy: calls HdmiCecOpen(). + * AIDL: connects to the AIDL binder service and obtains a session. + * + * @param[out] handle Receives the driver handle. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int open(int *handle) = 0; + + /** + * @brief Close the HDMI CEC HAL driver. + * + * Legacy: calls HdmiCecClose(). + * AIDL: disconnects from the binder service. + * + * @param[in] handle The driver handle returned by open(). + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int close(int handle) = 0; + + /** + * @brief Set the receive callback for incoming CEC messages. + * + * Legacy: calls HdmiCecSetRxCallback(). + * AIDL: registers an AIDL callback listener that bridges to cbfunc. + * + * @param[in] handle The driver handle. + * @param[in] cbfunc Callback function invoked on message reception. + * @param[in] data Opaque user data forwarded to cbfunc. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) = 0; + + /** + * @brief Set the transmit callback for transmission status notification. + * + * Legacy: calls HdmiCecSetTxCallback(). + * AIDL: registers an AIDL callback listener that bridges to cbfunc. + * + * @param[in] handle The driver handle. + * @param[in] cbfunc Callback function invoked with transmit result. + * @param[in] data Opaque user data forwarded to cbfunc. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) = 0; + + /** + * @brief Transmit a CEC message synchronously. + * + * Legacy: calls HdmiCecTx(). + * AIDL: sends message via binder and blocks until result is available. + * + * @param[in] handle The driver handle. + * @param[in] buf Buffer containing the CEC message. + * @param[in] len Length of the message in bytes. + * @param[out] result Receives the transmission result code. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int tx(int handle, const unsigned char *buf, int len, int *result) = 0; + + /** + * @brief Transmit a CEC message asynchronously. + * + * Legacy: calls HdmiCecTxAsync(). + * AIDL: sends message via binder; result delivered through TxCallback. + * + * @param[in] handle The driver handle. + * @param[in] buf Buffer containing the CEC message. + * @param[in] len Length of the message in bytes. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int txAsync(int handle, const unsigned char *buf, int len) = 0; + + /** + * @brief Add a logical address for receiving CEC messages. + * + * Legacy: calls HdmiCecAddLogicalAddress(). + * AIDL: registers the logical address via binder. + * + * @param[in] handle The driver handle. + * @param[in] logicalAddress Logical address to add (0-15). + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int addLogicalAddress(int handle, int logicalAddress) = 0; + + /** + * @brief Remove a previously added logical address. + * + * Legacy: calls HdmiCecRemoveLogicalAddress(). + * AIDL: unregisters the logical address via binder. + * + * @param[in] handle The driver handle. + * @param[in] logicalAddress Logical address to remove (0-15). + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int removeLogicalAddress(int handle, int logicalAddress) = 0; + + /** + * @brief Get the logical address of the device. + * + * Legacy: calls HdmiCecGetLogicalAddress(). + * AIDL: queries the logical address via binder. + * + * @param[in] handle The driver handle. + * @param[out] logicalAddress Pointer to store the logical address. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int getLogicalAddress(int handle, int *logicalAddress) = 0; + + /** + * @brief Get the physical address of the device. + * + * Legacy: calls HdmiCecGetPhysicalAddress(). + * AIDL: queries the physical address via binder. + * + * @param[in] handle The driver handle. + * @param[out] physicalAddress Pointer to store the physical address. + * @return HDMI_CEC_IO_SUCCESS on success, or an error code. + */ + virtual int getPhysicalAddress(int handle, unsigned int *physicalAddress) = 0; + + /** + * @brief Check if a frame of unsupported length should be skipped. + * + * Legacy: no-op (returns false). + * AIDL: validates frame length against binder service constraints. + * + * @param[in] length Length of the CEC frame. + * @return true if the frame should be skipped, false otherwise. + */ + virtual bool skipFrameOfUnsupportedLength(size_t length) = 0; + + /** + * @brief Emulate acknowledgment for poll frames. + * + * Legacy: Ignores this as the legacy HAL does not support emulating ACKs. + * AIDL: Check Vdevice topology to determine emulation required or not + * + * @param[in] buf Buffer containing the CEC frame. + * @param[in] len Length of the CEC frame. + * @return true if acknowledgment should be emulated, false otherwise. + */ + virtual bool emulateAckForPollFrames(const unsigned char *buf, int len) = 0; +}; + +#endif // I_HDMI_CEC_HAL_H + + + diff --git a/ccec/src/factoryImpl/ServiceManagerCheck.cpp b/ccec/src/factoryImpl/ServiceManagerCheck.cpp new file mode 100644 index 00000000..42780c91 --- /dev/null +++ b/ccec/src/factoryImpl/ServiceManagerCheck.cpp @@ -0,0 +1,255 @@ +/* + * Copyright 2026 RDK Management + * + * 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. +*/ + +/* + * ServiceManagerCheck.cpp — Checking the availability of the Android ServiceManager via Binder IPC. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ServiceManagerCheck.h" +#include "ccec/Util.hpp" + +// --- Internal implementation details --- +namespace { + +// --- Pure Legacy 32-bit Architecture Layouts --- +#pragma pack(push, 4) +struct binder_write_read_v7 { + uint32_t write_size; + uint32_t write_consumed; + uint32_t write_buffer; + uint32_t read_size; + uint32_t read_consumed; + uint32_t read_buffer; +}; + +struct binder_transaction_data_v7 { + union { + uint32_t handle; + uint32_t ptr; + } target; + uint32_t cookie; + uint32_t code; + uint32_t flags; + int32_t sender_pid; + int32_t sender_euid; + uint32_t data_size; + uint32_t offsets_size; + union { + struct { + uint32_t buffer; + uint32_t offsets; + } ptr; + uint8_t buf[8]; + } data; +}; +#pragma pack(pop) + +// --- Configuration Constants --- +constexpr uint32_t BINDER_MMAP_SIZE_V7 = (128 * 1024); +constexpr uint32_t BINDER_MMAP_SIZE_V8 = (1024 * 1024); +constexpr uint32_t BR_REPLY_V7 = 0x80247201; +constexpr uint32_t BR_REPLY_V8 = 0x80287203; +constexpr uint32_t BR_REPLY_V7_ACTUAL = 0x7206; +constexpr uint32_t BR_TRANSACTION_COMPLETE_V7 = 0x720c; +constexpr uint32_t BR_OK_V7 = 0x7205; +constexpr uint32_t PING_TRANSACTION = 0x5F504E47; // '_PNG' + +// Macro definitions for internal use +#define BINDER_VERSION _IOWR('b', 9, struct binder_version) +#define BINDER_WRITE_READ_V7 _IOWR('b', 1, struct binder_write_read_v7) +#define BC_TRANSACTION_V7 _IOW('c', 0, struct binder_transaction_data_v7) + +// --- Unified Payload Aggregator Struct --- +struct BinderTransaction { + std::vector write_payload; + std::vector read_payload; + unsigned long ioctl_command = 0; +}; + +// Helper: Generates v7 structural packets +static BinderTransaction prepare_v7_transaction() { + BinderTransaction tx; + tx.ioctl_command = BINDER_WRITE_READ_V7; + + binder_transaction_data_v7 txn{}; + txn.target.handle = 0; + txn.code = PING_TRANSACTION; + txn.flags = 0; + txn.data_size = 0; + txn.offsets_size = 0; + + const size_t tx_words = sizeof(txn) / sizeof(uint32_t); + tx.write_payload.reserve(1 + tx_words); + tx.write_payload.push_back(BC_TRANSACTION_V7); + + const auto* raw_ptr = reinterpret_cast(&txn); + tx.write_payload.insert(tx.write_payload.end(), raw_ptr, raw_ptr + tx_words); + tx.read_payload.resize(256, 0); + return tx; +} + +// Helper: Generates v8 (Current System Context) structural packets +static BinderTransaction prepare_v8_transaction() { + BinderTransaction tx; + tx.ioctl_command = BINDER_WRITE_READ; + + struct binder_transaction_data txn{}; + std::memset(&txn, 0, sizeof(txn)); + txn.target.handle = 0; + txn.code = PING_TRANSACTION; + txn.flags = TF_ACCEPT_FDS; + txn.data_size = 0; + txn.offsets_size = 0; + + const size_t tx_words = sizeof(txn) / sizeof(uint32_t); + tx.write_payload.reserve(1 + tx_words); + tx.write_payload.push_back(BC_TRANSACTION); + + const auto* raw_ptr = reinterpret_cast(&txn); + tx.write_payload.insert(tx.write_payload.end(), raw_ptr, raw_ptr + tx_words); + tx.read_payload.resize(256, 0); + return tx; +} + +// --- Common Protocol Engine Core --- +static bool execute_binder_ping(const int binder_fd, const int protocol_version) { + const BinderTransaction tx = (protocol_version == 7) ? prepare_v7_transaction() : prepare_v8_transaction(); + uint32_t bytes_consumed = 0; + + CCEC_LOG(LOG_INFO, "[*] Routing Ping via version %d layout engine...\n", protocol_version); + + if (protocol_version == 7) { + binder_write_read_v7 bwr{}; + const size_t write_size = tx.write_payload.size() * sizeof(uint32_t); + const size_t read_size = tx.read_payload.size() * sizeof(uint32_t); + bwr.write_size = write_size; + bwr.write_consumed = 0; + bwr.write_buffer = static_cast(reinterpret_cast(tx.write_payload.data())); + bwr.read_size = read_size; + bwr.read_consumed = 0; + bwr.read_buffer = static_cast(reinterpret_cast(tx.read_payload.data())); + + const unsigned long ioctl_cmd = tx.ioctl_command; + if (ioctl(binder_fd, ioctl_cmd, &bwr) < 0) { + CCEC_LOG(LOG_ERROR, "[-] ioctl execution map allocation failed\n"); + return false; + } + bytes_consumed = bwr.read_consumed; + } else { + struct binder_write_read bwr{}; + std::memset(&bwr, 0, sizeof(bwr)); + const size_t write_size = tx.write_payload.size() * sizeof(uint32_t); + const size_t read_size = tx.read_payload.size() * sizeof(uint32_t); + bwr.write_size = write_size; + bwr.write_consumed = 0; + bwr.write_buffer = reinterpret_cast(tx.write_payload.data()); + bwr.read_size = read_size; + bwr.read_consumed = 0; + bwr.read_buffer = reinterpret_cast(tx.read_payload.data()); + + const unsigned long ioctl_cmd = tx.ioctl_command; + if (ioctl(binder_fd, ioctl_cmd, &bwr) < 0) { + CCEC_LOG(LOG_ERROR, "[-] ioctl execution map allocation failed: %s\n", std::strerror(errno)); + return false; + } + bytes_consumed = bwr.read_consumed; + } + + // --- Unified Protocol Response Token Parsing Loop --- + CCEC_LOG(LOG_INFO, "[*] Driver returned %u bytes of response telemetry.\n", bytes_consumed); + + const uint32_t* const read_start = tx.read_payload.data(); + const uint32_t* const read_end = read_start + (bytes_consumed / sizeof(uint32_t)); + bool service_manager_alive = false; + + for (const uint32_t* read_ptr = read_start; read_ptr < read_end; ++read_ptr) { + const uint32_t token = *read_ptr; + CCEC_LOG(LOG_INFO, "[*] Intercepted response token: 0x%x\n", token); + + if (token == BR_REPLY || token == BR_REPLY_V7_ACTUAL || token == BR_REPLY_V7 || token == BR_REPLY_V8) { + CCEC_LOG(LOG_INFO, "[+] Explicit reply acknowledgement found!\n"); + service_manager_alive = true; + break; + } + if (token == BR_DEAD_REPLY || token == BR_FAILED_REPLY) { + CCEC_LOG(LOG_ERROR, "[-] Driver faulted payload execution target. Status: 0x%x\n", token); + break; + } + if (token == BR_TRANSACTION_COMPLETE || token == BR_TRANSACTION_COMPLETE_V7) { + CCEC_LOG(LOG_INFO, "[+] Transaction safely handed off to Binder kernel layer.\n"); + continue; + } + if (token == BR_NOOP || token == BR_OK || token == BR_OK_V7) { + continue; + } + + // Safety Fallback for unexpected or structural multi-word response components + CCEC_LOG(LOG_WARN, "[!] Structural bound reached or unhandled response code. Breaking parsing thread loop.\n"); + break; + } + + return service_manager_alive; +} + +} // namespace + +bool isServiceManagerAvailable() { + bool service_manager_alive = false; + + const int binder_fd = open("/dev/binder", O_RDWR | O_CLOEXEC); + if (binder_fd < 0) { + CCEC_LOG(LOG_ERROR, "[-] Failed to open /dev/binder\n"); + return service_manager_alive; + } + CCEC_LOG(LOG_INFO, "[+] Successfully opened /dev/binder\n"); + + binder_version version{}; + if (ioctl(binder_fd, BINDER_VERSION, &version) < 0) { + CCEC_LOG(LOG_ERROR, "[-] Failed to extract device driver protocol revision metadata\n"); + close(binder_fd); + return service_manager_alive; + } + CCEC_LOG(LOG_INFO, "[+] Binder protocol version detected: %d\n", version.protocol_version); + + const size_t binder_map_size = (version.protocol_version == 7) ? BINDER_MMAP_SIZE_V7 : BINDER_MMAP_SIZE_V8; + void* const mapped_mem = mmap(nullptr, binder_map_size, PROT_READ, MAP_PRIVATE, binder_fd, 0); + if (mapped_mem == MAP_FAILED) { + CCEC_LOG(LOG_ERROR, "[-] Shared address space context instantiation failed\n"); + close(binder_fd); + return service_manager_alive; + } + CCEC_LOG(LOG_INFO, "[+] Memory mapped successfully\n"); + + const bool ping_result = execute_binder_ping(binder_fd, version.protocol_version); + service_manager_alive = ping_result; + + munmap(mapped_mem, binder_map_size); + close(binder_fd); + return service_manager_alive; +} diff --git a/ccec/src/factoryImpl/ServiceManagerCheck.h b/ccec/src/factoryImpl/ServiceManagerCheck.h new file mode 100644 index 00000000..86801afc --- /dev/null +++ b/ccec/src/factoryImpl/ServiceManagerCheck.h @@ -0,0 +1,28 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2016 RDK Management + * + * 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 SERVICEMANAGER_CHECK_H +#define SERVICEMANAGER_CHECK_H + +bool isServiceManagerAvailable(); + +#endif // SERVICEMANAGER_CHECK_H + + + From 9e492e849977fb9d37dfa52d8cf1af69186325a9 Mon Sep 17 00:00:00 2001 From: kdarma930_comcast Date: Mon, 15 Jun 2026 12:25:56 +0000 Subject: [PATCH 02/10] Handle AIDL poll fallback for CEC device discovery --- .github/workflows/L1-tests.yml | 384 ++++++++++++++++++- ccec/src/DriverImpl.cpp | 43 +-- ccec/src/DriverImpl.hpp | 2 - ccec/src/Makefile | 2 - ccec/src/Makefile.am | 3 - ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 219 ++++++----- ccec/src/factoryImpl/HDMICecAidlHAL.h | 19 +- ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 9 - ccec/src/factoryImpl/HDMICecRdkVHAL.h | 13 - ccec/src/factoryImpl/IHDMICecHal.h | 25 +- ccec/src/factoryImpl/ServiceManagerCheck.cpp | 13 +- ccec/src/factoryImpl/ServiceManagerCheck.h | 3 - 12 files changed, 530 insertions(+), 205 deletions(-) diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 64fd73c4..25963c45 100644 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -74,23 +74,375 @@ jobs: cmake --install build/googletest - name: Generate stub headers - # Empty headers to mute errors - run: > + run: | + set -e cd "$GITHUB_WORKSPACE/hdmicec" - && - mkdir -p - stubs/rdk/iarmbus - stubs/ccec/drivers/iarmbus - && - cd stubs - && - touch - rdk/iarmbus/libIARM.h - rdk/iarmbus/libIBus.h - rdk/iarmbus/libIBusDaemon.h - ccec/drivers/iarmbus/CecIARMBusMgr.h - && - ln -s ../../../mocks/hdmicec/hdmi_cec_driver.h ccec/drivers/hdmi_cec_driver.h + mkdir -p \ + stubs/rdk/iarmbus \ + stubs/ccec/drivers/iarmbus \ + stubs/binder \ + stubs/utils \ + stubs/linux/android \ + stubs/com/rdk/hal/hdmicec + + touch \ + stubs/rdk/iarmbus/libIARM.h \ + stubs/rdk/iarmbus/libIBus.h \ + stubs/rdk/iarmbus/libIBusDaemon.h \ + stubs/ccec/drivers/iarmbus/CecIARMBusMgr.h + + ln -sf ../../../mocks/hdmicec/hdmi_cec_driver.h stubs/ccec/drivers/hdmi_cec_driver.h + + cat <<'EOF' > stubs/utils/String16.h + #ifndef STUB_UTILS_STRING16_H + #define STUB_UTILS_STRING16_H + + #include + + namespace android { + class String16 { + public: + String16() = default; + explicit String16(const char* value) : mValue(value ? value : "") {} + explicit String16(const std::string& value) : mValue(value) {} + + const std::string& str() const { return mValue; } + + friend bool operator==(const String16& lhs, const String16& rhs) { return lhs.mValue == rhs.mValue; } + friend bool operator!=(const String16& lhs, const String16& rhs) { return !(lhs == rhs); } + + private: + std::string mValue; + }; + } + + #endif + EOF + + cat <<'EOF' > stubs/utils/String8.h + #ifndef STUB_UTILS_STRING8_H + #define STUB_UTILS_STRING8_H + + #include + #include "String16.h" + + namespace android { + class String8 { + public: + String8() = default; + explicit String8(const char* value) : mValue(value ? value : "") {} + explicit String8(const String16& value) : mValue(value.str()) {} + + const char* c_str() const { return mValue.c_str(); } + const char* string() const { return mValue.c_str(); } + + private: + std::string mValue; + }; + } + + #endif + EOF + + cat <<'EOF' > stubs/utils/Vector.h + #ifndef STUB_UTILS_VECTOR_H + #define STUB_UTILS_VECTOR_H + + #include + + namespace android { + template + using Vector = std::vector; + } + + #endif + EOF + + cat <<'EOF' > stubs/binder/IServiceManager.h + #ifndef STUB_BINDER_ISERVICE_MANAGER_H + #define STUB_BINDER_ISERVICE_MANAGER_H + + #include + #include + #include + #include "utils/String16.h" + #include "utils/String8.h" + #include "utils/Vector.h" + + namespace android { + template + class sp { + public: + sp() = default; + sp(std::nullptr_t) : mPtr(nullptr) {} + sp(T* ptr) : mPtr(ptr) {} + sp(const std::shared_ptr& ptr) : mPtr(ptr) {} + + T* get() const { return mPtr.get(); } + T* operator->() const { return mPtr.get(); } + operator bool() const { return static_cast(mPtr); } + bool operator==(std::nullptr_t) const { return mPtr == nullptr; } + bool operator!=(std::nullptr_t) const { return mPtr != nullptr; } + sp& operator=(T* ptr) { mPtr.reset(ptr); return *this; } + + private: + std::shared_ptr mPtr; + }; + + class IBinder { + public: + virtual ~IBinder() = default; + }; + + namespace binder { + class Status { + public: + Status() : mOk(true), mMessage("OK") {} + explicit Status(bool ok, std::string message = "OK") : mOk(ok), mMessage(std::move(message)) {} + + static Status ok() { return Status(true, "OK"); } + bool isOk() const { return mOk; } + String8 toString8() const { return String8(mMessage.c_str()); } + + private: + bool mOk; + std::string mMessage; + }; + } + + class IServiceManager { + public: + virtual ~IServiceManager() = default; + virtual sp getService(const String16&) { return sp(nullptr); } + virtual Vector listServices() { return {}; } + }; + + class StubServiceManager : public IServiceManager {}; + + inline sp defaultServiceManager() { + static sp manager(new StubServiceManager()); + return manager; + } + + template + sp interface_cast(const sp&) { + return sp(new T()); + } + } + + #endif + EOF + + cat <<'EOF' > stubs/binder/ProcessState.h + #ifndef STUB_BINDER_PROCESS_STATE_H + #define STUB_BINDER_PROCESS_STATE_H + + namespace android { + class ProcessState { + public: + static ProcessState* self() { + static ProcessState instance; + return &instance; + } + + void startThreadPool() {} + }; + } + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/SendMessageStatus.h + #ifndef STUB_HDMICEC_SEND_MESSAGE_STATUS_H + #define STUB_HDMICEC_SEND_MESSAGE_STATUS_H + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + enum class SendMessageStatus { + ACK_STATE_0 = 0, + ACK_STATE_1 = 1, + BUSY = 2 + }; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/State.h + #ifndef STUB_HDMICEC_STATE_H + #define STUB_HDMICEC_STATE_H + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + enum class State { + UNKNOWN = 0, + IDLE = 1, + ACTIVE = 2 + }; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h + #ifndef STUB_HDMICEC_EVENT_LISTENER_H + #define STUB_HDMICEC_EVENT_LISTENER_H + + #include + #include "binder/IServiceManager.h" + #include "com/rdk/hal/hdmicec/SendMessageStatus.h" + #include "com/rdk/hal/hdmicec/State.h" + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + class IHdmiCecEventListener : public android::IBinder { + public: + virtual ~IHdmiCecEventListener() = default; + virtual android::binder::Status onMessageReceived(const std::vector&) { return android::binder::Status::ok(); } + virtual android::binder::Status onStateChanged(State, State) { return android::binder::Status::ok(); } + virtual android::binder::Status onMessageSent(const std::vector&, SendMessageStatus) { return android::binder::Status::ok(); } + }; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h + #ifndef STUB_BN_HDMICEC_EVENT_LISTENER_H + #define STUB_BN_HDMICEC_EVENT_LISTENER_H + + #include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + class BnHdmiCecEventListener : public IHdmiCecEventListener {}; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCecController.h + #ifndef STUB_HDMICEC_CONTROLLER_H + #define STUB_HDMICEC_CONTROLLER_H + + #include + #include + #include "binder/IServiceManager.h" + #include "com/rdk/hal/hdmicec/SendMessageStatus.h" + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + class IHdmiCecController : public android::IBinder { + public: + virtual ~IHdmiCecController() = default; + + virtual android::binder::Status addLogicalAddresses(const std::vector&, bool* result) { + if (result) { *result = true; } + return android::binder::Status::ok(); + } + + virtual android::binder::Status removeLogicalAddresses(const std::vector&, bool* result) { + if (result) { *result = true; } + return android::binder::Status::ok(); + } + + virtual android::binder::Status sendMessage(const std::vector&, SendMessageStatus* status) { + if (status) { *status = SendMessageStatus::ACK_STATE_0; } + return android::binder::Status::ok(); + } + }; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCec.h + #ifndef STUB_HDMICEC_H + #define STUB_HDMICEC_H + + #include + #include + #include "binder/IServiceManager.h" + #include "com/rdk/hal/hdmicec/IHdmiCecController.h" + #include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" + + namespace com { namespace rdk { namespace hal { namespace hdmicec { + class IHdmiCec : public android::IBinder { + public: + virtual ~IHdmiCec() = default; + + static std::string serviceName() { return "com.rdk.hal.hdmicec.IHdmiCec/default"; } + + virtual android::binder::Status open(const android::sp&, android::sp* controller) { + if (controller) { *controller = android::sp(new IHdmiCecController()); } + return android::binder::Status::ok(); + } + + virtual android::binder::Status close(const android::sp&, bool* result) { + if (result) { *result = true; } + return android::binder::Status::ok(); + } + + virtual android::binder::Status getLogicalAddresses(std::vector* addresses) { + if (addresses) { addresses->clear(); } + return android::binder::Status::ok(); + } + }; + }}}} + + #endif + EOF + + cat <<'EOF' > stubs/linux/android/binder.h + #ifndef STUB_LINUX_ANDROID_BINDER_H + #define STUB_LINUX_ANDROID_BINDER_H + + #include + #include + + typedef uintptr_t binder_uintptr_t; + + struct binder_version { + int32_t protocol_version; + }; + + struct binder_write_read { + uint64_t write_size; + uint64_t write_consumed; + binder_uintptr_t write_buffer; + uint64_t read_size; + uint64_t read_consumed; + binder_uintptr_t read_buffer; + }; + + struct binder_transaction_data { + union { + uint32_t handle; + binder_uintptr_t ptr; + } target; + binder_uintptr_t cookie; + uint32_t code; + uint32_t flags; + int32_t sender_pid; + int32_t sender_euid; + uint64_t data_size; + uint64_t offsets_size; + union { + struct { + binder_uintptr_t buffer; + binder_uintptr_t offsets; + } ptr; + uint8_t buf[8]; + } data; + }; + + #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) + #define BC_TRANSACTION 0x0 + #define TF_ACCEPT_FDS 0x10 + #define BR_REPLY 0x1 + #define BR_DEAD_REPLY 0x2 + #define BR_FAILED_REPLY 0x3 + #define BR_TRANSACTION_COMPLETE 0x4 + #define BR_NOOP 0x5 + #define BR_OK 0x6 + + #endif + EOF - name: Build hdmicec run: > diff --git a/ccec/src/DriverImpl.cpp b/ccec/src/DriverImpl.cpp index 850eb426..371df710 100644 --- a/ccec/src/DriverImpl.cpp +++ b/ccec/src/DriverImpl.cpp @@ -36,12 +36,8 @@ #include #include #include -#include -#include -#include #include #include -#include #include "osal/EventQueue.hpp" #include "osal/Exception.hpp" @@ -75,7 +71,6 @@ void DriverImpl::DriverReceiveCallback(int handle, void *callbackData, unsigned } catch(...) { CCEC_LOG( LOG_EXP, "Exception during frame offer...discarding\r\n"); - // Copilot fix: Delete frame to prevent memory leak when offer() throws exception delete frame; } CCEC_LOG( LOG_DEBUG, "frame offered\r\n"); @@ -212,16 +207,11 @@ void DriverImpl::writeAsync(const CECFrame &frame) noexcept(false) frame.getBuffer(&buf, &length); printFrameDetails(frame); - { - AutoLock lock_(mutex); + {AutoLock lock_(mutex); if (status != OPENED) { throw InvalidStateException(); } - if(mHal->skipFrameOfUnsupportedLength(length)) { - return; - } - CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTxAsync\r\n"); int err = mHal->txAsync(nativeHandle, buf, length); @@ -239,7 +229,7 @@ void DriverImpl::writeAsync(const CECFrame &frame) noexcept(false) } } - CCEC_LOG( LOG_DEBUG, "Send Async Completed\r\n"); + CCEC_LOG( LOG_DEBUG, "Send Async Completed\r\n"); } @@ -255,16 +245,10 @@ void DriverImpl::write(const CECFrame &frame) noexcept(false) frame.getBuffer(&buf, &length); printFrameDetails(frame); - { - AutoLock lock_(mutex); + {AutoLock lock_(mutex); if (status != OPENED) { throw InvalidStateException(); } - - if(mHal->emulateAckForPollFrames(buf, length)) { - return; - } - int sendResult = HDMI_CEC_IO_SUCCESS; CCEC_LOG( LOG_DEBUG, "DriverImpl::write to call HdmiCecTx\r\n"); @@ -282,16 +266,16 @@ void DriverImpl::write(const CECFrame &frame) noexcept(false) throw IOException(); } - if (sendResult != HDMI_CEC_IO_SUCCESS) { - if ((sendResult == HDMI_CEC_IO_INVALID_HANDLE) || - (sendResult == HDMI_CEC_IO_INVALID_ARGUMENT) || - (sendResult == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) || - (sendResult == HDMI_CEC_IO_SENT_FAILED) || - (sendResult == HDMI_CEC_IO_GENERAL_ERROR)) - { - throw IOException(); - } - } + if (sendResult != HDMI_CEC_IO_SUCCESS) { + if ((sendResult == HDMI_CEC_IO_INVALID_HANDLE) || + (sendResult == HDMI_CEC_IO_INVALID_ARGUMENT) || + (sendResult == HDMI_CEC_IO_LOGICALADDRESS_UNAVAILABLE) || + (sendResult == HDMI_CEC_IO_SENT_FAILED) || + (sendResult == HDMI_CEC_IO_GENERAL_ERROR)) + { + throw IOException(); + } + } if (((frame.at(0) & 0x0F) != 0x0F) && sendResult == HDMI_CEC_IO_SENT_BUT_NOT_ACKD) { throw CECNoAckException(); @@ -439,5 +423,6 @@ void DriverImpl::printFrameDetails(const CECFrame &frame) noexcept(false) { CCEC_END_NAMESPACE + /** @} */ /** @} */ diff --git a/ccec/src/DriverImpl.hpp b/ccec/src/DriverImpl.hpp index aeb88127..64830de8 100644 --- a/ccec/src/DriverImpl.hpp +++ b/ccec/src/DriverImpl.hpp @@ -32,7 +32,6 @@ #include #include - #include "osal/Mutex.hpp" #include "osal/EventQueue.hpp" @@ -103,4 +102,3 @@ CCEC_END_NAMESPACE /** @} */ /** @} */ - diff --git a/ccec/src/Makefile b/ccec/src/Makefile index e1c545d1..e5510ecb 100755 --- a/ccec/src/Makefile +++ b/ccec/src/Makefile @@ -97,5 +97,3 @@ library: $(OBJS) clean: @echo "Cleaning the directory..." @$(RM) $(OBJS) install - - diff --git a/ccec/src/Makefile.am b/ccec/src/Makefile.am index 7600cae7..6789fc1d 100644 --- a/ccec/src/Makefile.am +++ b/ccec/src/Makefile.am @@ -40,6 +40,3 @@ libRCEC_la_SOURCES = CECFrame.cpp \ libRCEC_la_LDFLAGS = -lpthread libRCEC_la_LIBADD = ${top_builddir}/osal/src/libRCECOSHal.la - - - diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index 4040d1a4..f62a997a 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -72,6 +71,24 @@ class HDMICecAidlHALEventListener : public BnHdmiCecEventListener { HDMICecAidlHAL *mAidlHal; }; + +// Return the standard logical-address candidates for a given device type. +// Used only as a fallback when AIDL reports no allocated addresses yet. +std::vector preferredLogicalAddressesForDeviceType(int devType) +{ + // Common CEC type ids used in middleware: + // 0: TV, 1: RecordingDevice, 3: Tuner, 4: PlaybackDevice, 5: AudioSystem. + switch (devType) { + case 0: return std::vector{0}; // TV + case 1: return std::vector{1, 2, 9}; // Recorder + case 3: return std::vector{3, 6, 7, 10}; // Tuner + case 5: return std::vector{5}; // AudioSystem + case 4: + default: + return std::vector{4, 8, 11}; // PlaybackDevice fallback + } +} + HDMICecAidlHAL::HDMICecAidlHAL() : mAidlService(nullptr), mAidlController(nullptr), @@ -91,51 +108,6 @@ HDMICecAidlHAL::~HDMICecAidlHAL() mEventListener = nullptr; } -bool HDMICecAidlHAL::parseLogicalAddressField(const std::string& line, const char* field, int& value) -{ - const size_t keyPos = line.find(field); - if (keyPos == std::string::npos) { - return false; - } - - const size_t valueStart = line.find_first_not_of(" \t", keyPos + strlen(field)); - if (valueStart == std::string::npos) { - return false; - } - - char* endPtr = nullptr; - const long parsed = std::strtol(line.c_str() + valueStart, &endPtr, 10); - if (endPtr == (line.c_str() + valueStart)) { - return false; - } - - value = static_cast(parsed); - return true; -} - -bool HDMICecAidlHAL::isPresentInVdeviceTopology(const uint8_t destination) -{ - std::ifstream topology(kVdeviceTopologyDump); - if (!topology.is_open()) { - return false; - } - - std::string line; - while (std::getline(topology, line)) { - int logicalAddr = -1; - if (parseLogicalAddressField(line, "Logical-1:", logicalAddr) && logicalAddr == static_cast(destination)) { - return true; - } - - logicalAddr = -1; - if (parseLogicalAddressField(line, "Logical-2:", logicalAddr) && logicalAddr == static_cast(destination)) { - return true; - } - } - - return false; -} - android::sp HDMICecAidlHAL::getAidlService() { AutoLock lock_(mAidlMutex); @@ -168,12 +140,16 @@ int HDMICecAidlHAL::open(int *handle) { CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::open invoked\n"); + if (handle == nullptr) { + CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::open failed: invalid handle pointer\r\n"); + throw IOException(); + } + android::sp service = getAidlService(); if (service == nullptr) { CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::open failed: IHdmiCec service unavailable\r\n"); throw IOException(); } - // Create event listener mEventListener = new HDMICecAidlHALEventListener(this); @@ -196,7 +172,7 @@ int HDMICecAidlHAL::open(int *handle) int HDMICecAidlHAL::close(int handle) { CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::close invoked\n"); - (void)handle; + (void)handle; if (mAidlController != nullptr) { android::sp service = getAidlService(); @@ -204,6 +180,7 @@ int HDMICecAidlHAL::close(int handle) bool result = false; android::binder::Status status = service->close(mAidlController, &result); if (!status.isOk()) { + CCEC_LOG(LOG_EXP, "Failed to close AIDL HdmiCec interface: %s\r\n", status.toString8().c_str()); CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::close failed: service->close status not OK\n"); throw IOException(); } @@ -223,18 +200,18 @@ int HDMICecAidlHAL::close(int handle) int HDMICecAidlHAL::addLogicalAddress(int handle, int logicalAddresses) { + (void)handle; if (mAidlController == nullptr) { throw IOException(); } - std::vector addresses; addresses.push_back(logicalAddresses); bool result = false; android::binder::Status status = mAidlController->addLogicalAddresses(addresses, &result); if (!status.isOk()) { - CCEC_LOG(LOG_EXP, "Failed to add logical address via AIDL: %s\r\n", status.toString8().c_str()); - throw IOException(); + CCEC_LOG(LOG_EXP, "Failed to add logical address via AIDL: %s\r\n", status.toString8().c_str()); + throw IOException(); } if (!result) { @@ -247,6 +224,7 @@ int HDMICecAidlHAL::addLogicalAddress(int handle, int logicalAddresses) int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) { + (void)handle; if (mAidlController == nullptr) { throw IOException(); } @@ -255,10 +233,10 @@ int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) addresses.push_back(logicalAddresses); bool result = false; android::binder::Status status = mAidlController->removeLogicalAddresses(addresses, &result); - if (!status.isOk() || !result) { - CCEC_LOG(LOG_EXP, "Failed to remove logical address via AIDL: %s\n", status.toString8().c_str()); - throw IOException(); - } + if (!status.isOk() || !result) { + CCEC_LOG(LOG_EXP, "Failed to remove logical address via AIDL: %s\n", status.toString8().c_str()); + throw IOException(); + } CCEC_LOG(LOG_DEBUG, "Successfully removed logical address via AIDL\n"); return 0; @@ -266,26 +244,52 @@ int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) int HDMICecAidlHAL::getLogicalAddress(int handle, int *logicalAddress) { + (void)handle; if (logicalAddress == nullptr) { CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::getLogicalAddress invalid output pointer\r\n"); throw IOException(); } *logicalAddress = 0; - - if (mAidlService == nullptr) { - android::sp service = getAidlService(); - if (service == nullptr) { + if (mAidlService == nullptr) { + android::sp service = getAidlService(); + if (service == nullptr) { throw IOException(); - } - mAidlService = service; - } + } + mAidlService = service; + } std::vector addresses; android::binder::Status status = mAidlService->getLogicalAddresses(&addresses); if (status.isOk() && addresses.size() > 0) { *logicalAddress = addresses[0]; + }else { + CCEC_LOG(LOG_WARN, + "DriverImpl::getLogicalAddress no allocated LA from AIDL (statusOk=%d, count=%zu). Trying fallback allocation.\r\n", + status.isOk() ? 1 : 0, + addresses.size()); + if (mAidlController != nullptr) { + const std::vector preferred = preferredLogicalAddressesForDeviceType(*logicalAddress); + for (std::vector::const_iterator it = preferred.begin(); it != preferred.end(); ++it) { + std::vector candidate; + candidate.push_back(*it); + bool addResult = false; + android::binder::Status addStatus = mAidlController->addLogicalAddresses(candidate, &addResult); + CCEC_LOG(LOG_DEBUG, + "DriverImpl::getLogicalAddress fallback addLogicalAddresses candidate=%d addOk=%d addResult=%d\r\n", + candidate[0], + addStatus.isOk() ? 1 : 0, + addResult ? 1 : 0); + addresses.clear(); + android::binder::Status retryStatus = mAidlService->getLogicalAddresses(&addresses); + if (retryStatus.isOk() && addresses.size() > 0) { + *logicalAddress = addresses[0]; + break; + } + } + } } + CCEC_LOG( LOG_DEBUG, "HDMICecAidlHAL::getLogicalAddress completed\r\n"); @@ -310,6 +314,14 @@ void HDMICecAidlHAL::dispatchRx(unsigned char *buf, int len) return; } + // Track initiator LA from inbound frames so 1-byte poll can be emulated + // locally on AIDL backends that reject 1-byte sendMessage payloads. + if (buf != nullptr && len >= 1) { + const uint8_t srcLA = static_cast((buf[0] >> 4) & 0x0F); + if (srcLA <= 0x0E) { + mSeenLogicalAddresses.insert(srcLA); + } + } mRxCb(0, mRxCbData, buf, len); } @@ -347,9 +359,10 @@ int HDMICecAidlHAL::setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void * int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *result) { + (void)handle; if (mAidlController == nullptr) { - throw IOException(); - } + throw IOException(); + } if (result == nullptr) { CCEC_LOG(LOG_ERROR, "HDMICecAidlHAL::tx invalid result pointer\n"); @@ -361,12 +374,17 @@ int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *resul throw IOException(); } + if(emulateAckForPollFrames(buf, len)) { + *result = 0; // HDMI_CEC_IO_SUCCESS + return 0; + } + std::vector message(buf, buf + len); SendMessageStatus sendStatus; android::binder::Status status = mAidlController->sendMessage(message, &sendStatus); if (!status.isOk()) { CCEC_LOG(LOG_ERROR, "AIDL sendMessage failed: %s\r\n", status.toString8().c_str()); - throw IOException(); + throw IOException(); } // Map AIDL SendMessageStatus to HAL error codes @@ -387,6 +405,7 @@ int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *resul int HDMICecAidlHAL::txAsync(int handle, const unsigned char *buf, int len) { + (void)handle; if (mAidlController == nullptr) { throw IOException(); } @@ -400,7 +419,7 @@ int HDMICecAidlHAL::txAsync(int handle, const unsigned char *buf, int len) android::binder::Status status = mAidlController->sendMessage(message, &sendStatus); if (!status.isOk()) { CCEC_LOG(LOG_ERROR, "AIDL sendMessage failed: %s\r\n", status.toString8().c_str()); - throw IOException(); + throw IOException(); } if (sendStatus == SendMessageStatus::BUSY) { @@ -415,48 +434,66 @@ int HDMICecAidlHAL::txAsync(int handle, const unsigned char *buf, int len) return 0; } -bool HDMICecAidlHAL::skipFrameOfUnsupportedLength(size_t length) { - if (length < kAidlMinCecFrameSize || length > kAidlMaxCecFrameSize) { - /* AIDL sendMessage accepts only 2..16 byte CEC frames. */ - CCEC_LOG(LOG_WARN, - "DriverImpl::writeAsync skipping unsupported CEC frame length=%zu on AIDL backend (valid range: 2..16).\r\n", - length); - return true; - } - - return false; -} - bool HDMICecAidlHAL::emulateAckForPollFrames(const unsigned char *buf, int len) { if (len <= 1) { /* - * Poll frame (header only): emulate ACK based on vdevice topology file. - * This keeps HdmiCecSource ping-based discovery working on AIDL backend. - */ + * Poll frame (header only): emulate ACK based on seen-LA cache + * and 2-byte probe. This keeps HdmiCecSource ping-based discovery + * working on AIDL backend. + */ const uint8_t destination = (buf != NULL) ? (buf[0] & 0x0F) : 0xFF; - const bool addressPresent = (destination <= 0x0E) ? isPresentInVdeviceTopology(destination) : false; - if (addressPresent) { - CCEC_LOG(LOG_DEBUG, - "DriverImpl::write poll-frame destination=0x%X present in topology. Emulating ack.\r\n", - destination); - return true; + if (destination <= 0x0E) { + /* Check seen-LA cache first */ + { + AutoLock lock_(mAidlMutex); + if (mSeenLogicalAddresses.count(destination) > 0) { + CCEC_LOG(LOG_DEBUG, + "HDMICecAidlHAL::emulateAckForPollFrames destination=0x%X present in seen-LA set. Emulating ack.\r\n", + destination); + return true; + } + } + + /* Probe with a 2-byte directed frame (GiveDevicePowerStatus) */ + { + AutoLock lock_(mAidlMutex); + std::vector probe; + probe.reserve(2); + probe.push_back(buf ? buf[0] : 0); + probe.push_back(0x8F); // GiveDevicePowerStatus + + SendMessageStatus probeStatus = SendMessageStatus::BUSY; + android::binder::Status aidlStatus = mAidlController->sendMessage(probe, &probeStatus); + if (aidlStatus.isOk() && probeStatus == SendMessageStatus::ACK_STATE_0) { + mSeenLogicalAddresses.insert(destination); + CCEC_LOG(LOG_DEBUG, + "HDMICecAidlHAL::emulateAckForPollFrames destination=0x%X ACKed by 2-byte probe. Emulating ack.\r\n", + destination); + return true; + } + + CCEC_LOG(LOG_DEBUG, + "HDMICecAidlHAL::emulateAckForPollFrames destination=0x%X probe NACK/failed (aidlOk=%d status=%d).\r\n", + destination, + aidlStatus.isOk() ? 1 : 0, + static_cast(probeStatus)); + } } CCEC_LOG(LOG_DEBUG, - "DriverImpl::write poll-frame destination=0x%X not present in topology. Returning no-ack.\r\n", - destination); + "HDMICecAidlHAL::emulateAckForPollFrames destination=0x%X not present. Returning no-ack.\r\n", + (buf != NULL) ? (buf[0] & 0x0F) : 0xFF); throw CECNoAckException(); } if (static_cast(len) > kAidlMaxCecFrameSize) { CCEC_LOG(LOG_EXP, - "DriverImpl::write blocking unsupported CEC frame length=%zu on AIDL backend (valid range: 2..16).\r\n", + "HDMICecAidlHAL::emulateAckForPollFrames blocking unsupported CEC frame length=%zu on AIDL backend (valid range: 2..16).\r\n", static_cast(len)); throw IOException(); } return false; } - diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.h b/ccec/src/factoryImpl/HDMICecAidlHAL.h index 3cd28163..15aeb689 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.h +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.h @@ -23,7 +23,8 @@ #include "IHDMICecHal.h" #include - #include +#include +#include #include #include #include @@ -55,20 +56,20 @@ class HDMICecAidlHAL : public IHDMICecHal { int setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) override; int tx(int handle, const unsigned char *buf, int len, int *result) override; int txAsync(int handle, const unsigned char *buf, int len) override; - bool skipFrameOfUnsupportedLength(size_t length) override; - bool emulateAckForPollFrames(const unsigned char *buf, int len) override; private: const size_t kAidlMinCecFrameSize = 2; const size_t kAidlMaxCecFrameSize = 16; - static constexpr const char* kVdeviceTopologyDump = "/tmp/hdmi_cec_device_list_info.txt"; - - bool parseLogicalAddressField(const std::string& line, const char* field, int& value); - bool isPresentInVdeviceTopology(const uint8_t destination); android::sp getAidlService(); void initAidlService(); void dispatchRx(unsigned char *buf, int len); void dispatchTx(int result); + /** + * @brief Emulate ACK for Poll messages + * This allows the driver to treat Poll frames as if they were ACKed, + * ensuring proper handling of device presence on the bus. + */ + bool emulateAckForPollFrames(const unsigned char *buf, int len); android::sp mAidlService; android::sp mAidlController; @@ -78,6 +79,10 @@ class HDMICecAidlHAL : public IHDMICecHal { void* mRxCbData; void* mTxCbData; mutable Mutex mAidlMutex; + // Logical addresses seen on inbound CEC frames. + // Used to emulate poll ACK/NACK locally because some AIDL backends + // reject 1-byte poll frames as invalid message size. + std::set mSeenLogicalAddresses; friend class HDMICecAidlHALEventListener; }; diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp index c19e05f6..623461ce 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -150,12 +150,3 @@ int HDMICecRdkVHAL::getPhysicalAddress(int handle, unsigned int *physicalAddress return ret; } -bool HDMICecRdkVHAL::skipFrameOfUnsupportedLength(size_t length) { - return false; -} - -bool HDMICecRdkVHAL::emulateAckForPollFrames(const unsigned char *buf, int len) -{ - // No emulation for HDMICecRdkVHAL - return false; -} diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.h b/ccec/src/factoryImpl/HDMICecRdkVHAL.h index adbbac79..944cff22 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.h +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.h @@ -89,19 +89,6 @@ class HDMICecRdkVHAL : public IHDMICecHal { * Calls HdmiCecGetPhysicalAddress(). */ int getPhysicalAddress(int handle, unsigned int *physicalAddress) override; - - /** - * @brief Determine if a received frame of the given length should be skipped - * because its length is unsupported by the legacy HAL. - */ - bool skipFrameOfUnsupportedLength(size_t length) override; - - /** - * @brief Emulate ACK for Poll messages, which the legacy HAL does not support. - * This allows the driver to treat Poll frames as if they were ACKed, - * ensuring proper handling of device presence on the bus. - */ - bool emulateAckForPollFrames(const unsigned char *buf, int len) override; }; #endif // HDMI_CEC_RDK_V_HAL_H diff --git a/ccec/src/factoryImpl/IHDMICecHal.h b/ccec/src/factoryImpl/IHDMICecHal.h index 55b0b1c8..4c2b22b7 100644 --- a/ccec/src/factoryImpl/IHDMICecHal.h +++ b/ccec/src/factoryImpl/IHDMICecHal.h @@ -21,6 +21,8 @@ #define I_HDMI_CEC_HAL_H #include +#include +#include #include "ccec/drivers/hdmi_cec_driver.h" /** @@ -158,29 +160,6 @@ class IHDMICecHal { * @return HDMI_CEC_IO_SUCCESS on success, or an error code. */ virtual int getPhysicalAddress(int handle, unsigned int *physicalAddress) = 0; - - /** - * @brief Check if a frame of unsupported length should be skipped. - * - * Legacy: no-op (returns false). - * AIDL: validates frame length against binder service constraints. - * - * @param[in] length Length of the CEC frame. - * @return true if the frame should be skipped, false otherwise. - */ - virtual bool skipFrameOfUnsupportedLength(size_t length) = 0; - - /** - * @brief Emulate acknowledgment for poll frames. - * - * Legacy: Ignores this as the legacy HAL does not support emulating ACKs. - * AIDL: Check Vdevice topology to determine emulation required or not - * - * @param[in] buf Buffer containing the CEC frame. - * @param[in] len Length of the CEC frame. - * @return true if acknowledgment should be emulated, false otherwise. - */ - virtual bool emulateAckForPollFrames(const unsigned char *buf, int len) = 0; }; #endif // I_HDMI_CEC_HAL_H diff --git a/ccec/src/factoryImpl/ServiceManagerCheck.cpp b/ccec/src/factoryImpl/ServiceManagerCheck.cpp index 42780c91..a35478d0 100644 --- a/ccec/src/factoryImpl/ServiceManagerCheck.cpp +++ b/ccec/src/factoryImpl/ServiceManagerCheck.cpp @@ -18,13 +18,12 @@ * ServiceManagerCheck.cpp — Checking the availability of the Android ServiceManager via Binder IPC. * */ - #include #include #include #include +#include #include -#include #include #include #include @@ -107,9 +106,9 @@ static BinderTransaction prepare_v7_transaction() { const size_t tx_words = sizeof(txn) / sizeof(uint32_t); tx.write_payload.reserve(1 + tx_words); tx.write_payload.push_back(BC_TRANSACTION_V7); - - const auto* raw_ptr = reinterpret_cast(&txn); - tx.write_payload.insert(tx.write_payload.end(), raw_ptr, raw_ptr + tx_words); + + tx.write_payload.resize(1 + tx_words); + std::memcpy(tx.write_payload.data() + 1, &txn, sizeof(txn)); tx.read_payload.resize(256, 0); return tx; } @@ -131,8 +130,8 @@ static BinderTransaction prepare_v8_transaction() { tx.write_payload.reserve(1 + tx_words); tx.write_payload.push_back(BC_TRANSACTION); - const auto* raw_ptr = reinterpret_cast(&txn); - tx.write_payload.insert(tx.write_payload.end(), raw_ptr, raw_ptr + tx_words); + tx.write_payload.resize(1 + tx_words); + std::memcpy(tx.write_payload.data() + 1, &txn, sizeof(txn)); tx.read_payload.resize(256, 0); return tx; } diff --git a/ccec/src/factoryImpl/ServiceManagerCheck.h b/ccec/src/factoryImpl/ServiceManagerCheck.h index 86801afc..2c5ae890 100644 --- a/ccec/src/factoryImpl/ServiceManagerCheck.h +++ b/ccec/src/factoryImpl/ServiceManagerCheck.h @@ -23,6 +23,3 @@ bool isServiceManagerAvailable(); #endif // SERVICEMANAGER_CHECK_H - - - From 3521d797bc44bce6f6f3e3c5d823400129ee4426 Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Mon, 22 Jun 2026 10:48:13 +0530 Subject: [PATCH 03/10] Removed unwanted logs. --- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 9 +++----- ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 30 +++++++++---------------- 2 files changed, 13 insertions(+), 26 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index f62a997a..a1792dc8 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -165,7 +165,6 @@ int HDMICecAidlHAL::open(int *handle) *handle = 1; /* Dummy handle — AIDL uses controller object */ - CCEC_LOG(LOG_INFO, "HDMICecAidlHAL::open completed successfully\r\n"); return 0; } @@ -218,7 +217,7 @@ int HDMICecAidlHAL::addLogicalAddress(int handle, int logicalAddresses) throw AddressNotAvailableException(); } - CCEC_LOG(LOG_DEBUG, "Successfully added logical address via AIDL\n"); + CCEC_LOG(LOG_DEBUG, "Successfully added logical address addr=%d via AIDL\n", logicalAddresses); return 0; } @@ -238,7 +237,7 @@ int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) throw IOException(); } - CCEC_LOG(LOG_DEBUG, "Successfully removed logical address via AIDL\n"); + CCEC_LOG(LOG_DEBUG, "Successfully removed logical address addr=%d via AIDL\n", logicalAddresses); return 0; } @@ -427,9 +426,7 @@ int HDMICecAidlHAL::txAsync(int handle, const unsigned char *buf, int len) throw IOException(); } - CCEC_LOG( LOG_DEBUG, "AIDL sendMessage completed, status: %d\r\n", static_cast(sendStatus)); - - CCEC_LOG( LOG_DEBUG, "Send Async Completed\n"); + CCEC_LOG( LOG_DEBUG, "AIDL txAsync completed, status: %d\r\n", static_cast(sendStatus)); return 0; } diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp index 623461ce..94aa0589 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -33,7 +33,6 @@ * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::open(int *handle) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::open\r\n"); int ret = ::HdmiCecOpen(handle); CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::open ret=%d handle=%d\r\n", ret, (handle ? *handle : -1)); return ret; @@ -45,9 +44,8 @@ int HDMICecRdkVHAL::open(int *handle) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::close(int handle) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::close handle=%d\r\n", handle); int ret = ::HdmiCecClose(handle); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::close ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::close handle=%d ret=%d\r\n", handle, ret); return ret; } @@ -57,9 +55,8 @@ int HDMICecRdkVHAL::close(int handle) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::setRxCallback handle=%d\r\n", handle); int ret = ::HdmiCecSetRxCallback(handle, cbfunc, data); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setRxCallback ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setRxCallback handle=%d ret=%d\r\n", handle, ret); return ret; } @@ -69,9 +66,8 @@ int HDMICecRdkVHAL::setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void * * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::setTxCallback handle=%d\r\n", handle); int ret = ::HdmiCecSetTxCallback(handle, cbfunc, data); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setTxCallback ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::setTxCallback handle=%d ret=%d\r\n", handle, ret); return ret; } @@ -81,9 +77,8 @@ int HDMICecRdkVHAL::setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void * * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::tx(int handle, const unsigned char *buf, int len, int *result) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::tx handle=%d len=%d\r\n", handle, len); int ret = ::HdmiCecTx(handle, buf, len, result); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::tx ret=%d sendResult=%d\r\n", ret, (result ? *result : -1)); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::tx handle=%d ret=%d sendResult=%d\r\n", handle, ret, (result ? *result : -1)); return ret; } @@ -93,9 +88,8 @@ int HDMICecRdkVHAL::tx(int handle, const unsigned char *buf, int len, int *resul * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::txAsync(int handle, const unsigned char *buf, int len) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::txAsync handle=%d len=%d\r\n", handle, len); int ret = ::HdmiCecTxAsync(handle, buf, len); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::txAsync ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::txAsync handle=%d ret=%d\r\n", handle, ret); return ret; } @@ -105,9 +99,8 @@ int HDMICecRdkVHAL::txAsync(int handle, const unsigned char *buf, int len) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::addLogicalAddress(int handle, int logicalAddress) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::addLogicalAddress handle=%d addr=%d\r\n", handle, logicalAddress); int ret = ::HdmiCecAddLogicalAddress(handle, logicalAddress); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::addLogicalAddress ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::addLogicalAddress handle=%d addr=%d ret=%d\r\n", handle, logicalAddress, ret); return ret; } @@ -118,9 +111,8 @@ int HDMICecRdkVHAL::addLogicalAddress(int handle, int logicalAddress) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::removeLogicalAddress(int handle, int logicalAddress) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::removeLogicalAddress handle=%d addr=%d\r\n", handle, logicalAddress); int ret = ::HdmiCecRemoveLogicalAddress(handle, logicalAddress); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::removeLogicalAddress ret=%d\r\n", ret); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::removeLogicalAddress handle=%d addr=%d ret=%d\r\n", handle, logicalAddress, ret); return ret; } @@ -130,10 +122,9 @@ int HDMICecRdkVHAL::removeLogicalAddress(int handle, int logicalAddress) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::getLogicalAddress(int handle, int *logicalAddress) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::getLogicalAddress handle=%d\r\n", handle); int ret = ::HdmiCecGetLogicalAddress(handle, logicalAddress); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getLogicalAddress ret=%d addr=%d\r\n", - ret, (logicalAddress ? *logicalAddress : -1)); + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getLogicalAddress handle=%d ret=%d addr=%d\r\n", + handle, ret, (logicalAddress ? *logicalAddress : -1)); return ret; } @@ -143,9 +134,8 @@ int HDMICecRdkVHAL::getLogicalAddress(int handle, int *logicalAddress) * -------------------------------------------------------------------- */ int HDMICecRdkVHAL::getPhysicalAddress(int handle, unsigned int *physicalAddress) { - CCEC_LOG(LOG_INFO, "HDMICecRdkVHAL::getPhysicalAddress handle=%d\r\n", handle); int ret = ::HdmiCecGetPhysicalAddress(handle, physicalAddress); - CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getPhysicalAddress ret=%d addr=0x%x\r\n", + CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getPhysicalAddress handle=%d ret=%d addr=0x%x\r\n", ret, (physicalAddress ? *physicalAddress : 0)); return ret; } From 1e173706051f7dc62dd731a1f98385157189ee08 Mon Sep 17 00:00:00 2001 From: kdarma930_comcast Date: Mon, 22 Jun 2026 06:57:06 +0000 Subject: [PATCH 04/10] Pass devType through HAL getLogicalAddress for AIDL fallback --- ccec/src/DriverImpl.cpp | 2 +- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 11 ++++++----- ccec/src/factoryImpl/HDMICecAidlHAL.h | 2 +- ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 3 ++- ccec/src/factoryImpl/HDMICecRdkVHAL.h | 4 ++-- ccec/src/factoryImpl/IHDMICecHal.h | 6 ++++-- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ccec/src/DriverImpl.cpp b/ccec/src/DriverImpl.cpp index 371df710..4f5f6a03 100644 --- a/ccec/src/DriverImpl.cpp +++ b/ccec/src/DriverImpl.cpp @@ -297,7 +297,7 @@ int DriverImpl::getLogicalAddress(int devType) int logicalAddress = 0; CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress called for devType : %d \r\n", devType); - mHal->getLogicalAddress(nativeHandle, &logicalAddress); + mHal->getLogicalAddress(nativeHandle, devType, &logicalAddress); CCEC_LOG( LOG_DEBUG, "DriverImpl::getLogicalAddress got logical Address : %d \r\n", logicalAddress); return logicalAddress; diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index a1792dc8..3ad0e2b5 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -241,7 +241,7 @@ int HDMICecAidlHAL::removeLogicalAddress(int handle, int logicalAddresses) return 0; } -int HDMICecAidlHAL::getLogicalAddress(int handle, int *logicalAddress) +int HDMICecAidlHAL::getLogicalAddress(int handle, int devType, int *logicalAddress) { (void)handle; if (logicalAddress == nullptr) { @@ -264,18 +264,19 @@ int HDMICecAidlHAL::getLogicalAddress(int handle, int *logicalAddress) *logicalAddress = addresses[0]; }else { CCEC_LOG(LOG_WARN, - "DriverImpl::getLogicalAddress no allocated LA from AIDL (statusOk=%d, count=%zu). Trying fallback allocation.\r\n", + "HDMICecAidlHAL::getLogicalAddress no allocated LA from AIDL (statusOk=%d, count=%zu devType=%d). Trying fallback allocation.\r\n", status.isOk() ? 1 : 0, - addresses.size()); + addresses.size(), + devType); if (mAidlController != nullptr) { - const std::vector preferred = preferredLogicalAddressesForDeviceType(*logicalAddress); + const std::vector preferred = preferredLogicalAddressesForDeviceType(devType); for (std::vector::const_iterator it = preferred.begin(); it != preferred.end(); ++it) { std::vector candidate; candidate.push_back(*it); bool addResult = false; android::binder::Status addStatus = mAidlController->addLogicalAddresses(candidate, &addResult); CCEC_LOG(LOG_DEBUG, - "DriverImpl::getLogicalAddress fallback addLogicalAddresses candidate=%d addOk=%d addResult=%d\r\n", + "HDMICecAidlHAL::getLogicalAddress fallback addLogicalAddresses candidate=%d addOk=%d addResult=%d\r\n", candidate[0], addStatus.isOk() ? 1 : 0, addResult ? 1 : 0); diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.h b/ccec/src/factoryImpl/HDMICecAidlHAL.h index 15aeb689..84dce4b1 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.h +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.h @@ -50,7 +50,7 @@ class HDMICecAidlHAL : public IHDMICecHal { int close(int handle) override; int addLogicalAddress(int handle, int logicalAddresses) override; int removeLogicalAddress(int handle, int logicalAddresses) override; - int getLogicalAddress(int handle, int *logicalAddress) override; + int getLogicalAddress(int handle, int devType, int *logicalAddress) override; int getPhysicalAddress(int handle, unsigned int *physicalAddress) override; int setRxCallback(int handle, HdmiCecRxCallback_t cbfunc, void *data) override; int setTxCallback(int handle, HdmiCecTxCallback_t cbfunc, void *data) override; diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp index 94aa0589..3dfb9e62 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -120,8 +120,9 @@ int HDMICecRdkVHAL::removeLogicalAddress(int handle, int logicalAddress) * getLogicalAddress * Calls HdmiCecGetLogicalAddress() to retrieve the current logical address. * -------------------------------------------------------------------- */ -int HDMICecRdkVHAL::getLogicalAddress(int handle, int *logicalAddress) +int HDMICecRdkVHAL::getLogicalAddress(int handle, int devType, int *logicalAddress) { + (void)devType; int ret = ::HdmiCecGetLogicalAddress(handle, logicalAddress); CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getLogicalAddress handle=%d ret=%d addr=%d\r\n", handle, ret, (logicalAddress ? *logicalAddress : -1)); diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.h b/ccec/src/factoryImpl/HDMICecRdkVHAL.h index 944cff22..293d1ab3 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.h +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.h @@ -80,9 +80,9 @@ class HDMICecRdkVHAL : public IHDMICecHal { /** * @brief Get the device logical address. - * Calls HdmiCecGetLogicalAddress(). + * Calls HdmiCecGetLogicalAddress(). devType is unused on legacy backend. */ - int getLogicalAddress(int handle, int *logicalAddress) override; + int getLogicalAddress(int handle, int devType, int *logicalAddress) override; /** * @brief Get the device physical address. diff --git a/ccec/src/factoryImpl/IHDMICecHal.h b/ccec/src/factoryImpl/IHDMICecHal.h index 4c2b22b7..016bb5d3 100644 --- a/ccec/src/factoryImpl/IHDMICecHal.h +++ b/ccec/src/factoryImpl/IHDMICecHal.h @@ -141,13 +141,15 @@ class IHDMICecHal { * @brief Get the logical address of the device. * * Legacy: calls HdmiCecGetLogicalAddress(). - * AIDL: queries the logical address via binder. + * AIDL: queries the logical address via binder, and may use devType + * as a fallback hint when no logical address is currently allocated. * * @param[in] handle The driver handle. + * @param[in] devType Device type hint (TV/Recorder/Tuner/Playback/AudioSystem). * @param[out] logicalAddress Pointer to store the logical address. * @return HDMI_CEC_IO_SUCCESS on success, or an error code. */ - virtual int getLogicalAddress(int handle, int *logicalAddress) = 0; + virtual int getLogicalAddress(int handle, int devType, int *logicalAddress) = 0; /** * @brief Get the physical address of the device. From 0ef127c58167acc2cb621d745332aeb4d588a2a6 Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Tue, 23 Jun 2026 11:11:28 +0530 Subject: [PATCH 05/10] Changed year to 2026 --- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 2 +- ccec/src/factoryImpl/HDMICecAidlHAL.h | 2 +- ccec/src/factoryImpl/HDMICecHalFactory.cpp | 2 +- ccec/src/factoryImpl/HDMICecHalFactory.h | 2 +- ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 2 +- ccec/src/factoryImpl/HDMICecRdkVHAL.h | 2 +- ccec/src/factoryImpl/IHDMICecHal.h | 2 +- ccec/src/factoryImpl/ServiceManagerCheck.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index 3ad0e2b5..116e3e5f 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.h b/ccec/src/factoryImpl/HDMICecAidlHAL.h index 84dce4b1..2d0ea3bc 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.h +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.cpp b/ccec/src/factoryImpl/HDMICecHalFactory.cpp index 15f078f7..03ce25cd 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.cpp +++ b/ccec/src/factoryImpl/HDMICecHalFactory.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.h b/ccec/src/factoryImpl/HDMICecHalFactory.h index ee8a6602..787a07f3 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.h +++ b/ccec/src/factoryImpl/HDMICecHalFactory.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp index 3dfb9e62..99d50b72 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.h b/ccec/src/factoryImpl/HDMICecRdkVHAL.h index 293d1ab3..74c77753 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.h +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/IHDMICecHal.h b/ccec/src/factoryImpl/IHDMICecHal.h index 016bb5d3..fe3476eb 100644 --- a/ccec/src/factoryImpl/IHDMICecHal.h +++ b/ccec/src/factoryImpl/IHDMICecHal.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/ccec/src/factoryImpl/ServiceManagerCheck.h b/ccec/src/factoryImpl/ServiceManagerCheck.h index 2c5ae890..235ac22f 100644 --- a/ccec/src/factoryImpl/ServiceManagerCheck.h +++ b/ccec/src/factoryImpl/ServiceManagerCheck.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2016 RDK Management + * Copyright 2026 RDK Management * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From fe8d48b3953a2e1561cddf529ede378c932c0670 Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Tue, 23 Jun 2026 11:44:31 +0530 Subject: [PATCH 06/10] Refactored the method isAidlServiceAvailable. --- ccec/src/factoryImpl/HDMICecHalFactory.cpp | 170 +++++++++++---------- ccec/src/factoryImpl/HDMICecHalFactory.h | 10 -- 2 files changed, 91 insertions(+), 89 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.cpp b/ccec/src/factoryImpl/HDMICecHalFactory.cpp index 03ce25cd..cdaca11c 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.cpp +++ b/ccec/src/factoryImpl/HDMICecHalFactory.cpp @@ -41,93 +41,105 @@ using namespace com::rdk::hal::hdmicec; static const android::String16 mServiceManagerName("manager"); -HDMICecHalFactory::BackendType HDMICecHalFactory::mBackendType = HDMICecHalFactory::BackendType::UNKNOWN; -bool HDMICecHalFactory::isAidlServiceAvailable() -{ - CCEC_LOG(LOG_INFO, "HDMICecHalFactory::isAidlServiceAvailable invoked\r\n"); - - if (mBackendType == HDMICecHalFactory::BackendType::AIDL) { - return true; - } else if (mBackendType == HDMICecHalFactory::BackendType::LEGACY) { - return false; - } - - if (!isServiceManagerAvailable()) { - CCEC_LOG(LOG_INFO, "Binder driver not available; assuming legacy HDMI CEC HAL\r\n"); - mBackendType = HDMICecHalFactory::BackendType::LEGACY; - return false; - } - - android::sp serviceManager = android::defaultServiceManager(); - if (serviceManager == nullptr) { - CCEC_LOG(LOG_ERROR, "HDMICecHalFactory::isAidlServiceAvailable failed: IServiceManager unavailable\r\n"); - mBackendType = HDMICecHalFactory::BackendType::LEGACY; - return false; - } - - CCEC_LOG(LOG_INFO, "Successfully obtained IServiceManager\r\n"); - - const android::String16 expectedServiceName(IHdmiCec::serviceName().c_str()); - android::Vector services = serviceManager->listServices(); - size_t discoveredServiceCount = 0; - bool matched = false; - - for (size_t index = 0; index < services.size(); ++index) { - if (services[index] != mServiceManagerName) { - ++discoveredServiceCount; +namespace { + class HalFactoryUtility { + enum class BackendType { + UNKNOWN, + LEGACY, + AIDL + }; + + static BackendType mBackendType; + + bool isAidlServiceAvailable(const android::String16 &expectedServiceName) + { + CCEC_LOG(LOG_INFO, "isAidlServiceAvailable invoked\r\n"); + + if (mBackendType == BackendType::AIDL) { + return true; + } else if (mBackendType == BackendType::LEGACY) { + return false; + } + + if (!isServiceManagerAvailable()) { + CCEC_LOG(LOG_INFO, "Binder driver not available; falling back to legacy HAL\r\n"); + mBackendType = BackendType::LEGACY; + return false; + } + + android::sp serviceManager = android::defaultServiceManager(); + if (serviceManager == nullptr) { + CCEC_LOG(LOG_ERROR, "isAidlServiceAvailable failed: IServiceManager unavailable\r\n"); + mBackendType = BackendType::LEGACY; + return false; + } + + CCEC_LOG(LOG_INFO, "Successfully obtained IServiceManager\r\n"); + + android::Vector services = serviceManager->listServices(); + size_t discoveredServiceCount = 0; + bool matched = false; + + for (size_t index = 0; index < services.size(); ++index) { + if (services[index] != mServiceManagerName) { + ++discoveredServiceCount; + } + } + + CCEC_LOG(LOG_INFO, "isAidlServiceAvailable discovered %zu binder services\r\n", discoveredServiceCount); + if (discoveredServiceCount == 0) { + CCEC_LOG(LOG_INFO, + "isAidlServiceAvailable found no binder services beyond the ServiceManager entry while searching for '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = BackendType::LEGACY; + return false; + } + + CCEC_LOG(LOG_INFO, + "isAidlServiceAvailable inspecting %zu registered binder services for '%s'\r\n", + discoveredServiceCount, android::String8(expectedServiceName).string()); + + for (size_t index = 0; index < services.size(); ++index) { + if (services[index] == mServiceManagerName) { + continue; + } + + const android::String8 discoveredServiceName(services[index]); + if (services[index] == expectedServiceName) { + matched = true; + } + + CCEC_LOG(LOG_INFO, + "isAidlServiceAvailable discovered binder service[%zu]='%s'\r\n", + index, + discoveredServiceName.string()); + } + + if (matched) { + CCEC_LOG(LOG_INFO, + "isAidlServiceAvailable found AIDL service '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = BackendType::AIDL; + return true; + } + + CCEC_LOG(LOG_INFO, + "isAidlServiceAvailable did not find AIDL service '%s'\r\n", + android::String8(expectedServiceName).string()); + mBackendType = BackendType::LEGACY; + return false; } - } - - CCEC_LOG(LOG_INFO, "HDMICecHalFactory::isAidlServiceAvailable discovered %zu binder services\r\n", discoveredServiceCount); - if (discoveredServiceCount == 0) { - CCEC_LOG(LOG_INFO, - "HDMICecHalFactory::isAidlServiceAvailable found no binder services beyond the ServiceManager entry while searching for '%s'\r\n", - android::String8(expectedServiceName).string()); - mBackendType = HDMICecHalFactory::BackendType::LEGACY; - return false; - } - - CCEC_LOG(LOG_INFO, - "HDMICecHalFactory::isAidlServiceAvailable inspecting %zu registered binder services for '%s'\r\n", - discoveredServiceCount, android::String8(expectedServiceName).string()); - - for (size_t index = 0; index < services.size(); ++index) { - if (services[index] == mServiceManagerName) { - continue; - } - - const android::String8 discoveredServiceName(services[index]); - if (services[index] == expectedServiceName) { - matched = true; - } - - CCEC_LOG(LOG_INFO, - "HDMICecHalFactory::isAidlServiceAvailable discovered binder service[%zu]='%s'\r\n", - index, - discoveredServiceName.string()); - } - - if (matched) { - CCEC_LOG(LOG_INFO, - "HDMICecHalFactory::isAidlServiceAvailable found HDMI CEC AIDL service '%s'\r\n", - android::String8(expectedServiceName).string()); - mBackendType = HDMICecHalFactory::BackendType::AIDL; - return true; - } - - CCEC_LOG(LOG_INFO, - "HDMICecHalFactory::isAidlServiceAvailable did not find HDMI CEC AIDL service '%s'\r\n", - android::String8(expectedServiceName).string()); - mBackendType = HDMICecHalFactory::BackendType::LEGACY; - return false; + }; + HalFactoryUtility::BackendType HalFactoryUtility::mBackendType + = HalFactoryUtility::BackendType::UNKNOWN; } std::unique_ptr HDMICecHalFactory::Create() { CCEC_LOG(LOG_INFO, "HDMICecHalFactory::Create invoked\r\n"); - if (isAidlServiceAvailable()) { + if (HalFactoryUtility::isAidlServiceAvailable(IHdmiCec::serviceName().c_str())) { CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is available — using HDMICecAidlHAL\r\n"); return std::make_unique(); } diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.h b/ccec/src/factoryImpl/HDMICecHalFactory.h index 787a07f3..7e2d0479 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.h +++ b/ccec/src/factoryImpl/HDMICecHalFactory.h @@ -26,16 +26,6 @@ class HDMICecHalFactory { public: static std::unique_ptr Create(); - -private: - enum class BackendType { - UNKNOWN, - LEGACY, - AIDL - }; - - static BackendType mBackendType; - static bool isAidlServiceAvailable(); }; #endif // HDMI_CEC_HAL_FACTORY_H From 2cebd5da32d5d1fd3cdfd198e8b84c0d578fc2b4 Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Tue, 23 Jun 2026 13:49:13 +0530 Subject: [PATCH 07/10] Fixed review comments. --- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index 116e3e5f..b5e9921a 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -27,6 +27,7 @@ #include "ccec/Util.hpp" #include "ccec/Exception.hpp" +#include "ccec/drivers/hdmi_cec_driver.h" using CCEC_OSAL::AutoLock; using android::sp; @@ -60,8 +61,12 @@ class HDMICecAidlHALEventListener : public BnHdmiCecEventListener { android::binder::Status onMessageSent(const std::vector& message, SendMessageStatus status) override { if (mAidlHal) { - int result = (status == SendMessageStatus::ACK_STATE_0) ? 1 : - (status == SendMessageStatus::ACK_STATE_1) ? 2 : 3; + int result = HDMI_CEC_IO_SENT_FAILED; + if (status == SendMessageStatus::ACK_STATE_0) { + result = HDMI_CEC_IO_SENT_AND_ACKD; + } else if (status == SendMessageStatus::ACK_STATE_1) { + result = HDMI_CEC_IO_SENT_BUT_NOT_ACKD; + } mAidlHal->dispatchTx(result); } return android::binder::Status::ok(); @@ -375,7 +380,7 @@ int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *resul } if(emulateAckForPollFrames(buf, len)) { - *result = 0; // HDMI_CEC_IO_SUCCESS + *result = HDMI_CEC_IO_SUCCESS; return 0; } @@ -388,13 +393,13 @@ int HDMICecAidlHAL::tx(int handle, const unsigned char *buf, int len, int *resul } // Map AIDL SendMessageStatus to HAL error codes - *result = 0; // HDMI_CEC_IO_SUCCESS + *result = HDMI_CEC_IO_SUCCESS; if (sendStatus == SendMessageStatus::ACK_STATE_0) { - *result = 1; // HDMI_CEC_IO_SENT_AND_ACKD + *result = HDMI_CEC_IO_SENT_AND_ACKD; } else if (sendStatus == SendMessageStatus::ACK_STATE_1) { - *result = 2; // HDMI_CEC_IO_SENT_BUT_NOT_ACKD + *result = HDMI_CEC_IO_SENT_BUT_NOT_ACKD; } else if (sendStatus == SendMessageStatus::BUSY){ - *result = 3; // HDMI_CEC_IO_SENT_FAILED + *result = HDMI_CEC_IO_SENT_FAILED; throw IOException(); } From 8f01cb6e318c8c7f686839305d18e7b28c8bbe9b Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Tue, 23 Jun 2026 15:11:39 +0530 Subject: [PATCH 08/10] Added exception handling around AIDL HAL creation. --- ccec/src/factoryImpl/HDMICecAidlHAL.cpp | 1 + ccec/src/factoryImpl/HDMICecHalFactory.cpp | 13 +++++++++---- ccec/src/factoryImpl/HDMICecRdkVHAL.cpp | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp index b5e9921a..ab5b0b94 100644 --- a/ccec/src/factoryImpl/HDMICecAidlHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecAidlHAL.cpp @@ -324,6 +324,7 @@ void HDMICecAidlHAL::dispatchRx(unsigned char *buf, int len) if (buf != nullptr && len >= 1) { const uint8_t srcLA = static_cast((buf[0] >> 4) & 0x0F); if (srcLA <= 0x0E) { + AutoLock lock_(mAidlMutex); mSeenLogicalAddresses.insert(srcLA); } } diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.cpp b/ccec/src/factoryImpl/HDMICecHalFactory.cpp index cdaca11c..b733634c 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.cpp +++ b/ccec/src/factoryImpl/HDMICecHalFactory.cpp @@ -44,6 +44,7 @@ static const android::String16 mServiceManagerName("manager"); namespace { class HalFactoryUtility { + public: enum class BackendType { UNKNOWN, LEGACY, @@ -52,7 +53,7 @@ namespace { static BackendType mBackendType; - bool isAidlServiceAvailable(const android::String16 &expectedServiceName) + bool isAidlServiceAvailable(const android::String16 expectedServiceName) { CCEC_LOG(LOG_INFO, "isAidlServiceAvailable invoked\r\n"); @@ -139,9 +140,13 @@ std::unique_ptr HDMICecHalFactory::Create() { CCEC_LOG(LOG_INFO, "HDMICecHalFactory::Create invoked\r\n"); - if (HalFactoryUtility::isAidlServiceAvailable(IHdmiCec::serviceName().c_str())) { - CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is available — using HDMICecAidlHAL\r\n"); - return std::make_unique(); + try { + if (HalFactoryUtility::isAidlServiceAvailable(IHdmiCec::serviceName().c_str())) { + CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is available — using HDMICecAidlHAL\r\n"); + return std::make_unique(); + } + } catch (...) { + CCEC_LOG(LOG_ERROR, "HDMICecHalFactory: Exception thrown while creating AIDL HAL,\r\n"); } CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is not available — using legacy HDMICecRdkVHAL\r\n"); diff --git a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp index 99d50b72..b7633391 100644 --- a/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp +++ b/ccec/src/factoryImpl/HDMICecRdkVHAL.cpp @@ -137,7 +137,7 @@ int HDMICecRdkVHAL::getPhysicalAddress(int handle, unsigned int *physicalAddress { int ret = ::HdmiCecGetPhysicalAddress(handle, physicalAddress); CCEC_LOG(LOG_DEBUG, "HDMICecRdkVHAL::getPhysicalAddress handle=%d ret=%d addr=0x%x\r\n", - ret, (physicalAddress ? *physicalAddress : 0)); + handle, ret, (physicalAddress ? *physicalAddress : 0)); return ret; } From e36b4909b25dda88eef12091c03d8c54b5b5fd8b Mon Sep 17 00:00:00 2001 From: Vinod Damodaran Date: Tue, 23 Jun 2026 17:00:22 +0530 Subject: [PATCH 09/10] Fixed build issue --- ccec/src/factoryImpl/HDMICecHalFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ccec/src/factoryImpl/HDMICecHalFactory.cpp b/ccec/src/factoryImpl/HDMICecHalFactory.cpp index b733634c..6b7e62d9 100644 --- a/ccec/src/factoryImpl/HDMICecHalFactory.cpp +++ b/ccec/src/factoryImpl/HDMICecHalFactory.cpp @@ -53,7 +53,7 @@ namespace { static BackendType mBackendType; - bool isAidlServiceAvailable(const android::String16 expectedServiceName) + static bool isAidlServiceAvailable(const android::String16 &expectedServiceName) { CCEC_LOG(LOG_INFO, "isAidlServiceAvailable invoked\r\n"); @@ -141,7 +141,7 @@ std::unique_ptr HDMICecHalFactory::Create() CCEC_LOG(LOG_INFO, "HDMICecHalFactory::Create invoked\r\n"); try { - if (HalFactoryUtility::isAidlServiceAvailable(IHdmiCec::serviceName().c_str())) { + if (HalFactoryUtility::isAidlServiceAvailable(android::String16(IHdmiCec::serviceName().c_str()))) { CCEC_LOG(LOG_INFO, "HDMICecHalFactory: Aidl Service is available — using HDMICecAidlHAL\r\n"); return std::make_unique(); } From 3097ab2a7c7bdff33c657540bb1618a7da497ced Mon Sep 17 00:00:00 2001 From: IshvarKR <130352532+IshvarKR@users.noreply.github.com> Date: Mon, 29 Jun 2026 15:02:12 +0530 Subject: [PATCH 10/10] Update for L1-tests.yml --- .github/workflows/L1-tests.yml | 384 +----------------- stubs/binder/IServiceManager.h | 76 ++++ stubs/binder/ProcessState.h | 16 + .../rdk/hal/hdmicec/BnHdmiCecEventListener.h | 10 + stubs/com/rdk/hal/hdmicec/IHdmiCec.h | 41 ++ .../com/rdk/hal/hdmicec/IHdmiCecController.h | 38 ++ .../rdk/hal/hdmicec/IHdmiCecEventListener.h | 20 + stubs/com/rdk/hal/hdmicec/SendMessageStatus.h | 12 + stubs/com/rdk/hal/hdmicec/State.h | 12 + stubs/linux/android/binder.h | 53 +++ stubs/utils/String16.h | 23 ++ stubs/utils/String8.h | 23 ++ stubs/utils/Vector.h | 11 + 13 files changed, 351 insertions(+), 368 deletions(-) create mode 100644 stubs/binder/IServiceManager.h create mode 100644 stubs/binder/ProcessState.h create mode 100644 stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h create mode 100644 stubs/com/rdk/hal/hdmicec/IHdmiCec.h create mode 100644 stubs/com/rdk/hal/hdmicec/IHdmiCecController.h create mode 100644 stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h create mode 100644 stubs/com/rdk/hal/hdmicec/SendMessageStatus.h create mode 100644 stubs/com/rdk/hal/hdmicec/State.h create mode 100644 stubs/linux/android/binder.h create mode 100644 stubs/utils/String16.h create mode 100644 stubs/utils/String8.h create mode 100644 stubs/utils/Vector.h diff --git a/.github/workflows/L1-tests.yml b/.github/workflows/L1-tests.yml index 25963c45..64fd73c4 100644 --- a/.github/workflows/L1-tests.yml +++ b/.github/workflows/L1-tests.yml @@ -74,375 +74,23 @@ jobs: cmake --install build/googletest - name: Generate stub headers - run: | - set -e + # Empty headers to mute errors + run: > cd "$GITHUB_WORKSPACE/hdmicec" - mkdir -p \ - stubs/rdk/iarmbus \ - stubs/ccec/drivers/iarmbus \ - stubs/binder \ - stubs/utils \ - stubs/linux/android \ - stubs/com/rdk/hal/hdmicec - - touch \ - stubs/rdk/iarmbus/libIARM.h \ - stubs/rdk/iarmbus/libIBus.h \ - stubs/rdk/iarmbus/libIBusDaemon.h \ - stubs/ccec/drivers/iarmbus/CecIARMBusMgr.h - - ln -sf ../../../mocks/hdmicec/hdmi_cec_driver.h stubs/ccec/drivers/hdmi_cec_driver.h - - cat <<'EOF' > stubs/utils/String16.h - #ifndef STUB_UTILS_STRING16_H - #define STUB_UTILS_STRING16_H - - #include - - namespace android { - class String16 { - public: - String16() = default; - explicit String16(const char* value) : mValue(value ? value : "") {} - explicit String16(const std::string& value) : mValue(value) {} - - const std::string& str() const { return mValue; } - - friend bool operator==(const String16& lhs, const String16& rhs) { return lhs.mValue == rhs.mValue; } - friend bool operator!=(const String16& lhs, const String16& rhs) { return !(lhs == rhs); } - - private: - std::string mValue; - }; - } - - #endif - EOF - - cat <<'EOF' > stubs/utils/String8.h - #ifndef STUB_UTILS_STRING8_H - #define STUB_UTILS_STRING8_H - - #include - #include "String16.h" - - namespace android { - class String8 { - public: - String8() = default; - explicit String8(const char* value) : mValue(value ? value : "") {} - explicit String8(const String16& value) : mValue(value.str()) {} - - const char* c_str() const { return mValue.c_str(); } - const char* string() const { return mValue.c_str(); } - - private: - std::string mValue; - }; - } - - #endif - EOF - - cat <<'EOF' > stubs/utils/Vector.h - #ifndef STUB_UTILS_VECTOR_H - #define STUB_UTILS_VECTOR_H - - #include - - namespace android { - template - using Vector = std::vector; - } - - #endif - EOF - - cat <<'EOF' > stubs/binder/IServiceManager.h - #ifndef STUB_BINDER_ISERVICE_MANAGER_H - #define STUB_BINDER_ISERVICE_MANAGER_H - - #include - #include - #include - #include "utils/String16.h" - #include "utils/String8.h" - #include "utils/Vector.h" - - namespace android { - template - class sp { - public: - sp() = default; - sp(std::nullptr_t) : mPtr(nullptr) {} - sp(T* ptr) : mPtr(ptr) {} - sp(const std::shared_ptr& ptr) : mPtr(ptr) {} - - T* get() const { return mPtr.get(); } - T* operator->() const { return mPtr.get(); } - operator bool() const { return static_cast(mPtr); } - bool operator==(std::nullptr_t) const { return mPtr == nullptr; } - bool operator!=(std::nullptr_t) const { return mPtr != nullptr; } - sp& operator=(T* ptr) { mPtr.reset(ptr); return *this; } - - private: - std::shared_ptr mPtr; - }; - - class IBinder { - public: - virtual ~IBinder() = default; - }; - - namespace binder { - class Status { - public: - Status() : mOk(true), mMessage("OK") {} - explicit Status(bool ok, std::string message = "OK") : mOk(ok), mMessage(std::move(message)) {} - - static Status ok() { return Status(true, "OK"); } - bool isOk() const { return mOk; } - String8 toString8() const { return String8(mMessage.c_str()); } - - private: - bool mOk; - std::string mMessage; - }; - } - - class IServiceManager { - public: - virtual ~IServiceManager() = default; - virtual sp getService(const String16&) { return sp(nullptr); } - virtual Vector listServices() { return {}; } - }; - - class StubServiceManager : public IServiceManager {}; - - inline sp defaultServiceManager() { - static sp manager(new StubServiceManager()); - return manager; - } - - template - sp interface_cast(const sp&) { - return sp(new T()); - } - } - - #endif - EOF - - cat <<'EOF' > stubs/binder/ProcessState.h - #ifndef STUB_BINDER_PROCESS_STATE_H - #define STUB_BINDER_PROCESS_STATE_H - - namespace android { - class ProcessState { - public: - static ProcessState* self() { - static ProcessState instance; - return &instance; - } - - void startThreadPool() {} - }; - } - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/SendMessageStatus.h - #ifndef STUB_HDMICEC_SEND_MESSAGE_STATUS_H - #define STUB_HDMICEC_SEND_MESSAGE_STATUS_H - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - enum class SendMessageStatus { - ACK_STATE_0 = 0, - ACK_STATE_1 = 1, - BUSY = 2 - }; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/State.h - #ifndef STUB_HDMICEC_STATE_H - #define STUB_HDMICEC_STATE_H - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - enum class State { - UNKNOWN = 0, - IDLE = 1, - ACTIVE = 2 - }; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h - #ifndef STUB_HDMICEC_EVENT_LISTENER_H - #define STUB_HDMICEC_EVENT_LISTENER_H - - #include - #include "binder/IServiceManager.h" - #include "com/rdk/hal/hdmicec/SendMessageStatus.h" - #include "com/rdk/hal/hdmicec/State.h" - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - class IHdmiCecEventListener : public android::IBinder { - public: - virtual ~IHdmiCecEventListener() = default; - virtual android::binder::Status onMessageReceived(const std::vector&) { return android::binder::Status::ok(); } - virtual android::binder::Status onStateChanged(State, State) { return android::binder::Status::ok(); } - virtual android::binder::Status onMessageSent(const std::vector&, SendMessageStatus) { return android::binder::Status::ok(); } - }; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h - #ifndef STUB_BN_HDMICEC_EVENT_LISTENER_H - #define STUB_BN_HDMICEC_EVENT_LISTENER_H - - #include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - class BnHdmiCecEventListener : public IHdmiCecEventListener {}; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCecController.h - #ifndef STUB_HDMICEC_CONTROLLER_H - #define STUB_HDMICEC_CONTROLLER_H - - #include - #include - #include "binder/IServiceManager.h" - #include "com/rdk/hal/hdmicec/SendMessageStatus.h" - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - class IHdmiCecController : public android::IBinder { - public: - virtual ~IHdmiCecController() = default; - - virtual android::binder::Status addLogicalAddresses(const std::vector&, bool* result) { - if (result) { *result = true; } - return android::binder::Status::ok(); - } - - virtual android::binder::Status removeLogicalAddresses(const std::vector&, bool* result) { - if (result) { *result = true; } - return android::binder::Status::ok(); - } - - virtual android::binder::Status sendMessage(const std::vector&, SendMessageStatus* status) { - if (status) { *status = SendMessageStatus::ACK_STATE_0; } - return android::binder::Status::ok(); - } - }; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/com/rdk/hal/hdmicec/IHdmiCec.h - #ifndef STUB_HDMICEC_H - #define STUB_HDMICEC_H - - #include - #include - #include "binder/IServiceManager.h" - #include "com/rdk/hal/hdmicec/IHdmiCecController.h" - #include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" - - namespace com { namespace rdk { namespace hal { namespace hdmicec { - class IHdmiCec : public android::IBinder { - public: - virtual ~IHdmiCec() = default; - - static std::string serviceName() { return "com.rdk.hal.hdmicec.IHdmiCec/default"; } - - virtual android::binder::Status open(const android::sp&, android::sp* controller) { - if (controller) { *controller = android::sp(new IHdmiCecController()); } - return android::binder::Status::ok(); - } - - virtual android::binder::Status close(const android::sp&, bool* result) { - if (result) { *result = true; } - return android::binder::Status::ok(); - } - - virtual android::binder::Status getLogicalAddresses(std::vector* addresses) { - if (addresses) { addresses->clear(); } - return android::binder::Status::ok(); - } - }; - }}}} - - #endif - EOF - - cat <<'EOF' > stubs/linux/android/binder.h - #ifndef STUB_LINUX_ANDROID_BINDER_H - #define STUB_LINUX_ANDROID_BINDER_H - - #include - #include - - typedef uintptr_t binder_uintptr_t; - - struct binder_version { - int32_t protocol_version; - }; - - struct binder_write_read { - uint64_t write_size; - uint64_t write_consumed; - binder_uintptr_t write_buffer; - uint64_t read_size; - uint64_t read_consumed; - binder_uintptr_t read_buffer; - }; - - struct binder_transaction_data { - union { - uint32_t handle; - binder_uintptr_t ptr; - } target; - binder_uintptr_t cookie; - uint32_t code; - uint32_t flags; - int32_t sender_pid; - int32_t sender_euid; - uint64_t data_size; - uint64_t offsets_size; - union { - struct { - binder_uintptr_t buffer; - binder_uintptr_t offsets; - } ptr; - uint8_t buf[8]; - } data; - }; - - #define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) - #define BC_TRANSACTION 0x0 - #define TF_ACCEPT_FDS 0x10 - #define BR_REPLY 0x1 - #define BR_DEAD_REPLY 0x2 - #define BR_FAILED_REPLY 0x3 - #define BR_TRANSACTION_COMPLETE 0x4 - #define BR_NOOP 0x5 - #define BR_OK 0x6 - - #endif - EOF + && + mkdir -p + stubs/rdk/iarmbus + stubs/ccec/drivers/iarmbus + && + cd stubs + && + touch + rdk/iarmbus/libIARM.h + rdk/iarmbus/libIBus.h + rdk/iarmbus/libIBusDaemon.h + ccec/drivers/iarmbus/CecIARMBusMgr.h + && + ln -s ../../../mocks/hdmicec/hdmi_cec_driver.h ccec/drivers/hdmi_cec_driver.h - name: Build hdmicec run: > diff --git a/stubs/binder/IServiceManager.h b/stubs/binder/IServiceManager.h new file mode 100644 index 00000000..5b2db973 --- /dev/null +++ b/stubs/binder/IServiceManager.h @@ -0,0 +1,76 @@ +#ifndef STUB_BINDER_ISERVICEMANAGER_H +#define STUB_BINDER_ISERVICEMANAGER_H + +#include +#include +#include + +#include "utils/String16.h" +#include "utils/String8.h" +#include "utils/Vector.h" + +namespace android { +template +class sp { +public: + sp() = default; + sp(std::nullptr_t) : mPtr(nullptr) {} + sp(T* ptr) : mPtr(ptr) {} + sp(const std::shared_ptr& ptr) : mPtr(ptr) {} + + T* get() const { return mPtr.get(); } + T* operator->() const { return mPtr.get(); } + operator bool() const { return static_cast(mPtr); } + bool operator==(std::nullptr_t) const { return mPtr == nullptr; } + bool operator!=(std::nullptr_t) const { return mPtr != nullptr; } + sp& operator=(T* ptr) { + mPtr.reset(ptr); + return *this; + } + +private: + std::shared_ptr mPtr; +}; + +class IBinder { +public: + virtual ~IBinder() = default; +}; + +namespace binder { +class Status { +public: + Status() : mOk(true), mMessage("OK") {} + explicit Status(bool ok, std::string message = "OK") : mOk(ok), mMessage(std::move(message)) {} + + static Status ok() { return Status(true, "OK"); } + bool isOk() const { return mOk; } + String8 toString8() const { return String8(mMessage.c_str()); } + +private: + bool mOk; + std::string mMessage; +}; +} + +class IServiceManager { +public: + virtual ~IServiceManager() = default; + virtual sp getService(const String16&) { return sp(nullptr); } + virtual Vector listServices() { return {}; } +}; + +class StubServiceManager : public IServiceManager {}; + +inline sp defaultServiceManager() { + static sp manager(new StubServiceManager()); + return manager; +} + +template +sp interface_cast(const sp&) { + return sp(new T()); +} +} + +#endif diff --git a/stubs/binder/ProcessState.h b/stubs/binder/ProcessState.h new file mode 100644 index 00000000..816837e0 --- /dev/null +++ b/stubs/binder/ProcessState.h @@ -0,0 +1,16 @@ +#ifndef STUB_BINDER_PROCESSSTATE_H +#define STUB_BINDER_PROCESSSTATE_H + +namespace android { +class ProcessState { +public: + static ProcessState* self() { + static ProcessState instance; + return &instance; + } + + void startThreadPool() {} +}; +} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h b/stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h new file mode 100644 index 00000000..9d3d5268 --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/BnHdmiCecEventListener.h @@ -0,0 +1,10 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_BNHDMICECEVENTLISTENER_H +#define STUB_COM_RDK_HAL_HDMICEC_BNHDMICECEVENTLISTENER_H + +#include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +class BnHdmiCecEventListener : public IHdmiCecEventListener {}; +}}}} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/IHdmiCec.h b/stubs/com/rdk/hal/hdmicec/IHdmiCec.h new file mode 100644 index 00000000..ba8ba811 --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/IHdmiCec.h @@ -0,0 +1,41 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_IHDMICEC_H +#define STUB_COM_RDK_HAL_HDMICEC_IHDMICEC_H + +#include +#include + +#include "binder/IServiceManager.h" +#include "com/rdk/hal/hdmicec/IHdmiCecController.h" +#include "com/rdk/hal/hdmicec/IHdmiCecEventListener.h" + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +class IHdmiCec : public android::IBinder { +public: + virtual ~IHdmiCec() = default; + + static std::string serviceName() { return "com.rdk.hal.hdmicec.IHdmiCec/default"; } + + virtual android::binder::Status open(const android::sp&, android::sp* controller) { + if (controller) { + *controller = android::sp(new IHdmiCecController()); + } + return android::binder::Status::ok(); + } + + virtual android::binder::Status close(const android::sp&, bool* result) { + if (result) { + *result = true; + } + return android::binder::Status::ok(); + } + + virtual android::binder::Status getLogicalAddresses(std::vector* addresses) { + if (addresses) { + addresses->clear(); + } + return android::binder::Status::ok(); + } +}; +}}}} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/IHdmiCecController.h b/stubs/com/rdk/hal/hdmicec/IHdmiCecController.h new file mode 100644 index 00000000..d86e1559 --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/IHdmiCecController.h @@ -0,0 +1,38 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_IHDMICECCONTROLLER_H +#define STUB_COM_RDK_HAL_HDMICEC_IHDMICECCONTROLLER_H + +#include +#include + +#include "binder/IServiceManager.h" +#include "com/rdk/hal/hdmicec/SendMessageStatus.h" + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +class IHdmiCecController : public android::IBinder { +public: + virtual ~IHdmiCecController() = default; + + virtual android::binder::Status addLogicalAddresses(const std::vector&, bool* result) { + if (result) { + *result = true; + } + return android::binder::Status::ok(); + } + + virtual android::binder::Status removeLogicalAddresses(const std::vector&, bool* result) { + if (result) { + *result = true; + } + return android::binder::Status::ok(); + } + + virtual android::binder::Status sendMessage(const std::vector&, SendMessageStatus* status) { + if (status) { + *status = SendMessageStatus::ACK_STATE_0; + } + return android::binder::Status::ok(); + } +}; +}}}} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h b/stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h new file mode 100644 index 00000000..ef19976f --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/IHdmiCecEventListener.h @@ -0,0 +1,20 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_IHDMICECEVENTLISTENER_H +#define STUB_COM_RDK_HAL_HDMICEC_IHDMICECEVENTLISTENER_H + +#include + +#include "binder/IServiceManager.h" +#include "com/rdk/hal/hdmicec/SendMessageStatus.h" +#include "com/rdk/hal/hdmicec/State.h" + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +class IHdmiCecEventListener : public android::IBinder { +public: + virtual ~IHdmiCecEventListener() = default; + virtual android::binder::Status onMessageReceived(const std::vector&) { return android::binder::Status::ok(); } + virtual android::binder::Status onStateChanged(State, State) { return android::binder::Status::ok(); } + virtual android::binder::Status onMessageSent(const std::vector&, SendMessageStatus) { return android::binder::Status::ok(); } +}; +}}}} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/SendMessageStatus.h b/stubs/com/rdk/hal/hdmicec/SendMessageStatus.h new file mode 100644 index 00000000..d440fcb5 --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/SendMessageStatus.h @@ -0,0 +1,12 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_SENDMESSAGESTATUS_H +#define STUB_COM_RDK_HAL_HDMICEC_SENDMESSAGESTATUS_H + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +enum class SendMessageStatus { + ACK_STATE_0 = 0, + ACK_STATE_1 = 1, + BUSY = 2 +}; +}}}} + +#endif diff --git a/stubs/com/rdk/hal/hdmicec/State.h b/stubs/com/rdk/hal/hdmicec/State.h new file mode 100644 index 00000000..6e66a937 --- /dev/null +++ b/stubs/com/rdk/hal/hdmicec/State.h @@ -0,0 +1,12 @@ +#ifndef STUB_COM_RDK_HAL_HDMICEC_STATE_H +#define STUB_COM_RDK_HAL_HDMICEC_STATE_H + +namespace com { namespace rdk { namespace hal { namespace hdmicec { +enum class State { + UNKNOWN = 0, + IDLE = 1, + ACTIVE = 2 +}; +}}}} + +#endif diff --git a/stubs/linux/android/binder.h b/stubs/linux/android/binder.h new file mode 100644 index 00000000..9d72bc55 --- /dev/null +++ b/stubs/linux/android/binder.h @@ -0,0 +1,53 @@ +#ifndef STUB_LINUX_ANDROID_BINDER_H +#define STUB_LINUX_ANDROID_BINDER_H + +#include +#include + +typedef uintptr_t binder_uintptr_t; + +struct binder_version { + int32_t protocol_version; +}; + +struct binder_write_read { + uint64_t write_size; + uint64_t write_consumed; + binder_uintptr_t write_buffer; + uint64_t read_size; + uint64_t read_consumed; + binder_uintptr_t read_buffer; +}; + +struct binder_transaction_data { + union { + uint32_t handle; + binder_uintptr_t ptr; + } target; + binder_uintptr_t cookie; + uint32_t code; + uint32_t flags; + int32_t sender_pid; + int32_t sender_euid; + uint64_t data_size; + uint64_t offsets_size; + union { + struct { + binder_uintptr_t buffer; + binder_uintptr_t offsets; + } ptr; + uint8_t buf[8]; + } data; +}; + +#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) +#define BC_TRANSACTION 0x0 +#define TF_ACCEPT_FDS 0x10 +#define BR_REPLY 0x1 +#define BR_DEAD_REPLY 0x2 +#define BR_FAILED_REPLY 0x3 +#define BR_TRANSACTION_COMPLETE 0x4 +#define BR_NOOP 0x5 +#define BR_OK 0x6 + +#endif diff --git a/stubs/utils/String16.h b/stubs/utils/String16.h new file mode 100644 index 00000000..2118035b --- /dev/null +++ b/stubs/utils/String16.h @@ -0,0 +1,23 @@ +#ifndef STUB_UTILS_STRING16_H +#define STUB_UTILS_STRING16_H + +#include + +namespace android { +class String16 { +public: + String16() = default; + explicit String16(const char* value) : mValue(value ? value : "") {} + explicit String16(const std::string& value) : mValue(value) {} + + const std::string& str() const { return mValue; } + + friend bool operator==(const String16& lhs, const String16& rhs) { return lhs.mValue == rhs.mValue; } + friend bool operator!=(const String16& lhs, const String16& rhs) { return !(lhs == rhs); } + +private: + std::string mValue; +}; +} + +#endif diff --git a/stubs/utils/String8.h b/stubs/utils/String8.h new file mode 100644 index 00000000..f1950e22 --- /dev/null +++ b/stubs/utils/String8.h @@ -0,0 +1,23 @@ +#ifndef STUB_UTILS_STRING8_H +#define STUB_UTILS_STRING8_H + +#include + +#include "String16.h" + +namespace android { +class String8 { +public: + String8() = default; + explicit String8(const char* value) : mValue(value ? value : "") {} + explicit String8(const String16& value) : mValue(value.str()) {} + + const char* c_str() const { return mValue.c_str(); } + const char* string() const { return mValue.c_str(); } + +private: + std::string mValue; +}; +} + +#endif diff --git a/stubs/utils/Vector.h b/stubs/utils/Vector.h new file mode 100644 index 00000000..38f6b639 --- /dev/null +++ b/stubs/utils/Vector.h @@ -0,0 +1,11 @@ +#ifndef STUB_UTILS_VECTOR_H +#define STUB_UTILS_VECTOR_H + +#include + +namespace android { +template +using Vector = std::vector; +} + +#endif