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

Commit 03afe48a authored by Amy's avatar Amy Committed by shubang
Browse files

Switch away from ARC input when ARC is terminated.

ag/5056172

This is helpful when TV turns on/off system audio mode but
Active Source does not change. We will always switch away from
ARC input when system audio mode/arc is off

Bug: 115756006
Test: local tested
Change-Id: If38d544384d8ce2fac57de67e7164b5ffb7e19f6
parent 25d5bf6a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@ public class ArcTerminationActionFromAvr extends HdmiCecFeatureAction {
            case Constants.MESSAGE_REPORT_ARC_TERMINATED:
                mState = STATE_ARC_TERMINATED;
                audioSystem().setArcStatus(false);
                if (audioSystem().getLocalActivePort() == Constants.CEC_SWITCH_ARC) {
                    audioSystem().routeToInputFromPortId(audioSystem().getRoutingPort());
                }
                finish();
                return true;
        }
+22 −21
Original line number Diff line number Diff line
@@ -207,6 +207,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
    @ServiceThreadOnly
    protected boolean handleRequestArcInitiate(HdmiCecMessage message) {
        assertRunOnServiceThread();
        removeAction(ArcInitiationActionFromAvr.class);
        if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) {
            mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE);
        } else if (!isDirectConnectToTv()) {
@@ -228,6 +229,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
            HdmiLogger.debug("ARC is not established between TV and AVR device");
            mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE);
        } else {
            removeAction(ArcTerminationActionFromAvr.class);
            addAndStartAction(new ArcTerminationActionFromAvr(this));
        }
        return true;
@@ -446,11 +448,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
            }
        }
        // Init arc whenever System Audio Mode is on
        // Since some TV like LG don't request ARC on with System Audio Mode on request
        if (newSystemAudioMode
                && SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)
                && !isArcEnabled() && isDirectConnectToTv()) {
        // Terminate arc when System Audio Mode is off
        // Since some TVs don't request ARC on with System Audio Mode on request
        if (SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)
                && isDirectConnectToTv()) {
            if (newSystemAudioMode && !isArcEnabled()) {
                removeAction(ArcInitiationActionFromAvr.class);
                addAndStartAction(new ArcInitiationActionFromAvr(this));
            } else if (!newSystemAudioMode && isArcEnabled()) {
                removeAction(ArcTerminationActionFromAvr.class);
                addAndStartAction(new ArcTerminationActionFromAvr(this));
            }
        }
    }

@@ -572,12 +580,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
    @Override
    protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
        int port = getLocalPortFromPhysicalAddress(physicalAddress);
        // Wake up if the new Active Source is the current device or under it
        // or if System Audio Control is enabled.
        if ((isSystemAudioActivated() || port >= 0) && mService.isPowerStandbyOrTransient()) {
            mService.wakeUp();
        }

        if (isSystemAudioActivated() && port < 0) {
            // If system audio mode is on and the new active source is not under the current device,
            // Will switch to ARC input.
@@ -603,11 +605,15 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
            HdmiLogger.debug("Invalid port number for Tv Input switching.");
            return;
        }
        // TODO(amyjojo): handle if switching to the current input
        // Wake up if the current device if ready to route.
        if (mService.isPowerStandbyOrTransient()) {
            mService.wakeUp();
        }
        if (portId == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
            switchToHomeTvInput();
        } else if (portId == Constants.CEC_SWITCH_ARC) {
            switchToTvInput(SystemProperties.get(Constants.PROPERTY_SYSTEM_AUDIO_DEVICE_ARC_PORT));
            setLocalActivePort(portId);
            return;
        } else {
            String uri = mTvInputs.get(portId);
@@ -620,6 +626,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
        }

        setLocalActivePort(portId);
        setRoutingPort(portId);
    }

    // For device to switch to specific TvInput with corresponding URI.
