Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab0c3de0 authored by Paul Colta's avatar Paul Colta Committed by Paul Colța
Browse files

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

Bug: 278662425
Test: atest com.android.server.hdmi
Change-Id: Ie72610c92f560fe8448009ac5d1f5952f55acfe1
parent 8a192565
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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();
+4 −14
Original line number Diff line number Diff line
@@ -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<>());
                }
            }
        }
+19 −1
Original line number Diff line number Diff line
@@ -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();