Loading services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java +9 −11 Original line number Original line Diff line number Diff line Loading @@ -88,26 +88,24 @@ 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(); } } } } } /** /** * Process <Active Source>. * Process <Active Source>. Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -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. * * Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +46 −2 Original line number Original line Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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()); Loading Loading @@ -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); Loading Loading
services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java +9 −11 Original line number Original line Diff line number Diff line Loading @@ -88,26 +88,24 @@ 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(); } } } } } /** /** * Process <Active Source>. * Process <Active Source>. Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -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. * * Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +46 −2 Original line number Original line Diff line number Diff line Loading @@ -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. Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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()); Loading Loading @@ -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); Loading