10792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang/* 20792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Copyright (C) 2014 The Android Open Source Project 30792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 40792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Licensed under the Apache License, Version 2.0 (the "License"); 50792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * you may not use this file except in compliance with the License. 60792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * You may obtain a copy of the License at 70792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 80792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * http://www.apache.org/licenses/LICENSE-2.0 90792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * 100792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * Unless required by applicable law or agreed to in writing, software 110792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * distributed under the License is distributed on an "AS IS" BASIS, 120792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * See the License for the specific language governing permissions and 140792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang * limitations under the License. 150792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang */ 160792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 170792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#define LOG_TAG "HdmiCecControllerJni" 180792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 190792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#define LOG_NDEBUG 1 200792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 218c688ada2dc256a746429b10b2e7a47a52e9b02fJinsuk Kim#include <JNIHelp.h> 228c688ada2dc256a746429b10b2e7a47a52e9b02fJinsuk Kim#include <ScopedPrimitiveArray.h> 23e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 244085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang#include <cstring> 250792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 264085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang#include <android_os_MessageQueue.h> 270792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#include <android_runtime/AndroidRuntime.h> 280792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#include <android_runtime/Log.h> 290792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#include <hardware/hdmi_cec.h> 30e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang#include <sys/param.h> 314085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang#include <utils/Looper.h> 324085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang#include <utils/RefBase.h> 330792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 340792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangnamespace android { 350792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 360792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangstatic struct { 37e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang jmethodID handleIncomingCecCommand; 38e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang jmethodID handleHotplug; 390792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} gHdmiCecControllerClassInfo; 400792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 410792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangclass HdmiCecController { 420792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangpublic: 434085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang HdmiCecController(hdmi_cec_device_t* device, jobject callbacksObj, 444085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang const sp<Looper>& looper); 45e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 46e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang void init(); 47e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 48e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // Send message to other device. Note that it runs in IO thread. 49e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang int sendMessage(const cec_message_t& message); 50a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang // Add a logical address to device. 51a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang int addLogicalAddress(cec_logical_address_t address); 52a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang // Clear all logical address registered to the device. 53a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang void clearLogicaladdress(); 54a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang // Get physical address of device. 55a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang int getPhysicalAddress(); 56a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang // Get CEC version from driver. 57a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang int getVersion(); 58a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang // Get vendor id used for vendor command. 59a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang uint32_t getVendorId(); 600340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // Get Port information on all the HDMI ports. 610340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jobjectArray getPortInfos(); 62092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Set a flag and its value. 63092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang void setOption(int flag, int value); 64092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Set audio return channel status. 651481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim void setAudioReturnChannel(int port, bool flag); 66092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang // Whether to hdmi device is connected to the given port. 67092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang bool isConnected(int port); 680792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 694085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jobject getCallbacksObj() const { 704085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang return mCallbacksObj; 714085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 72e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 734085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangprivate: 74a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim static const int INVALID_PHYSICAL_ADDRESS = 0xFFFF; 750792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang static void onReceived(const hdmi_event_t* event, void* arg); 760792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 77e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang hdmi_cec_device_t* mDevice; 780792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang jobject mCallbacksObj; 794085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang sp<Looper> mLooper; 800792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang}; 810792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 824085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang// RefBase wrapper for hdmi_event_t. As hdmi_event_t coming from HAL 834085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang// may keep its own lifetime, we need to copy it in order to delegate 844085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang// it to service thread. 854085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangclass CecEventWrapper : public LightRefBase<CecEventWrapper> { 864085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangpublic: 874085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang CecEventWrapper(const hdmi_event_t& event) { 884085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // Copy message. 894085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang switch (event.type) { 904085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang case HDMI_EVENT_CEC_MESSAGE: 914085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mEvent.cec.initiator = event.cec.initiator; 924085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mEvent.cec.destination = event.cec.destination; 934085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mEvent.cec.length = event.cec.length; 944085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang std::memcpy(mEvent.cec.body, event.cec.body, event.cec.length); 954085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 964085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang case HDMI_EVENT_HOT_PLUG: 974085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mEvent.hotplug.connected = event.hotplug.connected; 98284c31b92e4e0d0b8095ae50c61db9c83c9d577cJinsuk Kim mEvent.hotplug.port_id = event.hotplug.port_id; 994085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 1004085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang default: 1014085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // TODO: add more type whenever new type is introduced. 1024085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 1034085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1044085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1050792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 1064085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang const cec_message_t& cec() const { 1074085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang return mEvent.cec; 1084085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 109e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 1104085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang const hotplug_event_t& hotplug() const { 1114085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang return mEvent.hotplug; 1124085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 113e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 1144085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang virtual ~CecEventWrapper() {} 115e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 1164085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangprivate: 1174085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang hdmi_event_t mEvent; 1184085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang}; 119e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 1204085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang// Handler class to delegate incoming message to service thread. 1214085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangclass HdmiCecEventHandler : public MessageHandler { 1224085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangpublic: 1234085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang HdmiCecEventHandler(HdmiCecController* controller, const sp<CecEventWrapper>& event) 1244085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang : mController(controller), 1254085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mEventWrapper(event) { 1264085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1274085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1284085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang virtual ~HdmiCecEventHandler() {} 1294085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1304085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang void handleMessage(const Message& message) { 1314085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang switch (message.what) { 1324085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang case HDMI_EVENT_CEC_MESSAGE: 1334085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang propagateCecCommand(mEventWrapper->cec()); 1344085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 1354085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang case HDMI_EVENT_HOT_PLUG: 1364085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang propagateHotplugEvent(mEventWrapper->hotplug()); 1374085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 1384085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang default: 1394085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // TODO: add more type whenever new type is introduced. 1404085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang break; 1414085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1424085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 143e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 1444085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangprivate: 1454085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // Propagate the message up to Java layer. 1464085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang void propagateCecCommand(const cec_message_t& message) { 1474085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jint srcAddr = message.initiator; 1484085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jint dstAddr = message.destination; 1494085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang JNIEnv* env = AndroidRuntime::getJNIEnv(); 1504085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jbyteArray body = env->NewByteArray(message.length); 1514085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang const jbyte* bodyPtr = reinterpret_cast<const jbyte *>(message.body); 1524085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->SetByteArrayRegion(body, 0, message.length, bodyPtr); 1534085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1544085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->CallVoidMethod(mController->getCallbacksObj(), 1554085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang gHdmiCecControllerClassInfo.handleIncomingCecCommand, srcAddr, 1564085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang dstAddr, body); 1574085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->DeleteLocalRef(body); 1584085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1594085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang checkAndClearExceptionFromCallback(env, __FUNCTION__); 1604085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1614085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1624085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang void propagateHotplugEvent(const hotplug_event_t& event) { 1634085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // Note that this method should be called in service thread. 1644085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang JNIEnv* env = AndroidRuntime::getJNIEnv(); 165284c31b92e4e0d0b8095ae50c61db9c83c9d577cJinsuk Kim jint port = event.port_id; 16642230728b8212738c2351939c5577730f05a58deJungshik Jang jboolean connected = (jboolean) event.connected; 1674085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->CallVoidMethod(mController->getCallbacksObj(), 16842230728b8212738c2351939c5577730f05a58deJungshik Jang gHdmiCecControllerClassInfo.handleHotplug, port, connected); 1694085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1704085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang checkAndClearExceptionFromCallback(env, __FUNCTION__); 1714085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1724085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1734085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang // static 1744085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { 1754085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang if (env->ExceptionCheck()) { 1764085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang ALOGE("An exception was thrown by callback '%s'.", methodName); 1774085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang LOGE_EX(env); 1784085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->ExceptionClear(); 1794085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1804085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang } 1814085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1824085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang HdmiCecController* mController; 1834085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang sp<CecEventWrapper> mEventWrapper; 1844085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang}; 1854085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1864085d0ef62554c7e139b82bca0f97161bb159f8cJungshik JangHdmiCecController::HdmiCecController(hdmi_cec_device_t* device, 1874085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jobject callbacksObj, const sp<Looper>& looper) : 1884085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mDevice(device), 1894085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mCallbacksObj(callbacksObj), 1904085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mLooper(looper) { 1914085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang} 1924085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 1934085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangvoid HdmiCecController::init() { 1944085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang mDevice->register_event_callback(mDevice, HdmiCecController::onReceived, this); 195e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang} 196e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 197e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangint HdmiCecController::sendMessage(const cec_message_t& message) { 198e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang // TODO: propagate send_message's return value. 199e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang return mDevice->send_message(mDevice, &message); 200e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang} 201e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 202a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jangint HdmiCecController::addLogicalAddress(cec_logical_address_t address) { 203a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return mDevice->add_logical_address(mDevice, address); 204a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 205a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 206a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jangvoid HdmiCecController::clearLogicaladdress() { 207a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang mDevice->clear_logical_address(mDevice); 208a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 209a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 210a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jangint HdmiCecController::getPhysicalAddress() { 211a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim uint16_t addr; 212a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim if (!mDevice->get_physical_address(mDevice, &addr)) { 213a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return addr; 214a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang } 215a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return INVALID_PHYSICAL_ADDRESS; 216a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 217a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 218a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jangint HdmiCecController::getVersion() { 219a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang int version = 0; 220a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang mDevice->get_version(mDevice, &version); 221a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return version; 222a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 223a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 224a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Janguint32_t HdmiCecController::getVendorId() { 225a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang uint32_t vendorId = 0; 226a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang mDevice->get_vendor_id(mDevice, &vendorId); 227a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return vendorId; 228a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 229a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 2300340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk KimjobjectArray HdmiCecController::getPortInfos() { 2310340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim JNIEnv* env = AndroidRuntime::getJNIEnv(); 23263dd3bb3602bc00557680432b08b49a5a15bcdb7Jinsuk Kim jclass hdmiPortInfo = env->FindClass("android/hardware/hdmi/HdmiPortInfo"); 2330340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (hdmiPortInfo == NULL) { 2340340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return NULL; 2350340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2360340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jmethodID ctor = env->GetMethodID(hdmiPortInfo, "<init>", "(IIIZZZ)V"); 2370340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim if (ctor == NULL) { 2380340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return NULL; 2390340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2400340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim hdmi_port_info* ports; 2410340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim int numPorts; 2420340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim mDevice->get_port_info(mDevice, &ports, &numPorts); 2430340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jobjectArray res = env->NewObjectArray(numPorts, hdmiPortInfo, NULL); 2440340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 2450340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim // MHL support field will be obtained from MHL HAL. Leave it to false. 2460340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jboolean mhlSupported = (jboolean) 0; 2470340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim for (int i = 0; i < numPorts; ++i) { 2480340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim hdmi_port_info* info = &ports[i]; 2490340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jboolean cecSupported = (jboolean) info->cec_supported; 2500340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim jboolean arcSupported = (jboolean) info->arc_supported; 251284c31b92e4e0d0b8095ae50c61db9c83c9d577cJinsuk Kim jobject infoObj = env->NewObject(hdmiPortInfo, ctor, info->port_id, info->type, 2520340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim info->physical_address, cecSupported, mhlSupported, arcSupported); 2530340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim env->SetObjectArrayElement(res, i, infoObj); 2540340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim } 2550340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return res; 2560340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim} 2570340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 258092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangvoid HdmiCecController::setOption(int flag, int value) { 259092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang mDevice->set_option(mDevice, flag, value); 260092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 261092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 262092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang// Set audio return channel status. 2631481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim void HdmiCecController::setAudioReturnChannel(int port, bool enabled) { 2641481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim mDevice->set_audio_return_channel(mDevice, port, enabled ? 1 : 0); 265092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 266092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 267092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang// Whether to hdmi device is connected to the given port. 268092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangbool HdmiCecController::isConnected(int port) { 269092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return mDevice->is_connected(mDevice, port) == HDMI_CONNECTED; 270092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 271092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 2720792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang// static 2730792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangvoid HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) { 274e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCecController* controller = static_cast<HdmiCecController*>(arg); 275e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang if (controller == NULL) { 2760792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang return; 2770792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang } 2780792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 2794085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang sp<CecEventWrapper> spEvent(new CecEventWrapper(*event)); 2804085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang sp<HdmiCecEventHandler> handler(new HdmiCecEventHandler(controller, spEvent)); 2814085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang controller->mLooper->sendMessage(handler, event->type); 2820792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} 2830792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 2840792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang//------------------------------------------------------------------------------ 285e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 286e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang var = env->GetMethodID(clazz, methodName, methodDescriptor); \ 287e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang LOG_FATAL_IF(! var, "Unable to find method " methodName); 288e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 2894085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jangstatic jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj, 2904085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang jobject messageQueueObj) { 291e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang int err; 292e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang hw_module_t* module; 2934085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang err = hw_get_module(HDMI_CEC_HARDWARE_MODULE_ID, 294e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang const_cast<const hw_module_t **>(&module)); 295e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang if (err != 0) { 296e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang ALOGE("Error acquiring hardware module: %d", err); 297e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang return 0; 298e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 2994085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 300e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang hw_device_t* device; 3014085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang err = module->methods->open(module, HDMI_CEC_HARDWARE_INTERFACE, &device); 302e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang if (err != 0) { 303e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang ALOGE("Error opening hardware module: %d", err); 304e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang return 0; 305e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang } 3060792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 3074085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang sp<MessageQueue> messageQueue = 3084085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang android_os_MessageQueue_getMessageQueue(env, messageQueueObj); 3094085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang 3100792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang HdmiCecController* controller = new HdmiCecController( 311e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang reinterpret_cast<hdmi_cec_device*>(device), 3124085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang env->NewGlobalRef(callbacksObj), 3134085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang messageQueue->getLooper()); 314e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang controller->init(); 315e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 316e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang GET_METHOD_ID(gHdmiCecControllerClassInfo.handleIncomingCecCommand, clazz, 317e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang "handleIncomingCecCommand", "(II[B)V"); 318e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang GET_METHOD_ID(gHdmiCecControllerClassInfo.handleHotplug, clazz, 31942230728b8212738c2351939c5577730f05a58deJungshik Jang "handleHotplug", "(IZ)V"); 3200792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 3210792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang return reinterpret_cast<jlong>(controller); 3220792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} 3230792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 324e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jangstatic jint nativeSendCecCommand(JNIEnv* env, jclass clazz, jlong controllerPtr, 325e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang jint srcAddr, jint dstAddr, jbyteArray body) { 326e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang cec_message_t message; 327e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang message.initiator = static_cast<cec_logical_address_t>(srcAddr); 328e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang message.destination = static_cast<cec_logical_address_t>(dstAddr); 329e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 330e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang jsize len = env->GetArrayLength(body); 331e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang message.length = MIN(len, CEC_MESSAGE_BODY_MAX_LENGTH); 332e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang ScopedByteArrayRO bodyPtr(env, body); 333d0efcbbbb5145da42beafd36f86a6d90047ce9afJae Seo std::memcpy(message.body, bodyPtr.get(), message.length); 334e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 335e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang HdmiCecController* controller = 336e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang reinterpret_cast<HdmiCecController*>(controllerPtr); 337e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang return controller->sendMessage(message); 338e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang} 339e9c77c88ea34a66f83a94f960547275c0ff6bd07Jungshik Jang 340a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimstatic jint nativeAddLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr, 341a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim jint logicalAddress) { 342a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 343a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim return controller->addLogicalAddress(static_cast<cec_logical_address_t>(logicalAddress)); 344a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 345a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 346a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimstatic void nativeClearLogicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) { 347a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 348a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang controller->clearLogicaladdress(); 349a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 350a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 351a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimstatic jint nativeGetPhysicalAddress(JNIEnv* env, jclass clazz, jlong controllerPtr) { 352a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 353a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return controller->getPhysicalAddress(); 354a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 355a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 356a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimstatic jint nativeGetVersion(JNIEnv* env, jclass clazz, jlong controllerPtr) { 357a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 358a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return controller->getVersion(); 359a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 360a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 361a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jangstatic jint nativeGetVendorId(JNIEnv* env, jclass clazz, jlong controllerPtr) { 362a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 363a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang return controller->getVendorId(); 364a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang} 365a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang 3660340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kimstatic jobjectArray nativeGetPortInfos(JNIEnv* env, jclass clazz, jlong controllerPtr) { 3670340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 3680340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim return controller->getPortInfos(); 3690340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim} 3700340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim 371a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kimstatic void nativeSetOption(JNIEnv* env, jclass clazz, jlong controllerPtr, jint flag, jint value) { 372a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 373092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang controller->setOption(flag, value); 374092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 375092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 376092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangstatic void nativeSetAudioReturnChannel(JNIEnv* env, jclass clazz, jlong controllerPtr, 3771481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim jint port, jboolean enabled) { 378a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 3791481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim controller->setAudioReturnChannel(port, enabled == JNI_TRUE); 380092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 381092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 382092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jangstatic jboolean nativeIsConnected(JNIEnv* env, jclass clazz, jlong controllerPtr, jint port) { 383a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim HdmiCecController* controller = reinterpret_cast<HdmiCecController*>(controllerPtr); 384092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang return controller->isConnected(port) ? JNI_TRUE : JNI_FALSE ; 385092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang} 386092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang 38776f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod sMethods[] = { 3880792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang /* name, signature, funcPtr */ 3894085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang { "nativeInit", 3904085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang "(Lcom/android/server/hdmi/HdmiCecController;Landroid/os/MessageQueue;)J", 3914085d0ef62554c7e139b82bca0f97161bb159f8cJungshik Jang (void *) nativeInit }, 392a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeSendCecCommand", "(JII[B)I", (void *) nativeSendCecCommand }, 393a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeAddLogicalAddress", "(JI)I", (void *) nativeAddLogicalAddress }, 394a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeClearLogicalAddress", "(J)V", (void *) nativeClearLogicalAddress }, 395a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeGetPhysicalAddress", "(J)I", (void *) nativeGetPhysicalAddress }, 396a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeGetVersion", "(J)I", (void *) nativeGetVersion }, 397a9095ba488ea18aeafaf9c3a8258bf9f459bda71Jungshik Jang { "nativeGetVendorId", "(J)I", (void *) nativeGetVendorId }, 3980340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim { "nativeGetPortInfos", 39963dd3bb3602bc00557680432b08b49a5a15bcdb7Jinsuk Kim "(J)[Landroid/hardware/hdmi/HdmiPortInfo;", 4000340bbc89f8162f9c2a298c98b03bfcdd1bc6e87Jinsuk Kim (void *) nativeGetPortInfos }, 401092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang { "nativeSetOption", "(JII)V", (void *) nativeSetOption }, 4021481a4282818939436f590d8c88aea2d19166b8eJinsuk Kim { "nativeSetAudioReturnChannel", "(JIZ)V", (void *) nativeSetAudioReturnChannel }, 403092b445ef898e3c1e5b2918b554480940f0f5a28Jungshik Jang { "nativeIsConnected", "(JI)Z", (void *) nativeIsConnected }, 4040792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang}; 4050792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 4060792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang#define CLASS_PATH "com/android/server/hdmi/HdmiCecController" 4070792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 4080792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jangint register_android_server_hdmi_HdmiCecController(JNIEnv* env) { 409a6ce7708d6124224399241503fadcafe0c4684d4Jinsuk Kim int res = jniRegisterNativeMethods(env, CLASS_PATH, sMethods, NELEM(sMethods)); 4100792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang LOG_FATAL_IF(res < 0, "Unable to register native methods."); 4114048a4bcb1ea709ddb83a4fde3ff5c53e642f7d0Bernhard Rosenkränzer (void)res; // Don't scream about unused variable in the LOG_NDEBUG case 4120792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang return 0; 4130792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} 4140792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang 4150792d37385e60aa8d73f8df174d0a32f4f618bc4Jungshik Jang} /* namespace android */ 416