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

Commit 2af8848d authored by Yan Han's avatar Yan Han
Browse files

Update CEC network with feature support on receiving <Report Features>

Test: atest HdmiCecMessageValidatorTest
atest DeviceFeaturesTest
Bug: 199144863

Change-Id: I49161c8fd5ff2295b8654c8903cc548859d62664
parent 5f812220
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -106,6 +106,19 @@ public class DeviceFeatures {
        return builder.build();
    }

    /**
     * Returns the input that is not {@link #FEATURE_SUPPORT_UNKNOWN}. If neither is equal to
     * {@link #FEATURE_SUPPORT_UNKNOWN}, returns the second input.
     */
    private static @FeatureSupportStatus int updateFeatureSupportStatus(
            @FeatureSupportStatus int oldStatus, @FeatureSupportStatus int newStatus) {
        if (newStatus == FEATURE_SUPPORT_UNKNOWN) {
            return oldStatus;
        } else {
            return newStatus;
        }
    }

    /**
     * Returns the [Device Features] operand corresponding to this instance.
     * {@link #FEATURE_SUPPORT_UNKNOWN} maps to 0, indicating no support.
@@ -354,5 +367,29 @@ public class DeviceFeatures {
            mSetAudioVolumeLevelSupport = setAudioVolumeLevelSupport;
            return this;
        }

        /**
         * Updates all fields with those in a 'new' instance of {@link DeviceFeatures}.
         * All fields are replaced with those in the new instance, except when the field is
         * {@link #FEATURE_SUPPORT_UNKNOWN} in the new instance.
         */
        @NonNull
        public Builder update(DeviceFeatures newDeviceFeatures) {
            mRecordTvScreenSupport = updateFeatureSupportStatus(mRecordTvScreenSupport,
                    newDeviceFeatures.getRecordTvScreenSupport());
            mOsdStringSupport = updateFeatureSupportStatus(mOsdStringSupport,
                    newDeviceFeatures.getSetOsdStringSupport());
            mDeckControlSupport = updateFeatureSupportStatus(mDeckControlSupport,
                    newDeviceFeatures.getDeckControlSupport());
            mSetAudioRateSupport = updateFeatureSupportStatus(mSetAudioRateSupport,
                    newDeviceFeatures.getSetAudioRateSupport());
            mArcTxSupport = updateFeatureSupportStatus(mArcTxSupport,
                    newDeviceFeatures.getArcTxSupport());
            mArcRxSupport = updateFeatureSupportStatus(mArcRxSupport,
                    newDeviceFeatures.getArcRxSupport());
            mSetAudioVolumeLevelSupport = updateFeatureSupportStatus(mSetAudioVolumeLevelSupport,
                    newDeviceFeatures.getSetAudioVolumeLevelSupport());
            return this;
        }
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -734,5 +734,15 @@ public class HdmiDeviceInfo implements Parcelable {
            mAdopterId = adopterId;
            return this;
        }

        /**
         * Updates the value for {@link #getDeviceFeatures()} with a new set of device features.
         * New information overrides the old, except when feature support was unknown.
         */
        @NonNull
        public Builder updateDeviceFeatures(DeviceFeatures deviceFeatures) {
            mDeviceFeatures = mDeviceFeatures.toBuilder().update(deviceFeatures).build();
            return this;
        }
    }
}
+37 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.hardware.hdmi;

import static android.hardware.hdmi.DeviceFeatures.FEATURE_NOT_SUPPORTED;
import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORTED;
import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORT_UNKNOWN;

import static com.google.common.truth.Truth.assertThat;

