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
|
* Process messages from a given logical device. Called by
|
||||||
* {@link NewDeviceAction} actions when they finish adding the device
|
* {@link NewDeviceAction} actions when they finish adding the device
|
||||||
* information.
|
* information.
|
||||||
* <p><Active Source> is not processed in this method but processed
|
* <p><Active Source> is processed only when the TV input is ready.
|
||||||
* separately via {@link #processActiveSource()}.
|
* If not, {@link #processActiveSource()} will be invoked later to handle it.
|
||||||
*
|
*
|
||||||
* @param address logical address of CEC device which the messages to process
|
* @param address logical address of CEC device which the messages to process
|
||||||
* are associated with
|
* are associated with
|
||||||
*/
|
*/
|
||||||
void processMessagesForDevice(int address) {
|
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(); ) {
|
for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) {
|
||||||
HdmiCecMessage message = iter.next();
|
HdmiCecMessage message = iter.next();
|
||||||
if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE) {
|
if (message.getSource() != address) continue;
|
||||||
continue;
|
if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE
|
||||||
}
|
&& !mDevice.isInputReady(HdmiDeviceInfo.idForCecDevice(address))) continue;
|
||||||
if (message.getSource() == address) {
|
mDevice.onMessage(message);
|
||||||
mDevice.onMessage(message);
|
HdmiLogger.debug("Processing message:" + message);
|
||||||
HdmiLogger.debug("Processing message:" + message);
|
iter.remove();
|
||||||
iter.remove();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,6 +190,17 @@ abstract class HdmiCecLocalDevice {
|
|||||||
*/
|
*/
|
||||||
protected abstract void setPreferredAddress(int addr);
|
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.
|
* Dispatch incoming message.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent a logical device of type TV residing in Android system.
|
* 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) {
|
public void onInputAdded(String inputId) {
|
||||||
TvInputInfo tvInfo = mService.getTvInputManager().getTvInputInfo(inputId);
|
TvInputInfo tvInfo = mService.getTvInputManager().getTvInputInfo(inputId);
|
||||||
HdmiDeviceInfo info = tvInfo.getHdmiDeviceInfo();
|
HdmiDeviceInfo info = tvInfo.getHdmiDeviceInfo();
|
||||||
if (info != null && info.isCecDevice()) {
|
if (info == null) return;
|
||||||
mDelayedMessageBuffer.processActiveSource(info.getLogicalAddress());
|
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) {
|
HdmiCecLocalDeviceTv(HdmiControlService service) {
|
||||||
super(service, HdmiDeviceInfo.DEVICE_TV);
|
super(service, HdmiDeviceInfo.DEVICE_TV);
|
||||||
mPrevPortId = Constants.INVALID_PORT_ID;
|
mPrevPortId = Constants.INVALID_PORT_ID;
|
||||||
@@ -168,6 +201,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
|||||||
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
|
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
|
||||||
mAddress, mService.getVendorId()));
|
mAddress, mService.getVendorId()));
|
||||||
mCecSwitches.add(mService.getPhysicalAddress()); // TV is a CEC switch too.
|
mCecSwitches.add(mService.getPhysicalAddress()); // TV is a CEC switch too.
|
||||||
|
mTvInputs.clear();
|
||||||
mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
|
mSkipRoutingControl = (reason == HdmiControlService.INITIATED_BY_WAKE_UP_MESSAGE);
|
||||||
launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
|
launchRoutingControl(reason != HdmiControlService.INITIATED_BY_ENABLE_CEC &&
|
||||||
reason != HdmiControlService.INITIATED_BY_BOOT_UP);
|
reason != HdmiControlService.INITIATED_BY_BOOT_UP);
|
||||||
@@ -447,8 +481,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
|||||||
HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress);
|
HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress);
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
if (!handleNewDeviceAtTheTailOfActivePath(physicalAddress)) {
|
if (!handleNewDeviceAtTheTailOfActivePath(physicalAddress)) {
|
||||||
|
HdmiLogger.debug("Device info not found: %X; buffering the command", logicalAddress);
|
||||||
mDelayedMessageBuffer.add(message);
|
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 {
|
} else {
|
||||||
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
|
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
|
||||||
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
|
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
|
||||||
@@ -1776,6 +1814,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
|
|||||||
mDelayedMessageBuffer.processMessagesForDevice(address);
|
mDelayedMessageBuffer.processMessagesForDevice(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ServiceThreadOnly
|
||||||
|
void processDelayedActiveSource(int address) {
|
||||||
|
assertRunOnServiceThread();
|
||||||
|
mDelayedMessageBuffer.processActiveSource(address);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void dump(final IndentingPrintWriter pw) {
|
protected void dump(final IndentingPrintWriter pw) {
|
||||||
super.dump(pw);
|
super.dump(pw);
|
||||||
|
|||||||
Reference in New Issue
Block a user