HDMI: Fix ARC enabling when there is no eARC local device

Bug: 278662425
Test: atest com.android.server.hdmi
Change-Id: Ie72610c92f560fe8448009ac5d1f5952f55acfe1
This commit is contained in:
Paul Colta
2023-05-12 17:19:28 +02:00
committed by Paul Colța
parent 8a192565d0
commit ab0c3de070
3 changed files with 38 additions and 15 deletions

View File

@@ -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<AudioDescriptor> audioDescriptors) {
AudioDeviceAttributes attributes = new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_EARC, "", "",
new ArrayList<AudioProfile>(), audioDescriptors);
getAudioManager().setWiredDeviceConnectionState(attributes, enabled ? 1 : 0);
}
@ServiceThreadOnly
void handleEarcCapabilitiesReported(byte[] rawCapabilities, int portId) {
assertRunOnServiceThread();

View File

@@ -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<AudioDescriptor> audioDescriptors = parseCapabilities(rawCapabilities);
notifyEarcStatusToAudioService(true, audioDescriptors);
mService.notifyEarcStatusToAudioService(true, audioDescriptors);
}
}
}
private void notifyEarcStatusToAudioService(
boolean enabled, List<AudioDescriptor> audioDescriptors) {
AudioDeviceAttributes attributes = new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_HDMI_EARC, "", "",
new ArrayList<AudioProfile>(), 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<>());
}
}
}

View File

@@ -92,6 +92,7 @@ public class HdmiControlServiceTest {
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
private HdmiPortInfo[] mHdmiPortInfo;
private ArrayList<Integer> 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();