diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index cede2738cff07..be9df4aecf43d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -63,10 +63,12 @@ import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; import android.hardware.tv.cec.V1_0.SendMessageResult; import android.media.AudioAttributes; +import android.media.AudioDescriptor; import android.media.AudioDeviceAttributes; import android.media.AudioDeviceInfo; import android.media.AudioDeviceVolumeManager; import android.media.AudioManager; +import android.media.AudioProfile; import android.media.VolumeInfo; import android.media.session.MediaController; import android.media.session.MediaSessionManager; @@ -4727,9 +4729,22 @@ public class HdmiControlService extends SystemService { // reported connection state changes, but even if it did, it won't take effect. if (mEarcLocalDevice != null) { mEarcLocalDevice.handleEarcStateChange(status); + } else if (status == HDMI_EARC_STATUS_ARC_PENDING) { + // If the local device is null we notify the Audio Service that eARC connection + // is disabled. + notifyEarcStatusToAudioService(false, new ArrayList<>()); + startArcAction(true, null); } } + protected void notifyEarcStatusToAudioService( + boolean enabled, List audioDescriptors) { + AudioDeviceAttributes attributes = new AudioDeviceAttributes( + AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_EARC, "", "", + new ArrayList(), audioDescriptors); + getAudioManager().setWiredDeviceConnectionState(attributes, enabled ? 1 : 0); + } + @ServiceThreadOnly void handleEarcCapabilitiesReported(byte[] rawCapabilities, int portId) { assertRunOnServiceThread(); diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java index 9058c984f9588..873d5fc92601b 100644 --- a/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java +++ b/services/core/java/com/android/server/hdmi/HdmiEarcLocalDeviceTx.java @@ -23,8 +23,6 @@ import static com.android.server.hdmi.Constants.HDMI_EARC_STATUS_IDLE; import android.hardware.hdmi.HdmiDeviceInfo; import android.media.AudioDescriptor; -import android.media.AudioDeviceAttributes; -import android.media.AudioDeviceInfo; import android.media.AudioProfile; import android.os.Handler; import android.util.IndentingPrintWriter; @@ -88,10 +86,10 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice { mReportCapsHandler.removeCallbacksAndMessages(null); if (status == HDMI_EARC_STATUS_IDLE) { - notifyEarcStatusToAudioService(false, new ArrayList<>()); + mService.notifyEarcStatusToAudioService(false, new ArrayList<>()); mService.startArcAction(false, null); } else if (status == HDMI_EARC_STATUS_ARC_PENDING) { - notifyEarcStatusToAudioService(false, new ArrayList<>()); + mService.notifyEarcStatusToAudioService(false, new ArrayList<>()); mService.startArcAction(true, null); } else if (status == HDMI_EARC_STATUS_EARC_PENDING && oldEarcStatus == HDMI_EARC_STATUS_ARC_PENDING) { @@ -110,19 +108,11 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice { && mReportCapsHandler.hasCallbacks(mReportCapsRunnable)) { mReportCapsHandler.removeCallbacksAndMessages(null); List audioDescriptors = parseCapabilities(rawCapabilities); - notifyEarcStatusToAudioService(true, audioDescriptors); + mService.notifyEarcStatusToAudioService(true, audioDescriptors); } } } - private void notifyEarcStatusToAudioService( - boolean enabled, List audioDescriptors) { - AudioDeviceAttributes attributes = new AudioDeviceAttributes( - AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_EARC, "", "", - new ArrayList(), audioDescriptors); - mService.getAudioManager().setWiredDeviceConnectionState(attributes, enabled ? 1 : 0); - } - /** * Runnable for waiting for a certain amount of time for the audio system to report its * capabilities after eARC was connected. If the audio system doesn´t report its capabilities in @@ -134,7 +124,7 @@ public class HdmiEarcLocalDeviceTx extends HdmiEarcLocalDevice { public void run() { synchronized (mLock) { if (mEarcStatus == HDMI_EARC_STATUS_EARC_CONNECTED) { - notifyEarcStatusToAudioService(true, new ArrayList<>()); + mService.notifyEarcStatusToAudioService(true, new ArrayList<>()); } } } 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 0e6b412e330de..39930bc1e35aa 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -92,6 +92,7 @@ public class HdmiControlServiceTest { private ArrayList mLocalDevices = new ArrayList<>(); private HdmiPortInfo[] mHdmiPortInfo; private ArrayList mLocalDeviceTypes = new ArrayList<>(); + private static final int PORT_ID_EARC_SUPPORTED = 3; @Before public void setUp() throws Exception { @@ -148,7 +149,7 @@ public class HdmiControlServiceTest { .setEarcSupported(false) .build(); mHdmiPortInfo[2] = - new HdmiPortInfo.Builder(3, HdmiPortInfo.PORT_INPUT, 0x2000) + new HdmiPortInfo.Builder(PORT_ID_EARC_SUPPORTED, HdmiPortInfo.PORT_INPUT, 0x2000) .setCecSupported(true) .setMhlSupported(false) .setArcSupported(true) @@ -1128,6 +1129,23 @@ public class HdmiControlServiceTest { assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNull(); } + @Test + public void disableEarc_noEarcLocalDevice_enableArc() { + mHdmiControlServiceSpy.clearEarcLocalDevice(); + mHdmiControlServiceSpy.addEarcLocalDevice( + new HdmiEarcLocalDeviceTx(mHdmiControlServiceSpy)); + mHdmiControlServiceSpy.setEarcEnabled(HdmiControlManager.EARC_FEATURE_DISABLED); + mTestLooper.dispatchAll(); + assertThat(mHdmiControlServiceSpy.getEarcLocalDevice()).isNull(); + + Mockito.clearInvocations(mHdmiControlServiceSpy); + mHdmiControlServiceSpy.handleEarcStateChange(Constants.HDMI_EARC_STATUS_ARC_PENDING, + PORT_ID_EARC_SUPPORTED); + verify(mHdmiControlServiceSpy, times(1)) + .notifyEarcStatusToAudioService(eq(false), eq(new ArrayList<>())); + verify(mHdmiControlServiceSpy, times(1)).startArcAction(eq(true), any()); + } + @Test public void disableCec_doNotClearEarcLocalDevice() { mHdmiControlServiceSpy.clearEarcLocalDevice();