Loading services/core/java/com/android/server/hdmi/DeviceSelectActionFromPlayback.java 0 → 100644 +251 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; /** * Handles an action that selects a logical device as a new active source. * * Triggered by {@link HdmiPlaybackClient}, attempts to select the given target device * for a new active source. A >Routing Change< command is issued in order to select * the target device. If that doesn't succeed a >Set Stream Path< command is sent. * It does its best to wake up the target in standby mode, before issuing the device * select command. */ final class DeviceSelectActionFromPlayback extends HdmiCecFeatureAction { private static final String TAG = "DeviceSelectActionFromPlayback"; // Time in milliseconds we wait for the device power status to switch to 'Standby' private static final int TIMEOUT_TRANSIT_TO_STANDBY_MS = 5 * 1000; // Time in milliseconds we wait for the device power status to turn to 'On'. private static final int TIMEOUT_POWER_ON_MS = 5 * 1000; // The number of times we try to wake up the target device before we give up // and just send <Routing Change>. private static final int LOOP_COUNTER_MAX = 2; // State in which we wait for <Report Power Status> to come in response to the command // <Give Device Power Status> we have sent. @VisibleForTesting static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1; // State in which we wait for the device power status to switch to 'Standby'. // We wait till the status becomes 'Standby' before we send <Routing Change> // to wake up the device again. private static final int STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY = 2; // State in which we wait for the device power status to switch to 'on'. We wait // maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>. @VisibleForTesting static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3; // State in which we wait for <Active Source> to come in response to the command // <Routing Change> we have sent. @VisibleForTesting static final int STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE = 4; // State in which we wait for <Active Source> to come in response to the command // <Set Stream Path> we have sent. @VisibleForTesting private static final int STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH = 5; private final HdmiDeviceInfo mTarget; private final HdmiCecMessage mGivePowerStatus; private final boolean mIsCec20; private int mPowerStatusCounter = 0; /** * Constructor. * * @param source {@link HdmiCecLocalDevice} instance * @param target target logical device that will be a new active source * @param callback callback object */ DeviceSelectActionFromPlayback(HdmiCecLocalDevicePlayback source, HdmiDeviceInfo target, IHdmiControlCallback callback) { this(source, target, callback, source.getDeviceInfo().getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0 && target.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0); } @VisibleForTesting DeviceSelectActionFromPlayback(HdmiCecLocalDevicePlayback source, HdmiDeviceInfo target, IHdmiControlCallback callback, boolean isCec20) { super(source, callback); mTarget = target; mGivePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus( getSourceAddress(), getTargetAddress()); mIsCec20 = isCec20; } private int getTargetAddress() { return mTarget.getLogicalAddress(); } private int getTargetPath() { return mTarget.getPhysicalAddress(); } @Override public boolean start() { // This <Routing Change> message wakes up the target device in most cases. sendRoutingChange(); if (!mIsCec20) { queryDevicePowerStatus(); } else { int targetPowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; HdmiDeviceInfo targetDevice = localDevice().mService.getHdmiCecNetwork() .getCecDeviceInfo(getTargetAddress()); if (targetDevice != null) { targetPowerStatus = targetDevice.getDevicePowerStatus(); } if (targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) { queryDevicePowerStatus(); } else if (targetPowerStatus == HdmiControlManager.POWER_STATUS_ON) { mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE; addTimer(mState, HdmiConfig.TIMEOUT_MS); return true; } } mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; addTimer(mState, HdmiConfig.TIMEOUT_MS); return true; } private void queryDevicePowerStatus() { sendCommand( mGivePowerStatus, new HdmiControlService.SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != SendMessageResult.SUCCESS) { finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); return; } } }); } @Override public boolean processCommand(HdmiCecMessage cmd) { if (cmd.getSource() != getTargetAddress()) { return false; } int opcode = cmd.getOpcode(); byte[] params = cmd.getParams(); if (opcode == Constants.MESSAGE_ACTIVE_SOURCE) { // The target device was successfully set as the active source finishWithCallback(HdmiControlManager.RESULT_SUCCESS); return true; } if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS && opcode == Constants.MESSAGE_REPORT_POWER_STATUS) { return handleReportPowerStatus(params[0]); } return false; } private boolean handleReportPowerStatus(int powerStatus) { switch (powerStatus) { case HdmiControlManager.POWER_STATUS_ON: selectDevice(); return true; case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY: if (mPowerStatusCounter < 4) { mState = STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY; addTimer(mState, TIMEOUT_TRANSIT_TO_STANDBY_MS); } else { selectDevice(); } return true; case HdmiControlManager.POWER_STATUS_STANDBY: if (mPowerStatusCounter == 0) { sendRoutingChange(); mState = STATE_WAIT_FOR_DEVICE_POWER_ON; addTimer(mState, TIMEOUT_POWER_ON_MS); } else { selectDevice(); } return true; case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON: if (mPowerStatusCounter < LOOP_COUNTER_MAX) { mState = STATE_WAIT_FOR_DEVICE_POWER_ON; addTimer(mState, TIMEOUT_POWER_ON_MS); } else { selectDevice(); } return true; } return false; } private void selectDevice() { sendRoutingChange(); mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE; addTimer(mState, HdmiConfig.TIMEOUT_MS); } @Override void handleTimerEvent(int timeoutState) { if (mState != timeoutState) { Slog.w(TAG, "Timer in a wrong state. Ignored."); return; } switch (mState) { case STATE_WAIT_FOR_REPORT_POWER_STATUS: selectDevice(); addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_DEVICE_POWER_ON: mPowerStatusCounter++; queryDevicePowerStatus(); mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE: sendSetStreamPath(); mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH; addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH: finishWithCallback(HdmiControlManager.RESULT_TIMEOUT); break; } } private void sendRoutingChange() { sendCommand(HdmiCecMessageBuilder.buildRoutingChange(getSourceAddress(), playback().getActiveSource().physicalAddress, getTargetPath())); } private void sendSetStreamPath() { sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(getSourceAddress(), getTargetPath())); } } services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +14 −0 Original line number Diff line number Diff line Loading @@ -260,6 +260,20 @@ abstract class HdmiCecLocalDevice { return onMessage(message); } @ServiceThreadOnly @VisibleForTesting protected boolean isAlreadyActiveSource(HdmiDeviceInfo targetDevice, int targetAddress, IHdmiControlCallback callback) { ActiveSource active = getActiveSource(); if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON && active.isValid() && targetAddress == active.logicalAddress) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return true; } return false; } @ServiceThreadOnly @Constants.HandleMessageResult protected final int onMessage(HdmiCecMessage message) { Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +33 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,39 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { String.valueOf(addr)); } /** * Performs the action 'device select' or 'one touch play' initiated by a Playback device. * * @param id id of HDMI device to select * @param callback callback object to report the result with */ @ServiceThreadOnly void deviceSelect(int id, IHdmiControlCallback callback) { assertRunOnServiceThread(); synchronized (mLock) { if (id == getDeviceInfo().getId()) { mService.oneTouchPlay(callback); return; } } HdmiDeviceInfo targetDevice = mService.getHdmiCecNetwork().getDeviceInfo(id); if (targetDevice == null) { invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE); return; } int targetAddress = targetDevice.getLogicalAddress(); if (isAlreadyActiveSource(targetDevice, targetAddress, callback)) { return; } if (!mService.isControlEnabled()) { setActiveSource(targetDevice, "HdmiCecLocalDevicePlayback#deviceSelect()"); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } removeAction(DeviceSelectActionFromPlayback.class); addAndStartAction(new DeviceSelectActionFromPlayback(this, targetDevice, callback)); } @Override @ServiceThreadOnly void onHotplug(int portId, boolean connected) { Loading services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +1 −5 Original line number Diff line number Diff line Loading @@ -242,11 +242,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { return; } int targetAddress = targetDevice.getLogicalAddress(); ActiveSource active = getActiveSource(); if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON && active.isValid() && targetAddress == active.logicalAddress) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); if (isAlreadyActiveSource(targetDevice, targetAddress, callback)) { return; } if (targetAddress == Constants.ADDR_INTERNAL) { Loading services/core/java/com/android/server/hdmi/HdmiControlService.java +16 −11 Original line number Diff line number Diff line Loading @@ -1685,7 +1685,8 @@ public class HdmiControlService extends SystemService { return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { HdmiCecLocalDevicePlayback playback = playback(); if (tv == null && playback == null) { if (!mAddressAllocated) { mSelectRequestBuffer.set(SelectRequestBuffer.newDeviceSelect( HdmiControlService.this, deviceId, callback)); Loading @@ -1698,6 +1699,7 @@ public class HdmiControlService extends SystemService { invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE); return; } if (tv != null) { HdmiMhlLocalDeviceStub device = mMhlController.getLocalDeviceById(deviceId); if (device != null) { if (device.getPortId() == tv.getActivePortId()) { Loading @@ -1712,6 +1714,9 @@ public class HdmiControlService extends SystemService { return; } tv.deviceSelect(deviceId, callback); return; } playback.deviceSelect(deviceId, callback); } }); } Loading Loading
services/core/java/com/android/server/hdmi/DeviceSelectActionFromPlayback.java 0 → 100644 +251 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.hdmi; import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiDeviceInfo; import android.hardware.hdmi.HdmiPlaybackClient; import android.hardware.hdmi.IHdmiControlCallback; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; /** * Handles an action that selects a logical device as a new active source. * * Triggered by {@link HdmiPlaybackClient}, attempts to select the given target device * for a new active source. A >Routing Change< command is issued in order to select * the target device. If that doesn't succeed a >Set Stream Path< command is sent. * It does its best to wake up the target in standby mode, before issuing the device * select command. */ final class DeviceSelectActionFromPlayback extends HdmiCecFeatureAction { private static final String TAG = "DeviceSelectActionFromPlayback"; // Time in milliseconds we wait for the device power status to switch to 'Standby' private static final int TIMEOUT_TRANSIT_TO_STANDBY_MS = 5 * 1000; // Time in milliseconds we wait for the device power status to turn to 'On'. private static final int TIMEOUT_POWER_ON_MS = 5 * 1000; // The number of times we try to wake up the target device before we give up // and just send <Routing Change>. private static final int LOOP_COUNTER_MAX = 2; // State in which we wait for <Report Power Status> to come in response to the command // <Give Device Power Status> we have sent. @VisibleForTesting static final int STATE_WAIT_FOR_REPORT_POWER_STATUS = 1; // State in which we wait for the device power status to switch to 'Standby'. // We wait till the status becomes 'Standby' before we send <Routing Change> // to wake up the device again. private static final int STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY = 2; // State in which we wait for the device power status to switch to 'on'. We wait // maximum 100 seconds (20 * 5) before we give up and just send <Set Stream Path>. @VisibleForTesting static final int STATE_WAIT_FOR_DEVICE_POWER_ON = 3; // State in which we wait for <Active Source> to come in response to the command // <Routing Change> we have sent. @VisibleForTesting static final int STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE = 4; // State in which we wait for <Active Source> to come in response to the command // <Set Stream Path> we have sent. @VisibleForTesting private static final int STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH = 5; private final HdmiDeviceInfo mTarget; private final HdmiCecMessage mGivePowerStatus; private final boolean mIsCec20; private int mPowerStatusCounter = 0; /** * Constructor. * * @param source {@link HdmiCecLocalDevice} instance * @param target target logical device that will be a new active source * @param callback callback object */ DeviceSelectActionFromPlayback(HdmiCecLocalDevicePlayback source, HdmiDeviceInfo target, IHdmiControlCallback callback) { this(source, target, callback, source.getDeviceInfo().getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0 && target.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0); } @VisibleForTesting DeviceSelectActionFromPlayback(HdmiCecLocalDevicePlayback source, HdmiDeviceInfo target, IHdmiControlCallback callback, boolean isCec20) { super(source, callback); mTarget = target; mGivePowerStatus = HdmiCecMessageBuilder.buildGiveDevicePowerStatus( getSourceAddress(), getTargetAddress()); mIsCec20 = isCec20; } private int getTargetAddress() { return mTarget.getLogicalAddress(); } private int getTargetPath() { return mTarget.getPhysicalAddress(); } @Override public boolean start() { // This <Routing Change> message wakes up the target device in most cases. sendRoutingChange(); if (!mIsCec20) { queryDevicePowerStatus(); } else { int targetPowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; HdmiDeviceInfo targetDevice = localDevice().mService.getHdmiCecNetwork() .getCecDeviceInfo(getTargetAddress()); if (targetDevice != null) { targetPowerStatus = targetDevice.getDevicePowerStatus(); } if (targetPowerStatus == HdmiControlManager.POWER_STATUS_UNKNOWN) { queryDevicePowerStatus(); } else if (targetPowerStatus == HdmiControlManager.POWER_STATUS_ON) { mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE; addTimer(mState, HdmiConfig.TIMEOUT_MS); return true; } } mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; addTimer(mState, HdmiConfig.TIMEOUT_MS); return true; } private void queryDevicePowerStatus() { sendCommand( mGivePowerStatus, new HdmiControlService.SendMessageCallback() { @Override public void onSendCompleted(int error) { if (error != SendMessageResult.SUCCESS) { finishWithCallback(HdmiControlManager.RESULT_COMMUNICATION_FAILED); return; } } }); } @Override public boolean processCommand(HdmiCecMessage cmd) { if (cmd.getSource() != getTargetAddress()) { return false; } int opcode = cmd.getOpcode(); byte[] params = cmd.getParams(); if (opcode == Constants.MESSAGE_ACTIVE_SOURCE) { // The target device was successfully set as the active source finishWithCallback(HdmiControlManager.RESULT_SUCCESS); return true; } if (mState == STATE_WAIT_FOR_REPORT_POWER_STATUS && opcode == Constants.MESSAGE_REPORT_POWER_STATUS) { return handleReportPowerStatus(params[0]); } return false; } private boolean handleReportPowerStatus(int powerStatus) { switch (powerStatus) { case HdmiControlManager.POWER_STATUS_ON: selectDevice(); return true; case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY: if (mPowerStatusCounter < 4) { mState = STATE_WAIT_FOR_DEVICE_TO_TRANSIT_TO_STANDBY; addTimer(mState, TIMEOUT_TRANSIT_TO_STANDBY_MS); } else { selectDevice(); } return true; case HdmiControlManager.POWER_STATUS_STANDBY: if (mPowerStatusCounter == 0) { sendRoutingChange(); mState = STATE_WAIT_FOR_DEVICE_POWER_ON; addTimer(mState, TIMEOUT_POWER_ON_MS); } else { selectDevice(); } return true; case HdmiControlManager.POWER_STATUS_TRANSIENT_TO_ON: if (mPowerStatusCounter < LOOP_COUNTER_MAX) { mState = STATE_WAIT_FOR_DEVICE_POWER_ON; addTimer(mState, TIMEOUT_POWER_ON_MS); } else { selectDevice(); } return true; } return false; } private void selectDevice() { sendRoutingChange(); mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE; addTimer(mState, HdmiConfig.TIMEOUT_MS); } @Override void handleTimerEvent(int timeoutState) { if (mState != timeoutState) { Slog.w(TAG, "Timer in a wrong state. Ignored."); return; } switch (mState) { case STATE_WAIT_FOR_REPORT_POWER_STATUS: selectDevice(); addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_DEVICE_POWER_ON: mPowerStatusCounter++; queryDevicePowerStatus(); mState = STATE_WAIT_FOR_REPORT_POWER_STATUS; addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_ROUTING_CHANGE: sendSetStreamPath(); mState = STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH; addTimer(mState, HdmiConfig.TIMEOUT_MS); break; case STATE_WAIT_FOR_ACTIVE_SOURCE_MESSAGE_AFTER_SET_STREAM_PATH: finishWithCallback(HdmiControlManager.RESULT_TIMEOUT); break; } } private void sendRoutingChange() { sendCommand(HdmiCecMessageBuilder.buildRoutingChange(getSourceAddress(), playback().getActiveSource().physicalAddress, getTargetPath())); } private void sendSetStreamPath() { sendCommand(HdmiCecMessageBuilder.buildSetStreamPath(getSourceAddress(), getTargetPath())); } }
services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +14 −0 Original line number Diff line number Diff line Loading @@ -260,6 +260,20 @@ abstract class HdmiCecLocalDevice { return onMessage(message); } @ServiceThreadOnly @VisibleForTesting protected boolean isAlreadyActiveSource(HdmiDeviceInfo targetDevice, int targetAddress, IHdmiControlCallback callback) { ActiveSource active = getActiveSource(); if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON && active.isValid() && targetAddress == active.logicalAddress) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); return true; } return false; } @ServiceThreadOnly @Constants.HandleMessageResult protected final int onMessage(HdmiCecMessage message) { Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +33 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,39 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { String.valueOf(addr)); } /** * Performs the action 'device select' or 'one touch play' initiated by a Playback device. * * @param id id of HDMI device to select * @param callback callback object to report the result with */ @ServiceThreadOnly void deviceSelect(int id, IHdmiControlCallback callback) { assertRunOnServiceThread(); synchronized (mLock) { if (id == getDeviceInfo().getId()) { mService.oneTouchPlay(callback); return; } } HdmiDeviceInfo targetDevice = mService.getHdmiCecNetwork().getDeviceInfo(id); if (targetDevice == null) { invokeCallback(callback, HdmiControlManager.RESULT_TARGET_NOT_AVAILABLE); return; } int targetAddress = targetDevice.getLogicalAddress(); if (isAlreadyActiveSource(targetDevice, targetAddress, callback)) { return; } if (!mService.isControlEnabled()) { setActiveSource(targetDevice, "HdmiCecLocalDevicePlayback#deviceSelect()"); invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); return; } removeAction(DeviceSelectActionFromPlayback.class); addAndStartAction(new DeviceSelectActionFromPlayback(this, targetDevice, callback)); } @Override @ServiceThreadOnly void onHotplug(int portId, boolean connected) { Loading
services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +1 −5 Original line number Diff line number Diff line Loading @@ -242,11 +242,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { return; } int targetAddress = targetDevice.getLogicalAddress(); ActiveSource active = getActiveSource(); if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON && active.isValid() && targetAddress == active.logicalAddress) { invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS); if (isAlreadyActiveSource(targetDevice, targetAddress, callback)) { return; } if (targetAddress == Constants.ADDR_INTERNAL) { Loading
services/core/java/com/android/server/hdmi/HdmiControlService.java +16 −11 Original line number Diff line number Diff line Loading @@ -1685,7 +1685,8 @@ public class HdmiControlService extends SystemService { return; } HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { HdmiCecLocalDevicePlayback playback = playback(); if (tv == null && playback == null) { if (!mAddressAllocated) { mSelectRequestBuffer.set(SelectRequestBuffer.newDeviceSelect( HdmiControlService.this, deviceId, callback)); Loading @@ -1698,6 +1699,7 @@ public class HdmiControlService extends SystemService { invokeCallback(callback, HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE); return; } if (tv != null) { HdmiMhlLocalDeviceStub device = mMhlController.getLocalDeviceById(deviceId); if (device != null) { if (device.getPortId() == tv.getActivePortId()) { Loading @@ -1712,6 +1714,9 @@ public class HdmiControlService extends SystemService { return; } tv.deviceSelect(deviceId, callback); return; } playback.deviceSelect(deviceId, callback); } }); } Loading