summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJinsuk Kim <jinsukkim@google.com>2014-04-29 21:38:19 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-04-29 21:38:19 +0000
commitc79224e4b70c27293a6744f29d73653a3c5ee018 (patch)
tree35960a7ae541a97a95e3f5f60e33a78edaa7b18d
parent989a4e9b13a6900ab8f5c0c1b0a7340346fd8cdf (diff)
parent60037302208be033442cc3f3c50a25c7064ebbd1 (diff)
downloadframeworks_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.cpp216
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__);