diff options
| author | 2015-01-16 08:17:07 +0000 | |
|---|---|---|
| committer | 2015-01-16 08:17:07 +0000 | |
| commit | 2bf3b2c49c28d028ff615ba49cc876da8ae02fc3 (patch) | |
| tree | ab5b01cda3d87fab78b412a9081000eb65036624 | |
| parent | d3403e45d6d89d0307c0fc9427cc84792ac6ee83 (diff) | |
| parent | 964c00dd7b270dcf80aea3450bbfc23502965cce (diff) | |
am 964c00dd: CEC: Buffer Cec messages while allocating logical address
* commit '964c00dd7b270dcf80aea3450bbfc23502965cce':
CEC: Buffer Cec messages while allocating logical address
| -rw-r--r-- | services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java | 30 | ||||
| -rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiControlService.java | 73 |
2 files changed, 93 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java index d3ecff0f188a..c908145a6c72 100644 --- a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java +++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java @@ -77,11 +77,13 @@ final class DelayedMessageBuffer { } void processAllMessages() { - for (HdmiCecMessage message : mBuffer) { + // Use the copied buffer. + ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer); + mBuffer.clear(); + for (HdmiCecMessage message : copiedBuffer) { mDevice.onMessage(message); HdmiLogger.debug("Processing message:" + message); } - mBuffer.clear(); } /** @@ -95,15 +97,21 @@ final class DelayedMessageBuffer { * are associated with */ void processMessagesForDevice(int address) { + ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer); + mBuffer.clear(); HdmiLogger.debug("Checking message for address:" + address); - for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) { - HdmiCecMessage message = iter.next(); - if (message.getSource() != address) continue; + for (HdmiCecMessage message : copiedBuffer) { + if (message.getSource() != address) { + mBuffer.add(message); + continue; + } if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE - && !mDevice.isInputReady(HdmiDeviceInfo.idForCecDevice(address))) continue; + && !mDevice.isInputReady(HdmiDeviceInfo.idForCecDevice(address))) { + mBuffer.add(message); + continue; + } mDevice.onMessage(message); HdmiLogger.debug("Processing message:" + message); - iter.remove(); } } @@ -119,13 +127,15 @@ final class DelayedMessageBuffer { * @param address logical address of the device to be the active source */ void processActiveSource(int address) { - for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) { - HdmiCecMessage message = iter.next(); + ArrayList<HdmiCecMessage> copiedBuffer = new ArrayList<HdmiCecMessage>(mBuffer); + mBuffer.clear(); + for (HdmiCecMessage message : copiedBuffer) { if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE && message.getSource() == address) { mDevice.onMessage(message); HdmiLogger.debug("Processing message:" + message); - iter.remove(); + } else { + mBuffer.add(message); } } } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index cc8c53c653f2..37909cca4887 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -286,6 +286,69 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly private int mLastInputMhl = Constants.INVALID_PORT_ID; + // Set to true if the logical address allocation is completed. + private boolean mAddressAllocated = false; + + // Buffer for processing the incoming cec messages while allocating logical addresses. + private final class CecMessageBuffer { + private List<HdmiCecMessage> mBuffer = new ArrayList<>(); + + public void bufferMessage(HdmiCecMessage message) { + switch (message.getOpcode()) { + case Constants.MESSAGE_ACTIVE_SOURCE: + bufferActiveSource(message); + break; + case Constants.MESSAGE_IMAGE_VIEW_ON: + case Constants.MESSAGE_TEXT_VIEW_ON: + bufferImageOrTextViewOn(message); + break; + // Add here if new message that needs to buffer + default: + // Do not need to buffer messages other than above + break; + } + } + + public void processMessages() { + for (final HdmiCecMessage message : mBuffer) { + runOnServiceThread(new Runnable() { + @Override + public void run() { + handleCecCommand(message); + } + }); + } + mBuffer.clear(); + } + + private void bufferActiveSource(HdmiCecMessage message) { + if (!replaceMessageIfBuffered(message, Constants.MESSAGE_ACTIVE_SOURCE)) { + mBuffer.add(message); + } + } + + private void bufferImageOrTextViewOn(HdmiCecMessage message) { + if (!replaceMessageIfBuffered(message, Constants.MESSAGE_IMAGE_VIEW_ON) && + !replaceMessageIfBuffered(message, Constants.MESSAGE_TEXT_VIEW_ON)) { + mBuffer.add(message); + } + } + + // Returns true if the message is replaced + private boolean replaceMessageIfBuffered(HdmiCecMessage message, int opcode) { + for (int i = 0; i < mBuffer.size(); i++) { + HdmiCecMessage bufferedMessage = mBuffer.get(i); + if (bufferedMessage.getOpcode() == opcode) { + mBuffer.set(i, message); + return true; + } + } + return false; + } + } + + private CecMessageBuffer mCecMessageBuffer = new CecMessageBuffer(); + public HdmiControlService(Context context) { super(context); mLocalDevices = getIntList(SystemProperties.get(Constants.PROPERTY_DEVICE_TYPE)); @@ -474,6 +537,7 @@ public final class HdmiControlService extends SystemService { } private void initializeCec(int initiatedBy) { + mAddressAllocated = false; mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, ENABLED); initializeLocalDevices(initiatedBy); } @@ -504,6 +568,8 @@ public final class HdmiControlService extends SystemService { mCecController.clearLogicalAddress(); final ArrayList<HdmiCecLocalDevice> allocatedDevices = new ArrayList<>(); final int[] finished = new int[1]; + mAddressAllocated = allocatingDevices.isEmpty(); + for (final HdmiCecLocalDevice localDevice : allocatingDevices) { mCecController.allocateLogicalAddress(localDevice.getType(), localDevice.getPreferredAddress(), new AllocateAddressCallback() { @@ -524,12 +590,14 @@ public final class HdmiControlService extends SystemService { // Address allocation completed for all devices. Notify each device. if (allocatingDevices.size() == ++finished[0]) { + mAddressAllocated = true; if (initiatedBy != INITIATED_BY_HOTPLUG) { // In case of the hotplug we don't call onInitializeCecComplete() // since we reallocate the logical address only. onInitializeCecComplete(initiatedBy); } notifyAddressAllocated(allocatedDevices, initiatedBy); + mCecMessageBuffer.processMessages(); } } }); @@ -762,6 +830,10 @@ public final class HdmiControlService extends SystemService { @ServiceThreadOnly boolean handleCecCommand(HdmiCecMessage message) { assertRunOnServiceThread(); + if (!mAddressAllocated) { + mCecMessageBuffer.bufferMessage(message); + return true; + } int errorCode = mMessageValidator.isValid(message); if (errorCode != HdmiCecMessageValidator.OK) { // We'll not response on the messages with the invalid source or destination @@ -1990,6 +2062,7 @@ public final class HdmiControlService extends SystemService { device.onStandby(mStandbyMessageReceived); } mStandbyMessageReceived = false; + mAddressAllocated = false; mCecController.setOption(OPTION_CEC_SERVICE_CONTROL, DISABLED); } |