summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java20
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java11
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java48
3 files changed, 66 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
index 922a2c14c4cc..d3ecff0f188a 100644
--- a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
+++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
@@ -88,24 +88,22 @@ final class DelayedMessageBuffer {
* Process messages from a given logical device. Called by
* {@link NewDeviceAction} actions when they finish adding the device
* information.
- * <p>&lt;Active Source&gt; is not processed in this method but processed
- * separately via {@link #processActiveSource()}.
+ * <p>&lt;Active Source&gt; is processed only when the TV input is ready.
+ * If not, {@link #processActiveSource()} will be invoked later to handle it.
*
* @param address logical address of CEC device which the messages to process
* are associated with
*/
void processMessagesForDevice(int address) {
- HdmiLogger.debug("Processing message for address:" + address);
+ HdmiLogger.debug("Checking message for address:" + address);
for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) {
HdmiCecMessage message = iter.next();
- if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE) {
- continue;
- }
- if (message.getSource() == address) {
- mDevice.onMessage(message);
- HdmiLogger.debug("Processing message:" + message);
- iter.remove();
- }
+ if (message.getSource() != address) continue;
+ if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE
+ && !mDevice.isInputReady(HdmiDeviceInfo.idForCecDevice(address))) continue;
+ mDevice.onMessage(message);
+ HdmiLogger.debug("Processing message:" + message);
+ iter.remove();
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index 4f8b9fbc71f5..1b478885e9cb 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -191,6 +191,17 @@ abstract class HdmiCecLocalDevice {
protected abstract void setPreferredAddress(int addr);
/**
+ * Returns true if the TV input associated with the CEC device is ready
+ * to accept further processing such as input switching. This is used
+ * to buffer certain CEC commands and process it later if the input is not
+ * ready yet. For other types of local devices(non-TV), this method returns
+ * true by default to let the commands be processed right away.
+ */
+ protected boolean isInputReady(int deviceId) {
+ return true;
+ }
+
+ /**
* Dispatch incoming message.
*
* @param message incoming message
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 90dbd1765200..a8941619dc2d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -63,6 +63,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.HashMap;
/**
* Represent a logical device of type TV residing in Android system.
@@ -143,12 +144,44 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
public void onInputAdded(String inputId) {
TvInputInfo tvInfo = mService.getTvInputManager().getTvInputInfo(inputId);
HdmiDeviceInfo info = tvInfo.getHdmiDeviceInfo();
- if (info != null && info.isCecDevice()) {
- mDelayedMessageBuffer.processActiveSource(info.getLogicalAddress());
+ if (info == null) return;
+ addTvInput(inputId, info.getId());
+ if (info.isCecDevice()) {
+ processDelayedActiveSource(info.getLogicalAddress());
}
}
+
+ @Override
+ public void onInputRemoved(String inputId) {
+ removeTvInput(inputId);
+ }
};
+ // Keeps the mapping (TV input ID, HDMI device ID) to keep track of the TV inputs ready to
+ // accept input switching request from HDMI devices. Requests for which the corresponding
+ // input ID is not yet registered by TV input framework need to be buffered for delayed
+ // processing.
+ private final HashMap<String, Integer> mTvInputs = new HashMap<>();
+
+ @ServiceThreadOnly
+ private void addTvInput(String inputId, int deviceId) {
+ assertRunOnServiceThread();
+ mTvInputs.put(inputId, deviceId);
+ }
+
+ @ServiceThreadOnly
+ private void removeTvInput(String inputId) {
+ assertRunOnServiceThread();
+ mTvInputs.remove(inputId);
+ }
+
+ @Override
+ @ServiceThreadOnly
+ protected boolean isInputReady(int deviceId) {
+ assertRunOnServiceThread();
+ return mTvInputs.containsValue(deviceId);
+ }
+
HdmiCecLocalDeviceTv(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_TV);
mPrevPortId = Constants.INVALID_PORT_ID;
@@ -168,6 +201,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
mAddress, mService.getVendorId()));
mCecSwitches.add(mService.getPhysicalAddress()); // TV is a CEC switch too.
+ mTvInputs.clear();
mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
reason != HdmiControlService.INITIATED_BY_BOOT_UP);
@@ -447,8 +481,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress);
if (info == null) {
if (!handleNewDeviceAtTheTailOfActivePath(physicalAddress)) {
+ HdmiLogger.debug("Device info not found: %X; buffering the command", logicalAddress);
mDelayedMessageBuffer.add(message);
}
+ } else if (!isInputReady(info.getId())) {
+ HdmiLogger.debug("Input not ready for device: %X; buffering the command", info.getId());
+ mDelayedMessageBuffer.add(message);
} else {
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
@@ -1776,6 +1814,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
mDelayedMessageBuffer.processMessagesForDevice(address);
}
+ @ServiceThreadOnly
+ void processDelayedActiveSource(int address) {
+ assertRunOnServiceThread();
+ mDelayedMessageBuffer.processActiveSource(address);
+ }
+
@Override
protected void dump(final IndentingPrintWriter pw) {
super.dump(pw);