From 5023f012703fbd0e1b9f104452eaac28b4c5cfa5 Mon Sep 17 00:00:00 2001 From: Nathalie Le Clair Date: Wed, 5 Oct 2022 13:59:48 +0200 Subject: [PATCH] Block new ARC connections during eARC connection If eARC is disabled or not supported, ARC gets connected normally. Test: atest Bug: 262573690 Change-Id: I5c3d172f313c9457e3debe4d35ba6308f221b740 --- .../server/hdmi/HdmiCecLocalDeviceTv.java | 13 + .../server/hdmi/HdmiControlService.java | 10 + .../server/hdmi/HdmiEarcLocalDeviceTx.java | 4 + .../server/hdmi/HdmiCecLocalDeviceTvTest.java | 316 ++++++++++++++++-- .../server/hdmi/HdmiControlServiceTest.java | 40 +++ 5 files changed, 354 insertions(+), 29 deletions(-) diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 96e7b03ec5a06..72ff5b55de5bf 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -912,6 +912,12 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { } return; } + if (enabled && mService.earcBlocksArcConnection()) { + Slog.i(TAG, + "ARC connection blocked because eARC connection is established or being " + + "established."); + return; + } // Terminate opposite action and start action if not exist. if (enabled) { @@ -1010,6 +1016,13 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { protected int handleInitiateArc(HdmiCecMessage message) { assertRunOnServiceThread(); + if (mService.earcBlocksArcConnection()) { + Slog.i(TAG, + "ARC connection blocked because eARC connection is established or being " + + "established."); + return Constants.ABORT_NOT_IN_CORRECT_MODE; + } + if (!canStartArcUpdateAction(message.getSource(), true)) { HdmiDeviceInfo avrDeviceInfo = getAvrDeviceInfo(); if (avrDeviceInfo == null) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 85bd16b2cb2f7..8c4a5cab6a29e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -26,6 +26,7 @@ import static android.hardware.hdmi.HdmiControlManager.SOUNDBAR_MODE_ENABLED; import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static com.android.server.hdmi.Constants.DISABLED; import static com.android.server.hdmi.Constants.ENABLED; +import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_ARC_PENDING; import static com.android.server.hdmi.Constants.OPTION_MHL_ENABLE; import static com.android.server.hdmi.Constants.OPTION_MHL_INPUT_SWITCHING; import static com.android.server.hdmi.Constants.OPTION_MHL_POWER_CHARGE; @@ -4540,4 +4541,13 @@ public class HdmiControlService extends SystemService { mEarcLocalDevice.handleEarcCapabilitiesReported(rawCapabilities); } } + + protected boolean earcBlocksArcConnection() { + if (mEarcLocalDevice == null) { + return false; + } + synchronized (mLock) { + return mEarcLocalDevice.mEarcStatus != HDMI_EARC_STATUS_ARC_PENDING; + } + } } diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java index c7c7702b871a1..5caacf6d291a1 100644 --- a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java +++ b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java @@ -18,6 +18,7 @@ package com.android.server.hdmi; import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_ARC_PENDING; import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_CONNECTED; +import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_EARC_PENDING; import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_IDLE; import android.hardware.hdmi.HdmiDeviceInfo; @@ -69,6 +70,9 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice { HdmiEarcLocalDeviceTx(HdmiControlService service) { super(service, HdmiDeviceInfo.DEVICE_TV); + synchronized (mLock) { + mEarcStatus = HDMI_EARC_STATUS_EARC_PENDING; + } mReportCapsHandler = new Handler(service.getServiceLooper()); mReportCapsRunnable = new ReportCapsRunnable(); } 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 5246107685543..689fcd1ce2288 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java @@ -96,6 +96,7 @@ public class HdmiCecLocalDeviceTvTest { private int mTvPhysicalAddress; private int mTvLogicalAddress; private boolean mWokenUp; + private boolean mEarcBlocksArc; private List mDeviceEventListeners = new ArrayList<>(); private class DeviceEventListener { @@ -155,6 +156,11 @@ public class HdmiCecLocalDeviceTvTest { return false; } + @Override + boolean isPowerStandbyOrTransient() { + return false; + } + @Override AudioManager getAudioManager() { return mAudioManager; @@ -164,6 +170,11 @@ public class HdmiCecLocalDeviceTvTest { void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) { mDeviceEventListeners.add(new DeviceEventListener(device, status)); } + + @Override + protected boolean earcBlocksArcConnection() { + return mEarcBlocksArc; + } }; mHdmiControlService.setIoLooper(mMyLooper); @@ -175,16 +186,18 @@ public class HdmiCecLocalDeviceTvTest { mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService)); HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2]; hdmiPortInfos[0] = - new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x1000, true, false, false); + new HdmiPortInfo(1, HdmiPortInfo.PORT_INPUT, 0x1000, true, false, false, false); hdmiPortInfos[1] = - new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, true); + new HdmiPortInfo(2, HdmiPortInfo.PORT_INPUT, 0x2000, true, false, true, true); mNativeWrapper.setPortInfo(hdmiPortInfos); mHdmiControlService.initService(); mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY); mPowerManager = new FakePowerManagerWrapper(context); mHdmiControlService.setPowerManager(mPowerManager); mTvPhysicalAddress = 0x0000; + mEarcBlocksArc = false; mNativeWrapper.setPhysicalAddress(mTvPhysicalAddress); + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED); mTestLooper.dispatchAll(); mHdmiCecLocalDeviceTv = mHdmiControlService.tv(); mTvLogicalAddress = mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(); @@ -426,9 +439,10 @@ public class HdmiCecLocalDeviceTvTest { public void startArcAction_enable_portDoesNotSupportArc() { // Emulate Audio device on port 0x1000 (does not support ARC) mNativeWrapper.setPortConnectionStatus(1, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mHdmiCecLocalDeviceTv.startArcAction(true); HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation( @@ -445,9 +459,10 @@ public class HdmiCecLocalDeviceTvTest { public void startArcAction_disable_portDoesNotSupportArc() { // Emulate Audio device on port 0x1000 (does not support ARC) mNativeWrapper.setPortConnectionStatus(1, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mHdmiCecLocalDeviceTv.startArcAction(false); HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation( @@ -464,9 +479,10 @@ public class HdmiCecLocalDeviceTvTest { public void startArcAction_enable_portSupportsArc() { // Emulate Audio device on port 0x2000 (supports ARC) mNativeWrapper.setPortConnectionStatus(2, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mTestLooper.dispatchAll(); mHdmiCecLocalDeviceTv.startArcAction(true); @@ -485,9 +501,10 @@ public class HdmiCecLocalDeviceTvTest { public void startArcAction_disable_portSupportsArc() { // Emulate Audio device on port 0x2000 (supports ARC) mNativeWrapper.setPortConnectionStatus(2, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mTestLooper.dispatchAll(); mHdmiCecLocalDeviceTv.startArcAction(false); @@ -522,9 +539,10 @@ public class HdmiCecLocalDeviceTvTest { public void handleInitiateArc_portDoesNotSupportArc() { // Emulate Audio device on port 0x1000 (does not support ARC) mNativeWrapper.setPortConnectionStatus(1, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc( ADDR_AUDIO_SYSTEM, @@ -544,9 +562,10 @@ public class HdmiCecLocalDeviceTvTest { public void handleInitiateArc_portSupportsArc() { // Emulate Audio device on port 0x2000 (supports ARC) mNativeWrapper.setPortConnectionStatus(2, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mTestLooper.dispatchAll(); HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc( @@ -574,6 +593,66 @@ public class HdmiCecLocalDeviceTvTest { assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); } + @Test + public void handleTerminateArc_noAudioDevice() { + HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(terminateArc); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated); + } + + @Test + public void handleTerminateArc_portDoesNotSupportArc() { + // Emulate Audio device on port 0x1000 (does not support ARC) + mNativeWrapper.setPortConnectionStatus(1, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + + HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(terminateArc); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated); + } + + @Test + public void handleTerminateArc_portSupportsArc() { + // Emulate Audio device on port 0x2000 (supports ARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(terminateArc); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated); + } + @Test public void supportsRecordTvScreen() { HdmiCecMessage recordTvScreen = HdmiCecMessage.build(ADDR_RECORDER_1, mTvLogicalAddress, @@ -595,9 +674,10 @@ public class HdmiCecLocalDeviceTvTest { HdmiControlManager.SYSTEM_AUDIO_CONTROL_ENABLED); // Emulate Audio device on port 0x1000 (does not support ARC) mNativeWrapper.setPortConnectionStatus(1, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x1000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mTestLooper.dispatchAll(); HdmiCecFeatureAction systemAudioAutoInitiationAction = @@ -636,9 +716,9 @@ public class HdmiCecLocalDeviceTvTest { public void hotplugDetectionAction_discoversDeviceAfterMessageReceived() { // Playback 1 sends a message before ACKing a poll mNativeWrapper.setPollAddressResponse(ADDR_PLAYBACK_1, SendMessageResult.NACK); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildActiveSource( + HdmiCecMessage activeSource = HdmiCecMessageBuilder.buildActiveSource( ADDR_PLAYBACK_1, ADDR_TV); - mNativeWrapper.onCecMessage(hdmiCecMessage); + mNativeWrapper.onCecMessage(activeSource); mTestLooper.dispatchAll(); // Playback 1 begins ACKing polls, allowing detection by HotplugDetectionAction @@ -853,11 +933,11 @@ public class HdmiCecLocalDeviceTvTest { @Test public void tvSendRequestArcTerminationOnSleep() { // Emulate Audio device on port 0x2000 (supports ARC) - mNativeWrapper.setPortConnectionStatus(2, true); - HdmiCecMessage hdmiCecMessage = HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( - ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); - mNativeWrapper.onCecMessage(hdmiCecMessage); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); mTestLooper.dispatchAll(); mHdmiCecLocalDeviceTv.startArcAction(true); @@ -898,4 +978,182 @@ public class HdmiCecLocalDeviceTvTest { assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination); } + @Test + public void startArcAction_enable_earcBlocksArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = true; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + mHdmiCecLocalDeviceTv.startArcAction(true); + mTestLooper.dispatchAll(); + HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcInitiation); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcTermination); + } + + @Test + public void startArcAction_enable_earcDoesNotBlockArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = false; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + mHdmiCecLocalDeviceTv.startArcAction(true); + mTestLooper.dispatchAll(); + HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).contains(requestArcInitiation); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcTermination); + } + + @Test + public void startArcAction_disable_earcBlocksArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = true; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + mHdmiCecLocalDeviceTv.startArcAction(false); + mTestLooper.dispatchAll(); + HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildRequestArcInitiation( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(requestArcInitiation); + assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination); + } + + @Test + public void handleInitiateArc_earcBlocksArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = true; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(requestArcInitiation); + mTestLooper.dispatchAll(); + + HdmiCecMessage featureAbortMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand( + ADDR_TV, + ADDR_AUDIO_SYSTEM, + Constants.MESSAGE_INITIATE_ARC, + Constants.ABORT_NOT_IN_CORRECT_MODE); + assertThat(mNativeWrapper.getResultMessages()).contains(featureAbortMessage); + } + + @Test + public void handleInitiateArc_earcDoesNotBlockArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = false; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + HdmiCecMessage requestArcInitiation = HdmiCecMessageBuilder.buildInitiateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(requestArcInitiation); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + // should only be sent after SAD querying is done + assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated); + + // Finish querying SADs + assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); + mNativeWrapper.clearResultMessages(); + mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); + mTestLooper.dispatchAll(); + assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY); + mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS); + mTestLooper.dispatchAll(); + + assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated); + } + + @Test + public void handleTerminateArc_earcBlocksArc() { + mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED); + mTestLooper.dispatchAll(); + + mEarcBlocksArc = true; + + // Emulate Audio device on port 0x2000 (supports ARC and eARC) + mNativeWrapper.setPortConnectionStatus(2, true); + HdmiCecMessage reportPhysicalAddress = + HdmiCecMessageBuilder.buildReportPhysicalAddressCommand( + ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM); + mNativeWrapper.onCecMessage(reportPhysicalAddress); + mTestLooper.dispatchAll(); + + HdmiCecMessage terminateArc = HdmiCecMessageBuilder.buildTerminateArc( + ADDR_AUDIO_SYSTEM, + ADDR_TV); + + mNativeWrapper.onCecMessage(terminateArc); + mTestLooper.dispatchAll(); + + HdmiCecMessage reportArcTerminated = HdmiCecMessageBuilder.buildReportArcTerminated( + ADDR_TV, + ADDR_AUDIO_SYSTEM); + assertThat(mNativeWrapper.getResultMessages()).contains(reportArcTerminated); + } } 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 2b555a07a50fd..ac361e1cb9fba 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -1253,6 +1253,46 @@ public class HdmiControlServiceTest { verify(mHdmiControlServiceSpy, times(0)).setEarcEnabledInHal(true); } + @Test + public void earcIdle_blocksArcConnection() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_IDLE); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); + } + + @Test + public void earcPending_blocksArcConnection() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_PENDING); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); + } + + @Test + public void earcEnabled_blocksArcConnection() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isTrue(); + } + + @Test + public void arcPending_doesNotBlockArcConnection() { + mHdmiControlServiceSpy.mEarcSupported = true; + mHdmiControlServiceSpy.clearEarcLocalDevice(); + HdmiEarcLocalDeviceTx localDeviceTx = new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy); + localDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING); + mHdmiControlServiceSpy.addEarcLocalDevice(localDeviceTx); + assertThat(mHdmiControlServiceSpy.earcBlocksArcConnection()).isFalse(); + } + protected static class MockPlaybackDevice extends HdmiCecLocalDevicePlayback { private boolean mCanGoToStandby;