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

Commit 79b54e92 authored by Amy's avatar Amy Committed by shubang
Browse files

Add routingChange and routingInformation handlers.

ag/4997843

Test: com.android.server.hdmi

Bug: 112476122
Bug: 112476226
Change-Id: I7b01513bd23aeec2e96f48c5e9351ca70840226a
parent 34037424
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.view.KeyEvent;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.Constants.LocalActivePort;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;

@@ -1051,7 +1052,7 @@ abstract class HdmiCecLocalDevice {
     * <p>This check assumes target address is valid.
     * @param targetPhysicalAddress is the physical address of the target device
     * @return
     * <p>If the target device is under the current device, return the port number of current device
     * If the target device is under the current device, return the port number of current device
     * that the target device is connected to.
     *
     * <p>If the target device has the same physical address as the current device, return
@@ -1085,4 +1086,27 @@ abstract class HdmiCecLocalDevice {
        }
        return TARGET_NOT_UNDER_LOCAL_DEVICE;
    }

    /** Calculates the physical address for {@code activePortId}.
     *
     * <p>This method assumes current device physical address is valid.
     * <p>If the current device is already the leaf of the whole CEC system
     * and can't have devices under it, will return its own physical address.
     *
     * @param activePortId is the local active port Id
     * @return the calculated physical address of the port
     */
    protected int getActivePathOnSwitchFromActivePortId(@LocalActivePort int activePortId) {
        int myPhysicalAddress = mService.getPhysicalAddress();
        int finalMask = activePortId << 8;
        int mask;
        for (mask = 0x0F00; mask > 0x000F;  mask >>= 4) {
            if ((myPhysicalAddress & mask) == 0)  {
                break;
            } else {
                finalMask >>= 4;
            }
        }
        return finalMask | myPhysicalAddress;
    }
}
+55 −0
Original line number Diff line number Diff line
@@ -677,4 +677,59 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
                        | Intent.FLAG_ACTIVITY_NO_ANIMATION);
        mService.getContext().startActivity(activityIntent);
    }

    @Override
    protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
        int port = getLocalPortFromPhysicalAddress(physicalAddress);
        // Routing change or information sent from switches under the current device can be ignored.
        if (port > 0) {
            return;
        }
        // When other switches route to some other devices not under the current device,
        // check system audio mode status and do ARC switch if needed.
        if (port < 0 && isSystemAudioActivated()) {
            handleRoutingChangeAndInformationForSystemAudio();
            return;
        }
        // When other switches route to the current device
        // and the current device is also a switch.
        if (port == 0) {
            handleRoutingChangeAndInformationForSwitch(message);
        }
    }

    // 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()) {
            routeToInputFromPortId(Constants.CEC_SWITCH_HOME);
            setAndBroadcastActiveSource(message, mService.getPhysicalAddress());
            return;
        }

        int routingInformationPath =
                getActivePathOnSwitchFromActivePortId(mService.getPhysicalAddress());
        // 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"
                    + "to devices under it any more. "
                    + "It's physical address is " + routingInformationPath);
            return;
        }
        // Otherwise will switch to the current active port and broadcast routing information.
        mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingInformation(
                mAddress, routingInformationPath));
        routeToInputFromPortId(getActivePortId());
    }
}
+36 −0
Original line number Diff line number Diff line
@@ -143,12 +143,48 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        return true;
    }

    @Override
    @ServiceThreadOnly
    protected boolean handleRoutingChange(HdmiCecMessage message) {
        assertRunOnServiceThread();
        int newPath = HdmiUtils.twoBytesToInt(message.getParams(), 2);
        // if the current device is a pure playback device
        if (!mIsSwitchDevice
                && newPath == mService.getPhysicalAddress()
                && mService.isPlaybackDevice()) {
            setAndBroadcastActiveSource(message, newPath);
        }
        handleRoutingChangeAndInformation(newPath, message);
        return true;
    }

    @Override
    @ServiceThreadOnly
    protected boolean handleRoutingInformation(HdmiCecMessage message) {
        assertRunOnServiceThread();
        int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
        // if the current device is a pure playback device
        if (!mIsSwitchDevice
                && physicalAddress == mService.getPhysicalAddress()
                && mService.isPlaybackDevice()) {
            setAndBroadcastActiveSource(message, physicalAddress);
        }
        handleRoutingChangeAndInformation(physicalAddress, message);
        return true;
    }

    // Method to switch Input with the new Active Path.
    // All the devices with Switch functionality should implement this.
    protected void switchInputOnReceivingNewActivePath(int physicalAddress) {
        // do nothing
    }

    // Source device with Switch functionality should implement this method.
    // TODO(): decide which type will handle the routing when multi device type is supported
    protected void handleRoutingChangeAndInformation(int physicalAddress, HdmiCecMessage message) {
        // do nothing
    }

    // Active source claiming needs to be handled in the parent class
    // since we decide who will be the active source when the device supports
    // multiple device types in this method.
+32 −0
Original line number Diff line number Diff line
@@ -571,4 +571,36 @@ public class HdmiCecLocalDeviceAudioSystemTest {
        assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource())
            .isEqualTo(expectedActiveSource);
    }

    @Test
    public void handleRoutingChange_currentActivePortIsHome() {
        HdmiCecMessage message =
                HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, mAvrPhysicalAddress);

        HdmiCecMessage expectedMessage =
                HdmiCecMessageBuilder.buildActiveSource(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress);
        ActiveSource expectedActiveSource = ActiveSource.of(ADDR_AUDIO_SYSTEM, mAvrPhysicalAddress);
        int expectedLocalActivePort = Constants.CEC_SWITCH_HOME;

        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingChange(message)).isTrue();
        mTestLooper.dispatchAll();
        assertThat(mHdmiCecLocalDeviceAudioSystem.getActiveSource())
            .isEqualTo(expectedActiveSource);
        assertThat(mHdmiCecLocalDeviceAudioSystem.getLocalActivePort())
            .isEqualTo(expectedLocalActivePort);
        assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
    }

    @Test
    public void handleRoutingInformation_currentActivePortIsHDMI1() {
        HdmiCecMessage message =
                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000);
        mHdmiCecLocalDeviceAudioSystem.setLocalActivePort(Constants.CEC_SWITCH_HDMI1);
        HdmiCecMessage expectedMessage =
                HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100);

        assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingInformation(message)).isTrue();
        mTestLooper.dispatchAll();
        assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage);
    }
}