From c02f2fb278bacf4ff9ab1eb420908698ad5864fc Mon Sep 17 00:00:00 2001 From: Nathalie Le Clair Date: Wed, 5 Oct 2022 16:15:07 +0200 Subject: [PATCH] Update ARC state based on eARC status updates 1. If eARC connection fails: try to initiate ARC. 2. If the eARC HAL moves to the IDLE state: terminate ARC. This is required by the HDMI 2.0 definition, Section 9.5.4.2.5. Test: atest Bug: 262573690 Change-Id: Iefc324ba054ac97fc0790729453cec18d42571cc --- .../server/hdmi/HdmiControlService.java | 9 ++++ .../server/hdmi/HdmiEarcLocalDeviceTx.java | 2 + .../server/hdmi/HdmiControlServiceTest.java | 42 +++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 36ed5b52039ce..503442e4a5f6f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -4468,6 +4468,7 @@ public class HdmiControlService extends SystemService { @ServiceThreadOnly private void onEnableEarc() { + // This will terminate ARC as well. initializeEarc(INITIATED_BY_ENABLE_EARC); } @@ -4553,4 +4554,12 @@ public class HdmiControlService extends SystemService { return mEarcLocalDevice.mEarcStatus != HDMI_EARC_STATUS_ARC_PENDING; } } + + protected void startArcAction(boolean enabled, IHdmiControlCallback callback) { + if (!isTvDeviceEnabled()) { + invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE); + } else { + tv().startArcAction(enabled, callback); + } + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java index 5caacf6d291a1..bdc30b9f16ad2 100644 --- a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java +++ b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java @@ -87,8 +87,10 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice { mReportCapsHandler.removeCallbacksAndMessages(null); if (status == HDMI_EARC_STATUS_IDLE) { notifyEarcStatusToAudioService(false, new ArrayList<>()); + mService.startArcAction(false, null); } else if (status == HDMI_EARC_STATUS_ARC_PENDING) { notifyEarcStatusToAudioService(false, new ArrayList<>()); + mService.startArcAction(true, null); } else if (status == HDMI_EARC_STATUS_EARC_CONNECTED) { mReportCapsHandler.postDelayed(mReportCapsRunnable, REPORT_CAPS_MAX_DELAY_MS); } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index ac361e1cb9fba..b948fd0a590b9 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -30,9 +30,11 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.assertEquals; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -1293,6 +1295,46 @@ public class HdmiControlServiceTest { assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isFalse(); } + @Test + public void earcStatusBecomesIdle_terminateArc() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE); + verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(false), any()); + } + + @Test + public void earcStatusBecomesEnabled_doNothing() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED); + verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any()); + } + + @Test + public void earcStatusBecomesPending_doNothing() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING); + verify(mHdmiControlServiceSpy, times(0)).startArcAction(anyBoolean(), any()); + } + + @Test + public void earcStatusBecomesNotEnabled_initiateArc() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); + verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any()); + } + protected static class MockPlaybackDevice extends HdmiCecLocalDevicePlayback { private boolean mCanGoToStandby;