diff options
author | Jinsuk Kim <jinsukkim@google.com> | 2014-04-29 21:38:19 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-04-29 21:38:19 +0000 |
commit | c79224e4b70c27293a6744f29d73653a3c5ee018 (patch) | |
tree | 35960a7ae541a97a95e3f5f60e33a78edaa7b18d | |
parent | 989a4e9b13a6900ab8f5c0c1b0a7340346fd8cdf (diff) | |
parent | 60037302208be033442cc3f3c50a25c7064ebbd1 (diff) | |
download | frameworks_base-c79224e4b70c27293a6744f29d73653a3c5ee018.zip frameworks_base-c79224e4b70c27293a6744f29d73653a3c5ee018.tar.gz frameworks_base-c79224e4b70c27293a6744f29d73653a3c5ee018.tar.bz2 |
am 60037302: am 8fe27e88: Merge "Move logical address allocation logic into native service from HAL" into klp-modular-dev
* commit '60037302208be033442cc3f3c50a25c7064ebbd1':
Move logical address allocation logic into native service from HAL
-rw-r--r-- | services/core/jni/com_android_server_hdmi_HdmiCecService.cpp | 216 |
1 files changed, 167 insertions, 49 deletions
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp index 54c9755..6e03993 100644 --- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp +++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp @@ -67,10 +67,10 @@ public: cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType); uint16_t getPhysicalAddress(); - int getDeviceType(cec_logical_address_t addr); + cec_device_type_t getDeviceType(cec_logical_address_t addr); void queueMessage(const MessageEntry& message); void queueOutgoingMessage(const cec_message_t& message); - void sendReportPhysicalAddress(); + void sendReportPhysicalAddress(cec_logical_address_t srcAddr); void sendActiveSource(cec_logical_address_t srcAddr); void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr, int opcode, int reason); @@ -93,15 +93,41 @@ private: EVENT_TYPE_STANDBY }; + /* + * logical address pool for each device type. + */ + static const cec_logical_address_t TV_ADDR_POOL[]; + static const cec_logical_address_t PLAYBACK_ADDR_POOL[]; + static const cec_logical_address_t RECORDER_ADDR_POOL[]; + static const cec_logical_address_t TUNER_ADDR_POOL[]; + static const unsigned int MAX_BUFFER_SIZE = 256; static const uint16_t INVALID_PHYSICAL_ADDRESS = 0xFFFF; - static const int INACTIVE_DEVICE_TYPE = -1; static void onReceived(const hdmi_event_t* event, void* arg); static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); void updatePhysicalAddress(); void updateLogicalAddress(); + + // Allocate logical address. The CEC standard recommends that we try to use the address + // we have ever used before, in case this is to allocate an address afte the cable is + // connected again. If preferredAddr is given a valid one (not CEC_ADDR_UNREGISTERED), then + // this method checks if the address is available first. If not, it tries other addresses + // int the address pool available for the given type. + cec_logical_address_t allocateLogicalAddress(cec_device_type_t type, + cec_logical_address_t preferredAddr); + + // Send a CEC ping message. Returns true if successful. + bool sendPing(cec_logical_address_t addr); + + // Return the pool of logical addresses that are used for a given device type. + // One of the addresses in the pool will be chosen in the allocation logic. + bool getLogicalAddressPool(cec_device_type_t type, const cec_logical_address_t** addrPool, + size_t* poolSize); + + // Handles the message retrieved from internal message queue. The message can be + // for either rx or tx. void dispatchMessage(const MessageEntry& message); void processIncomingMessage(const cec_message_t& msg); @@ -159,6 +185,29 @@ private: std::string mOsdName; }; + const cec_logical_address_t HdmiCecHandler::TV_ADDR_POOL[] = { + CEC_ADDR_TV, + CEC_ADDR_FREE_USE, + }; + + const cec_logical_address_t HdmiCecHandler::PLAYBACK_ADDR_POOL[] = { + CEC_ADDR_PLAYBACK_1, + CEC_ADDR_PLAYBACK_2, + CEC_ADDR_PLAYBACK_3 + }; + + const cec_logical_address_t HdmiCecHandler::RECORDER_ADDR_POOL[] = { + CEC_ADDR_RECORDER_1, + CEC_ADDR_RECORDER_2, + CEC_ADDR_RECORDER_3 + }; + + const cec_logical_address_t HdmiCecHandler::TUNER_ADDR_POOL[] = { + CEC_ADDR_TUNER_1, + CEC_ADDR_TUNER_2, + CEC_ADDR_TUNER_3, + CEC_ADDR_TUNER_4 + }; HdmiCecHandler::HdmiCecHandler(hdmi_cec_device_t* device, jobject callbacksObj) : mDevice(device), @@ -176,39 +225,15 @@ uint16_t HdmiCecHandler::getPhysicalAddress() { return mPhysicalAddress; } -void HdmiCecHandler::updatePhysicalAddress() { - uint16_t addr; - if (!mDevice->get_physical_address(mDevice, &addr)) { - mPhysicalAddress = addr; - } else { - mPhysicalAddress = INVALID_PHYSICAL_ADDRESS; - } -} - -void HdmiCecHandler::updateLogicalAddress() { - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); - for (; it != mLogicalDevices.end(); ++it) { - cec_logical_address_t addr; - if (!mDevice->get_logical_address(mDevice, it->first, &addr)) { - it->second = addr; - } - } -} - cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) { - cec_logical_address_t addr; - int res = mDevice->allocate_logical_address(mDevice, type, &addr); - - if (res != 0) { - ALOGE("Logical Address Allocation failed: %d", res); - } else { - ALOGV("Logical Address Allocation success: %d", addr); + cec_logical_address addr = allocateLogicalAddress(type, CEC_ADDR_UNREGISTERED); + if (addr != CEC_ADDR_UNREGISTERED && !mDevice->add_logical_address(mDevice, addr)) { mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr)); // Broadcast <Report Physical Address> when a new logical address was allocated to let // other devices discover the new logical device and its logical - physical address // association. - sendReportPhysicalAddress(); + sendReportPhysicalAddress(addr); } return addr; } @@ -229,14 +254,14 @@ cec_logical_address_t HdmiCecHandler::getLogicalAddress(cec_device_type_t type) return CEC_ADDR_UNREGISTERED; } -int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) { +cec_device_type_t HdmiCecHandler::getDeviceType(cec_logical_address_t addr) { std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); for (; it != mLogicalDevices.end(); ++it) { if (it->second == addr) { return it->first; } } - return INACTIVE_DEVICE_TYPE; + return CEC_DEVICE_INACTIVE; } void HdmiCecHandler::queueMessage(const MessageEntry& entry) { @@ -256,26 +281,26 @@ void HdmiCecHandler::queueOutgoingMessage(const cec_message_t& message) { queueMessage(entry); } -void HdmiCecHandler::sendReportPhysicalAddress() { +void HdmiCecHandler::sendReportPhysicalAddress(cec_logical_address_t addr) { if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { ALOGE("Invalid physical address."); return; } - - // Report physical address for each logical one hosted in it. - std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); - while (it != mLogicalDevices.end()) { - cec_message_t msg; - msg.initiator = it->second; // logical address - msg.destination = CEC_ADDR_BROADCAST; - msg.length = 4; - msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS; - msg.body[1] = (mPhysicalAddress >> 8) & 0xff; - msg.body[2] = mPhysicalAddress & 0xff; - msg.body[3] = it->first; // device type - queueOutgoingMessage(msg); - ++it; + cec_device_type_t deviceType = getDeviceType(addr); + if (deviceType == CEC_DEVICE_INACTIVE) { + ALOGE("Invalid logical address: %d", addr); + return; } + + cec_message_t msg; + msg.initiator = addr; + msg.destination = CEC_ADDR_BROADCAST; + msg.length = 4; + msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS; + msg.body[1] = (mPhysicalAddress >> 8) & 0xff; + msg.body[2] = mPhysicalAddress & 0xff; + msg.body[3] = deviceType; + queueOutgoingMessage(msg); } void HdmiCecHandler::sendActiveSource(cec_logical_address_t srcAddr) { @@ -410,6 +435,99 @@ void HdmiCecHandler::checkAndClearExceptionFromCallback(JNIEnv* env, const char* } } +void HdmiCecHandler::updatePhysicalAddress() { + uint16_t addr; + if (!mDevice->get_physical_address(mDevice, &addr)) { + mPhysicalAddress = addr; + } else { + mPhysicalAddress = INVALID_PHYSICAL_ADDRESS; + } +} + +void HdmiCecHandler::updateLogicalAddress() { + mDevice->clear_logical_address(mDevice); + std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin(); + for (; it != mLogicalDevices.end(); ++it) { + cec_logical_address_t addr; + cec_logical_address_t preferredAddr = it->second; + cec_device_type_t deviceType = it->first; + addr = allocateLogicalAddress(deviceType, preferredAddr); + if (!mDevice->add_logical_address(mDevice, addr)) { + it->second = addr; + } else { + it->second = CEC_ADDR_UNREGISTERED; + } + } +} + +cec_logical_address_t HdmiCecHandler::allocateLogicalAddress(cec_device_type_t type, + cec_logical_address_t preferredAddr) { + const cec_logical_address_t* addrPool; + size_t poolSize; + if (getLogicalAddressPool(type, &addrPool, &poolSize) < 0) { + return CEC_ADDR_UNREGISTERED; + } + unsigned start = 0; + + // Find the index of preferred address in the pool. If not found, the start + // position will be 0. This happens when the passed preferredAddr is set to + // CEC_ADDR_UNREGISTERED, meaning that no preferred address is given. + for (unsigned i = 0; i < poolSize; i++) { + if (addrPool[i] == preferredAddr) { + start = i; + break; + } + } + for (unsigned i = 0; i < poolSize; i++) { + cec_logical_address_t addr = addrPool[(start + i) % poolSize]; + if (!sendPing(addr)) { + // Failure in pinging means the address is available, not taken by any device. + ALOGV("Logical Address Allocation success: %d", addr); + return addr; + } + } + ALOGE("Logical Address Allocation failed"); + return CEC_ADDR_UNREGISTERED; +} + +bool HdmiCecHandler::sendPing(cec_logical_address addr) { + cec_message_t msg; + msg.initiator = msg.destination = addr; + msg.length = 0; + return !mDevice->send_message(mDevice, &msg); + +} + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +bool HdmiCecHandler::getLogicalAddressPool(cec_device_type_t deviceType, + const cec_logical_address_t** addrPool, size_t* poolSize) { + switch (deviceType) { + case CEC_DEVICE_TV: + *addrPool = TV_ADDR_POOL; + *poolSize = ARRAY_SIZE(TV_ADDR_POOL); + break; + case CEC_DEVICE_RECORDER: + *addrPool = RECORDER_ADDR_POOL; + *poolSize = ARRAY_SIZE(RECORDER_ADDR_POOL); + break; + case CEC_DEVICE_TUNER: + *addrPool = TUNER_ADDR_POOL; + *poolSize = ARRAY_SIZE(TUNER_ADDR_POOL); + break; + case CEC_DEVICE_PLAYBACK: + *addrPool = PLAYBACK_ADDR_POOL; + *poolSize = ARRAY_SIZE(PLAYBACK_ADDR_POOL); + break; + default: + ALOGE("Unsupported device type: %d", deviceType); + return false; + } + return true; +} + +#undef ARRAY_SIZE + void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) { int type = entry.first; mMessageQueueLock.unlock(); @@ -434,7 +552,7 @@ void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) { void HdmiCecHandler::processIncomingMessage(const cec_message_t& msg) { int opcode = msg.body[0]; if (opcode == CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS) { - sendReportPhysicalAddress(); + sendReportPhysicalAddress(msg.destination); } else if (opcode == CEC_MESSAGE_REQUEST_ACTIVE_SOURCE) { handleRequestActiveSource(); } else if (opcode == CEC_MESSAGE_GET_OSD_NAME) { @@ -507,7 +625,7 @@ void HdmiCecHandler::handleRequestActiveSource() { JNIEnv* env = AndroidRuntime::getJNIEnv(); jint activeDeviceType = env->CallIntMethod(mCallbacksObj, gHdmiCecServiceClassInfo.getActiveSource); - if (activeDeviceType != INACTIVE_DEVICE_TYPE) { + if (activeDeviceType != CEC_DEVICE_INACTIVE) { sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType))); } checkAndClearExceptionFromCallback(env, __FUNCTION__); |