@@ -662,19 +669,13 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {

    // Handle the system audio(ARC) part of the logic on receiving routing change or information.
    private void handleRoutingChangeAndInformationForSystemAudio() {
        if (mService.isPowerStandbyOrTransient()) {
            mService.wakeUp();
        }
        // TODO(b/115637145): handle system aduio without ARC
        routeToInputFromPortId(Constants.CEC_SWITCH_ARC);
    }

    // Handle the routing control part of the logic on receiving routing change or information.
    private void handleRoutingChangeAndInformationForSwitch(HdmiCecMessage message) {
        if (mService.isPowerStandbyOrTransient()) {
            mService.wakeUp();
        }
        if (getLocalActivePort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
        if (getRoutingPort() == Constants.CEC_SWITCH_HOME && mService.isPlaybackDevice()) {
            routeToInputFromPortId(Constants.CEC_SWITCH_HOME);
            mService.setAndBroadcastActiveSourceFromOneDeviceType(
                    message.getSource(), mService.getPhysicalAddress());
@@ -682,7 +683,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
        }

        int routingInformationPath =
                getActivePathOnSwitchFromActivePortId(getLocalActivePort());
                getActivePathOnSwitchFromActivePortId(getRoutingPort());
        // If current device is already the leaf of the whole HDMI system, will do nothing.
        if (routingInformationPath == mService.getPhysicalAddress()) {
            HdmiLogger.debug("Current device can't assign valid physical address"
@@ -693,6 +694,6 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
        // Otherwise will switch to the current active port and broadcast routing information.
        mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingInformation(
                mAddress, routingInformationPath));
        routeToInputFromPortId(getLocalActivePort());
        routeToInputFromPortId(getRoutingPort());
    }
}
+58 −8
Original line number Diff line number Diff line
@@ -45,14 +45,24 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
    protected boolean mIsSwitchDevice = SystemProperties.getBoolean(
            Constants.PROPERTY_HDMI_IS_DEVICE_HDMI_CEC_SWITCH, false);

    // Local active port number used for Routing Control.
    // This records the default active port or the previous valid active port.
    // Routing port number used for Routing Control.
    // This records the default routing port or the previous valid routing port.
    // Default is HOME input.
    // Note that we don't save active path here because for source device,
    // new Active Source physical address might not match the local active path
    // new Active Source physical address might not match the active path
    @GuardedBy("mLock")
    @LocalActivePort
    private int mLocalActivePort = Constants.CEC_SWITCH_HOME;
    private int mRoutingPort = Constants.CEC_SWITCH_HOME;

    // This records the current input of the device.
    // When device is switched to ARC input, mRoutingPort does not record it
    // since it's not an HDMI port used for Routing Control.
    // mLocalActivePort will record whichever input we switch to to keep tracking on
    // the current input status of the device.
    // This can help prevent duplicate switching and provide status information.
    @GuardedBy("mLock")
    @LocalActivePort
    protected int mLocalActivePort = Constants.CEC_SWITCH_HOME;

    protected HdmiCecLocalDeviceSource(HdmiControlService service, int deviceType) {
        super(service, deviceType);
@@ -219,19 +229,59 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        }
    }

    /**
     * Set {@link #mRoutingPort} to a specific {@link LocalActivePort} to record the current active
     * CEC Routing Control related port.
     *
     * @param portId The portId of the new routing port.
     */
    @VisibleForTesting
    protected void setLocalActivePort(@LocalActivePort int portId) {
    protected void setRoutingPort(@LocalActivePort int portId) {
        synchronized (mLock) {
            mLocalActivePort = portId;
            mRoutingPort = portId;
        }
    }

    // To get the local active port to switch to
    // when receivng routing change or information.
    /**
     * Get {@link #mRoutingPort}. This is useful when the device needs to route to the last valid
     * routing port.
     */
    @LocalActivePort
    protected int getRoutingPort() {
        synchronized (mLock) {
            return mRoutingPort;
        }
    }

    /**
     * Get {@link #mLocalActivePort}. This is useful when device needs to know the current active
     * port.
     */
    @LocalActivePort
    protected int getLocalActivePort() {
        synchronized (mLock) {
            return mLocalActivePort;
        }
    }

    /**
     * Set {@link #mLocalActivePort} to a specific {@link LocalActivePort} to record the current
     * active port.
     *
     * <p>It does not have to be a Routing Control related port. For example it can be
     * set to {@link Constants#CEC_SWITCH_ARC} but this port is System Audio related.
     *
     * @param activePort The portId of the new active port.
     */
    protected void setLocalActivePort(@LocalActivePort int activePort) {
        synchronized (mLock) {
            mLocalActivePort = activePort;
        }
    }

    // Check if the device is trying to switch to the same input that is active right now.
    // This can help avoid redundant port switching.
    protected boolean isSwitchingToTheSameInput(@LocalActivePort int activePort) {
        return activePort == getLocalActivePort();
    }
}
+5 −0
Original line number Diff line number Diff line
@@ -88,6 +88,11 @@ final class OneTouchPlayAction extends HdmiCecFeatureAction {
        source.mService.setAndBroadcastActiveSourceFromOneDeviceType(
                mTargetAddress, getSourcePath());
        // Set local active port to HOME when One Touch Play.
        // Active Port and Current Input are handled by the switch functionality device.
        if (source.mService.audioSystem() != null) {
            source = source.mService.audioSystem();
        }
        source.setRoutingPort(Constants.CEC_SWITCH_HOME);
        source.setLocalActivePort(Constants.CEC_SWITCH_HOME);
    }

+2 −2
Original line number Diff line number Diff line
@@ -580,7 +580,7 @@ public class HdmiCecLocalDeviceAudioSystemTest {
        mTestLooper.dispatchAll();
        assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource())
            .isEqualTo(expectedActiveSource);
        assertThat(mHdmiCecLocalDeviceAudioSystem.getLocalActivePort())
        assertThat(mHdmiCecLocalDeviceAudioSystem.getRoutingPort())
            .isEqualTo(expectedLocalActivePort);
        assertThat(mNativeWrapper.getResultMessages()).contains(expectedMessage);
    }
@@ -589,7 +589,7 @@ public class HdmiCecLocalDeviceAudioSystemTest {
    public void handleRoutingInformation_currentActivePortIsHDMI1() {
        HdmiCecMessage message =
                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000);
        mHdmiCecLocalDeviceAudioSystem.setLocalActivePort(Constants.CEC_SWITCH_HDMI1);
        mHdmiCecLocalDeviceAudioSystem.setRoutingPort(Constants.CEC_SWITCH_HDMI1);
        HdmiCecMessage expectedMessage =
                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100);