diff options
author | Naseer Ahmed <naseer@codeaurora.org> | 2014-07-23 17:56:26 -0400 |
---|---|---|
committer | Naseer Ahmed <naseer@codeaurora.org> | 2015-03-02 14:54:49 -0500 |
commit | 7a7b66d1f03997b19ddc0b630dc36850c7826d97 (patch) | |
tree | 721f17316cc829a8009368ca5dc465c135a52a3c /libqservice | |
parent | 361b88f0c31d90b1966bc7371c2aee3e089185cb (diff) | |
download | display-7a7b66d1f03997b19ddc0b630dc36850c7826d97.tar.gz |
display: Add HDMI CEC HAL
Implement the spec as per
hardware/libhardware/include/hardware/hdmi_cec.h
Change-Id: I02e1ba9deee1007b7e5922c363b9f5d6c6ad82a9
Diffstat (limited to 'libqservice')
-rw-r--r-- | libqservice/Android.mk | 3 | ||||
-rw-r--r-- | libqservice/IQHDMIClient.cpp | 103 | ||||
-rw-r--r-- | libqservice/IQHDMIClient.h | 57 | ||||
-rw-r--r-- | libqservice/IQService.cpp | 29 | ||||
-rw-r--r-- | libqservice/IQService.h | 11 | ||||
-rw-r--r-- | libqservice/QService.cpp | 26 | ||||
-rw-r--r-- | libqservice/QService.h | 4 |
7 files changed, 225 insertions, 8 deletions
diff --git a/libqservice/Android.mk b/libqservice/Android.mk index 78b1d775..287e6ce8 100644 --- a/libqservice/Android.mk +++ b/libqservice/Android.mk @@ -10,7 +10,8 @@ LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"qdqservice\" LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) LOCAL_SRC_FILES := QService.cpp \ IQService.cpp \ - IQClient.cpp + IQClient.cpp \ + IQHDMIClient.cpp LOCAL_COPY_HEADERS_TO := $(common_header_export_path) LOCAL_COPY_HEADERS := IQService.h \ IQClient.h diff --git a/libqservice/IQHDMIClient.cpp b/libqservice/IQHDMIClient.cpp new file mode 100644 index 00000000..9f5044a5 --- /dev/null +++ b/libqservice/IQHDMIClient.cpp @@ -0,0 +1,103 @@ +/* +* Copyright (c) 2014 The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +#include <utils/Log.h> +#include <binder/Parcel.h> +#include "IQHDMIClient.h" + +using namespace android; +namespace qClient { + +enum { + HDMI_CONNECTED = IBinder::FIRST_CALL_TRANSACTION, + CEC_MESSAGE_RECEIVED +}; + +class BpQHDMIClient : public BpInterface<IQHDMIClient> +{ +public: + BpQHDMIClient(const sp<IBinder>& impl) + :BpInterface<IQHDMIClient>(impl) + { + } + + void onHdmiHotplug(int connected) + { + Parcel data, reply; + data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor()); + data.writeInt32(connected); + remote()->transact(HDMI_CONNECTED, data, &reply, IBinder::FLAG_ONEWAY); + } + + void onCECMessageRecieved(char *msg, ssize_t len) + { + Parcel data, reply; + data.writeInterfaceToken(IQHDMIClient::getInterfaceDescriptor()); + data.writeInt32((int32_t)len); + void *buf = data.writeInplace(len); + if (buf != NULL) + memcpy(buf, msg, len); + remote()->transact(CEC_MESSAGE_RECEIVED, data, &reply, + IBinder::FLAG_ONEWAY); + } +}; + +IMPLEMENT_META_INTERFACE(QHDMIClient, + "android.display.IQHDMIClient"); + +status_t BnQHDMIClient::onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags) +{ + switch(code) { + case HDMI_CONNECTED: { + CHECK_INTERFACE(IQHDMIClient, data, reply); + int connected = data.readInt32(); + onHdmiHotplug(connected); + return NO_ERROR; + } + case CEC_MESSAGE_RECEIVED: { + CHECK_INTERFACE(IQHDMIClient, data, reply); + ssize_t len = data.readInt32(); + const void* msg; + if(len >= 0 && len <= (ssize_t) data.dataAvail()) { + msg = data.readInplace(len); + } else { + msg = NULL; + len = 0; + } + if (msg != NULL) + onCECMessageRecieved((char*) msg, len); + return NO_ERROR; + } + default: { + return BBinder::onTransact(code, data, reply, flags); + } + } +} + +}; //namespace qClient diff --git a/libqservice/IQHDMIClient.h b/libqservice/IQHDMIClient.h new file mode 100644 index 00000000..c3d012a4 --- /dev/null +++ b/libqservice/IQHDMIClient.h @@ -0,0 +1,57 @@ +/* +* Copyright (c) 2014 The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef HDMI_EVENTS_LISTENER_H_ +#define HDMI_EVENTS_LISTENER_H_ + +#include <utils/RefBase.h> +#include <binder/IInterface.h> + +namespace qClient { + +class IQHDMIClient : public android::IInterface +{ +public: + DECLARE_META_INTERFACE(QHDMIClient); + virtual void onHdmiHotplug(int connected) = 0; + virtual void onCECMessageRecieved(char *msg, ssize_t len) = 0; +}; + +class BnQHDMIClient : public android::BnInterface<IQHDMIClient> +{ +public: + virtual android::status_t onTransact( uint32_t code, + const android::Parcel& data, + android::Parcel* reply, uint32_t flags = 0); +}; + +}; //namespace qhdmi + +#endif // HDMI_EVENTS_LISTENER_H_ + diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp index eee22f08..5e67b15c 100644 --- a/libqservice/IQService.cpp +++ b/libqservice/IQService.cpp @@ -45,13 +45,22 @@ public: : BpInterface<IQService>(impl) {} virtual void connect(const sp<IQClient>& client) { - ALOGD_IF(QSERVICE_DEBUG, "%s: connect client", __FUNCTION__); + ALOGD_IF(QSERVICE_DEBUG, "%s: connect HWC client", __FUNCTION__); Parcel data, reply; data.writeInterfaceToken(IQService::getInterfaceDescriptor()); data.writeStrongBinder(client->asBinder()); - remote()->transact(CONNECT, data, &reply); + remote()->transact(CONNECT_HWC_CLIENT, data, &reply); } + virtual void connect(const sp<IQHDMIClient>& client) { + ALOGD_IF(QSERVICE_DEBUG, "%s: connect HDMI client", __FUNCTION__); + Parcel data, reply; + data.writeInterfaceToken(IQService::getInterfaceDescriptor()); + data.writeStrongBinder(client->asBinder()); + remote()->transact(CONNECT_HDMI_CLIENT, data, &reply); + } + + virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel, Parcel* outParcel) { ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel); @@ -90,10 +99,10 @@ status_t BnQService::onTransact( callerUid == AID_ROOT || callerUid == AID_SYSTEM); - if (code == CONNECT) { + if (code == CONNECT_HWC_CLIENT) { CHECK_INTERFACE(IQService, data, reply); if(callerUid != AID_GRAPHICS) { - ALOGE("display.qservice CONNECT access denied: \ + ALOGE("display.qservice CONNECT_HWC_CLIENT access denied: \ pid=%d uid=%d process=%s", callerPid, callerUid, callingProcName); return PERMISSION_DENIED; @@ -102,6 +111,18 @@ status_t BnQService::onTransact( interface_cast<IQClient>(data.readStrongBinder()); connect(client); return NO_ERROR; + } else if(code == CONNECT_HDMI_CLIENT) { + CHECK_INTERFACE(IQService, data, reply); + if(callerUid != AID_SYSTEM && callerUid != AID_ROOT) { + ALOGE("display.qservice CONNECT_HDMI_CLIENT access denied: \ + pid=%d uid=%d process=%s", + callerPid, callerUid, callingProcName); + return PERMISSION_DENIED; + } + sp<IQHDMIClient> client = + interface_cast<IQHDMIClient>(data.readStrongBinder()); + connect(client); + return NO_ERROR; } else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) { if(!permission) { ALOGE("display.qservice access denied: command=%d\ diff --git a/libqservice/IQService.h b/libqservice/IQService.h index 796e506e..78cbd2ae 100644 --- a/libqservice/IQService.h +++ b/libqservice/IQService.h @@ -28,6 +28,7 @@ #include <binder/IInterface.h> #include <binder/IBinder.h> #include <IQClient.h> +#include <IQHDMIClient.h> namespace qService { @@ -41,7 +42,7 @@ public: COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION, SECURING = 2, // Hardware securing start/end notification UNSECURING = 3, // Hardware unsecuring start/end notification - CONNECT = 4, // Connect to qservice + CONNECT_HWC_CLIENT = 4, // Connect to qservice SCREEN_REFRESH = 5, // Refresh screen through SF invalidate EXTERNAL_ORIENTATION = 6,// Set external orientation BUFFER_MIRRORMODE = 7, // Buffer mirrormode @@ -61,6 +62,7 @@ public: TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates SET_FRAME_DUMP_CONFIG = 21, // Provides ability to set the frame dump config SET_S3D_MODE = 22, // Set the 3D mode as specified in msm_hdmi_modes.h + CONNECT_HDMI_CLIENT = 23, // Connect HDMI CEC HAL Client COMMAND_LIST_END = 400, }; @@ -85,8 +87,13 @@ public: DUMP_VIRTUAL_DISPLAY, }; - // Register a client that can be notified + // Register a HWC client that can be notified + // This client is generic and is intended to get + // dispatches of all events calling into QService virtual void connect(const android::sp<qClient::IQClient>& client) = 0; + // Register an HDMI client. This client gets notification of HDMI events + // such as plug/unplug and CEC messages + virtual void connect(const android::sp<qClient::IQHDMIClient>& client) = 0; // Generic function to dispatch binder commands // The type of command decides how the data is parceled virtual android::status_t dispatch(uint32_t command, diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp index 12dd9956..52766953 100644 --- a/libqservice/QService.cpp +++ b/libqservice/QService.cpp @@ -50,10 +50,15 @@ QService::~QService() } void QService::connect(const sp<qClient::IQClient>& client) { - ALOGD_IF(QSERVICE_DEBUG,"client connected"); + ALOGD_IF(QSERVICE_DEBUG,"HWC client connected"); mClient = client; } +void QService::connect(const sp<qClient::IQHDMIClient>& client) { + ALOGD_IF(QSERVICE_DEBUG,"HWC client connected"); + mHDMIClient = client; +} + status_t QService::dispatch(uint32_t command, const Parcel* inParcel, Parcel* outParcel) { status_t err = (status_t) FAILED_TRANSACTION; @@ -68,6 +73,25 @@ status_t QService::dispatch(uint32_t command, const Parcel* inParcel, return err; } +void QService::onHdmiHotplug(int connected) { + if(mHDMIClient.get()) { + ALOGD_IF(QSERVICE_DEBUG, "%s: HDMI hotplug", __FUNCTION__); + mHDMIClient->onHdmiHotplug(connected); + } else { + ALOGE("%s: Failed to get a valid HDMI client", __FUNCTION__); + } +} + +void QService::onCECMessageReceived(char *msg, ssize_t len) { + if(mHDMIClient.get()) { + ALOGD_IF(QSERVICE_DEBUG, "%s: CEC message received", __FUNCTION__); + mHDMIClient->onCECMessageRecieved(msg, len); + } else { + ALOGE("%s: Failed to get a valid HDMI client", __FUNCTION__); + } +} + + void QService::init() { if(!sQService) { diff --git a/libqservice/QService.h b/libqservice/QService.h index a8e4cdba..719c9b7c 100644 --- a/libqservice/QService.h +++ b/libqservice/QService.h @@ -46,13 +46,17 @@ class QService : public BnQService { public: virtual ~QService(); virtual void connect(const android::sp<qClient::IQClient>& client); + virtual void connect(const android::sp<qClient::IQHDMIClient>& client); virtual android::status_t dispatch(uint32_t command, const android::Parcel* data, android::Parcel* reply); + void onHdmiHotplug(int connected); + void onCECMessageReceived(char *msg, ssize_t len); static void init(); private: QService(); android::sp<qClient::IQClient> mClient; + android::sp<qClient::IQHDMIClient> mHDMIClient; static QService *sQService; }; }; // namespace qService |