@@ -74,4 +75,40 @@ public class DeviceFeaturesTest {

        assertThat(info.toOperand()).isEqualTo(new byte[]{(byte) 0b0111_0000});
    }

    @Test
    public void testUpdate() {
        DeviceFeatures oldFeatures = DeviceFeatures.ALL_FEATURES_SUPPORT_UNKNOWN.toBuilder()
                .setRecordTvScreenSupport(FEATURE_SUPPORTED)
                .setSetOsdStringSupport(FEATURE_SUPPORTED)
                .setDeckControlSupport(FEATURE_NOT_SUPPORTED)
                .setSetAudioRateSupport(FEATURE_NOT_SUPPORTED)
                .setArcTxSupport(FEATURE_SUPPORT_UNKNOWN)
                .setArcRxSupport(FEATURE_SUPPORT_UNKNOWN)
                .setSetAudioVolumeLevelSupport(FEATURE_SUPPORT_UNKNOWN)
                .build();

        DeviceFeatures newFeatures = DeviceFeatures.ALL_FEATURES_SUPPORT_UNKNOWN.toBuilder()
                .setRecordTvScreenSupport(FEATURE_NOT_SUPPORTED)
                .setSetOsdStringSupport(FEATURE_SUPPORT_UNKNOWN)
                .setDeckControlSupport(FEATURE_SUPPORTED)
                .setSetAudioRateSupport(FEATURE_SUPPORT_UNKNOWN)
                .setArcTxSupport(FEATURE_SUPPORTED)
                .setArcRxSupport(FEATURE_NOT_SUPPORTED)
                .setSetAudioVolumeLevelSupport(FEATURE_SUPPORT_UNKNOWN)
                .build();

        // Always take the field from newFeatures, unless it's FEATURE_SUPPORT_UNKNOWN
        DeviceFeatures updatedFeatures = DeviceFeatures.ALL_FEATURES_SUPPORT_UNKNOWN.toBuilder()
                .setRecordTvScreenSupport(FEATURE_NOT_SUPPORTED)
                .setSetOsdStringSupport(FEATURE_SUPPORTED)
                .setDeckControlSupport(FEATURE_SUPPORTED)
                .setSetAudioRateSupport(FEATURE_NOT_SUPPORTED)
                .setArcTxSupport(FEATURE_SUPPORTED)
                .setArcRxSupport(FEATURE_NOT_SUPPORTED)
                .setSetAudioVolumeLevelSupport(FEATURE_SUPPORT_UNKNOWN)
                .build();

        assertThat(oldFeatures.toBuilder().update(newFeatures).build()).isEqualTo(updatedFeatures);
    }
}
+14 −6
Original line number Diff line number Diff line
@@ -505,6 +505,12 @@ public class HdmiCecNetwork {
            addCecDevice(newDevice);
        }

        // If a message type has its own class, all valid messages of that type
        // will be represented by an instance of that class.
        if (message instanceof ReportFeaturesMessage) {
            handleReportFeatures((ReportFeaturesMessage) message);
        }

        switch (message.getOpcode()) {
            case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS:
                handleReportPhysicalAddress(message);
@@ -521,18 +527,20 @@ public class HdmiCecNetwork {
            case Constants.MESSAGE_CEC_VERSION:
                handleCecVersion(message);
                break;
            case Constants.MESSAGE_REPORT_FEATURES:
                handleReportFeatures(message);
                break;
        }
    }

    @ServiceThreadOnly
    private void handleReportFeatures(HdmiCecMessage message) {
    private void handleReportFeatures(ReportFeaturesMessage message) {
        assertRunOnServiceThread();

        int version = Byte.toUnsignedInt(message.getParams()[0]);
        updateDeviceCecVersion(message.getSource(), version);
        HdmiDeviceInfo currentDeviceInfo = getCecDeviceInfo(message.getSource());
        HdmiDeviceInfo newDeviceInfo = currentDeviceInfo.toBuilder()
                .setCecVersion(message.getCecVersion())
                .updateDeviceFeatures(message.getDeviceFeatures())
                .build();

        updateCecDevice(newDeviceInfo);
    }

    @ServiceThreadOnly
+27 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.hdmi;


import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORTED;

import static com.google.common.truth.Truth.assertThat;

import android.content.Context;
@@ -547,6 +549,31 @@ public class HdmiCecNetworkTest {
        assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion);
    }

    @Test
    public void cecDevices_tracking_reportFeatures_updatesDeviceFeatures() {
        // Features should be set correctly with the initial <Report Features>
        int logicalAddress = Constants.ADDR_PLAYBACK_1;
        int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0;
        DeviceFeatures deviceFeatures = DeviceFeatures.NO_FEATURES_SUPPORTED;
        mHdmiCecNetwork.handleCecMessage(
                ReportFeaturesMessage.build(logicalAddress,
                        cecVersion, Collections.emptyList(),
                        Constants.RC_PROFILE_SOURCE, Collections.emptyList(), deviceFeatures));

        HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
        assertThat(cecDeviceInfo.getDeviceFeatures()).isEqualTo(deviceFeatures);

        // New information from <Report Features> should override old information
        DeviceFeatures updatedFeatures = DeviceFeatures.NO_FEATURES_SUPPORTED.toBuilder()
                .setSetAudioVolumeLevelSupport(FEATURE_SUPPORTED).build();
        mHdmiCecNetwork.handleCecMessage(
                ReportFeaturesMessage.build(logicalAddress,
                        cecVersion, Collections.emptyList(),
                        Constants.RC_PROFILE_SOURCE, Collections.emptyList(), updatedFeatures));
        cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress);
        assertThat(cecDeviceInfo.getDeviceFeatures()).isEqualTo(updatedFeatures);
    }

    @Test
    public void getSafeCecDevicesLocked_addDevice_sizeOne() {
        mHdmiCecNetwork.addCecDevice(HdmiDeviceInfo.INACTIVE_DEVICE);