diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 754fa25191b07..77de187e57cae 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -422,6 +422,9 @@ public class HdmiControlService extends SystemService { // Set to true if the logical address allocation is completed. private boolean mAddressAllocated = false; + // Whether a CEC-enabled sink is connected to the playback device + private boolean mIsCecAvailable = false; + // Object that handles logging statsd atoms. // Use getAtomWriter() instead of accessing directly, to allow dependency injection for testing. private HdmiCecAtomWriter mAtomWriter = new HdmiCecAtomWriter(); @@ -2229,6 +2232,7 @@ public class HdmiControlService extends SystemService { pw.println("mProhibitMode: " + mProhibitMode); pw.println("mPowerStatus: " + mPowerStatusController.getPowerStatus()); + pw.println("mIsCecAvailable: " + mIsCecAvailable); pw.println("mCecVersion: " + mCecVersion); // System settings @@ -2450,7 +2454,7 @@ public class HdmiControlService extends SystemService { if (hdmiCecEnabled != HdmiControlManager.HDMI_CEC_CONTROL_ENABLED) { return false; } - return true; + return mIsCecAvailable; } @ServiceThreadOnly @@ -2835,24 +2839,24 @@ public class HdmiControlService extends SystemService { private void invokeHdmiControlStatusChangeListenerLocked( Collection listeners, @HdmiControlManager.HdmiCecControl int isEnabled) { - if (listeners.isEmpty()) { - return; - } if (isEnabled == HdmiControlManager.HDMI_CEC_CONTROL_ENABLED) { queryDisplayStatus(new IHdmiControlCallback.Stub() { public void onComplete(int status) { - boolean isAvailable = true; if (status == HdmiControlManager.POWER_STATUS_UNKNOWN || status == HdmiControlManager.RESULT_EXCEPTION || status == HdmiControlManager.RESULT_SOURCE_NOT_AVAILABLE) { - isAvailable = false; + mIsCecAvailable = false; + } else { + mIsCecAvailable = true; } - invokeHdmiControlStatusChangeListenerLocked(listeners, isEnabled, isAvailable); } }); - return; + } else { + mIsCecAvailable = false; + } + if (!listeners.isEmpty()) { + invokeHdmiControlStatusChangeListenerLocked(listeners, isEnabled, mIsCecAvailable); } - invokeHdmiControlStatusChangeListenerLocked(listeners, isEnabled, false); } private void invokeHdmiControlStatusChangeListenerLocked( diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java index ef7b274eeb830..011b8f899753e 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java @@ -138,6 +138,7 @@ public class DevicePowerStatusActionTest { mDevicePowerStatusAction = DevicePowerStatusAction.create(mPlaybackDevice, ADDR_TV, mCallbackMock); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); } @Test diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 80da6961cf16c..a29a76b438dfd 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -60,6 +60,7 @@ import java.util.concurrent.TimeUnit; @RunWith(JUnit4.class) /** Tests for {@link HdmiCecLocalDevicePlayback} class. */ public class HdmiCecLocalDevicePlaybackTest { + private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1; private static final int PORT_1 = 1; private static final HdmiDeviceInfo INFO_TV = new HdmiDeviceInfo( @@ -1045,6 +1046,10 @@ public class HdmiCecLocalDevicePlaybackTest { assertThat(mHdmiCecLocalDevicePlayback.isActiveSource()).isTrue(); // 4. DUT turned off. mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); + // TODO(b/184939731): remove waiting times once pending actions no longer block + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); HdmiCecMessage standbyMessageBroadcast = HdmiCecMessageBuilder.buildStandby( mHdmiCecLocalDevicePlayback.mAddress, ADDR_BROADCAST); @@ -1502,6 +1507,7 @@ public class HdmiCecLocalDevicePlaybackTest { @Test public void queryDisplayStatus() { + mTestLooper.moveTimeForward(TIMEOUT_MS); mHdmiControlService.queryDisplayStatus(new IHdmiControlCallback.Stub() { @Override public void onComplete(int result) { @@ -1618,6 +1624,12 @@ public class HdmiCecLocalDevicePlaybackTest { @Test public void shouldHandleTvPowerKey_CecDisabled() { + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + HdmiCecMessage reportPowerStatusMessage = HdmiCecMessageBuilder.buildReportPowerStatus( + Constants.ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON); + mNativeWrapper.onCecMessage(reportPowerStatusMessage); + mTestLooper.dispatchAll(); + mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue( HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, HdmiControlManager.HDMI_CEC_CONTROL_DISABLED); @@ -1626,14 +1638,35 @@ public class HdmiCecLocalDevicePlaybackTest { @Test public void shouldHandleTvPowerKey_PowerControlModeNone() { + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + HdmiCecMessage reportPowerStatusMessage = HdmiCecMessageBuilder.buildReportPowerStatus( + Constants.ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON); + mNativeWrapper.onCecMessage(reportPowerStatusMessage); + mTestLooper.dispatchAll(); + mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue( HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE, HdmiControlManager.POWER_CONTROL_MODE_NONE); assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse(); } + @Test + public void shouldHandleTvPowerKey_CecNotAvailable() { + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + // TV doesn't report its power status + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse(); + } + @Test public void shouldHandleTvPowerKey_CecEnabled_PowerControlModeTv() { + mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); + HdmiCecMessage reportPowerStatusMessage = HdmiCecMessageBuilder.buildReportPowerStatus( + Constants.ADDR_TV, mPlaybackLogicalAddress, HdmiControlManager.POWER_STATUS_ON); + mNativeWrapper.onCecMessage(reportPowerStatusMessage); + mTestLooper.dispatchAll(); + mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue( HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED, HdmiControlManager.HDMI_CEC_CONTROL_ENABLED); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java index 950b8a2540076..c7a508a9d6264 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -61,6 +61,7 @@ import java.util.ArrayList; @RunWith(JUnit4.class) /** Tests for {@link HdmiCecLocalDeviceTv} class. */ public class HdmiCecLocalDeviceTvTest { + private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1; private HdmiControlService mHdmiControlService; private HdmiCecController mHdmiCecController; @@ -294,6 +295,10 @@ public class HdmiCecLocalDeviceTvTest { HdmiControlManager.TV_SEND_STANDBY_ON_SLEEP_ENABLED); mTestLooper.dispatchAll(); mHdmiControlService.onStandby(HdmiControlService.STANDBY_SCREEN_OFF); + // TODO(184939731): remove waiting times once pending actions no longer block + mTestLooper.moveTimeForward(TIMEOUT_MS); + mTestLooper.dispatchAll(); + mTestLooper.moveTimeForward(TIMEOUT_MS); mTestLooper.dispatchAll(); HdmiCecMessage standby = HdmiCecMessageBuilder.buildStandby(ADDR_TV, ADDR_BROADCAST); assertThat(mNativeWrapper.getResultMessages()).contains(standby); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java index d74bff2837cec..48931739d9cf5 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/OneTouchPlayActionTest.java @@ -142,6 +142,7 @@ public class OneTouchPlayActionTest { mPhysicalAddress = 0x2000; mNativeWrapper.setPhysicalAddress(mPhysicalAddress); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); } private OneTouchPlayAction createOneTouchPlayAction(HdmiCecLocalDevicePlayback device, @@ -161,6 +162,7 @@ public class OneTouchPlayActionTest { mLocalDevices.add(playbackDevice); mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -203,6 +205,7 @@ public class OneTouchPlayActionTest { mLocalDevices.add(playbackDevice); mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -245,6 +248,7 @@ public class OneTouchPlayActionTest { mLocalDevices.add(playbackDevice); mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -297,6 +301,7 @@ public class OneTouchPlayActionTest { mLocalDevices.add(playbackDevice); mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -342,6 +347,7 @@ public class OneTouchPlayActionTest { mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, HdmiControlManager.POWER_STATUS_ON); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -376,6 +382,7 @@ public class OneTouchPlayActionTest { mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, HdmiControlManager.POWER_STATUS_UNKNOWN); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback(); @@ -420,6 +427,7 @@ public class OneTouchPlayActionTest { mHdmiControlService.getHdmiCecNetwork().updateDevicePowerStatus(ADDR_TV, HdmiControlManager.POWER_STATUS_STANDBY); mTestLooper.dispatchAll(); + mNativeWrapper.clearResultMessages(); TestActionTimer actionTimer = new TestActionTimer(); TestCallback callback = new TestCallback();