Merge "CEC: Handle <Active Source> arriving before TvInputCallback.onAddInput" into lmp-mr1-dev
This commit is contained in:
@@ -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><Active Source> is not processed in this method but processed
|
||||
* separately via {@link #processActiveSource()}.
|
||||
* <p><Active Source> 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,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.
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user