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

Commit abbbf2ae authored by Yan Han's avatar Yan Han
Browse files

Keep DeviceFeatures updated in local devices.

Local devices currently contain an instance of HdmiDeviceInfo.
With the addition of DeviceFeatures to it, it should be kept updated
whenever a device's set of supported features is computed.

This also necessitates updating the builder method for <Report Features>
messages to use the new DeviceFeatures type.

Note: Updates to a local device's HdmiDeviceInfo are not propagated to
HdmiCecNetwork (except immediately after address allocation)
because the convention for the more dynamic fields of HdmiDeviceInfo
is to only update them in the local device.

Bug: 204854610
Test: atest com.android.server.hdmi
Change-Id: I1ba6f1bdfb36b36f079ec03063d5a6ce6d355e92
parent 23181eb8
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.hdmi;

import android.annotation.CallSuper;
import android.hardware.hdmi.DeviceFeatures;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.IHdmiControlCallback;
@@ -634,7 +635,34 @@ abstract class HdmiCecLocalDevice {

    protected abstract List<Integer> getRcFeatures();

    protected abstract List<Integer> getDeviceFeatures();
    /**
     * Computes the set of supported device features. To update local state with changes in
     * the set of supported device features, use {@link #getDeviceFeatures} instead.
     */
    protected DeviceFeatures computeDeviceFeatures() {
        return DeviceFeatures.NO_FEATURES_SUPPORTED;
    }

    /**
     * Computes the set of supported device features, and updates local state to match.
     */
    private void updateDeviceFeatures() {
        synchronized (mLock) {
            setDeviceInfo(getDeviceInfo().toBuilder()
                    .setDeviceFeatures(computeDeviceFeatures())
                    .build());
        }
    }

    /**
     * Computes and returns the set of supported device features. Updates local state to match.
     */
    protected final DeviceFeatures getDeviceFeatures() {
        updateDeviceFeatures();
        synchronized (mLock) {
            return getDeviceInfo().getDeviceFeatures();
        }
    }

    @Constants.HandleMessageResult
    protected int handleGiveFeatures(HdmiCecMessage message) {
@@ -655,7 +683,7 @@ abstract class HdmiCecLocalDevice {

        int rcProfile = getRcProfile();
        List<Integer> rcFeatures = getRcFeatures();
        List<Integer> deviceFeatures = getDeviceFeatures();
        DeviceFeatures deviceFeatures = getDeviceFeatures();

        mService.sendCecCommand(
                HdmiCecMessageBuilder.buildReportFeatures(
@@ -922,6 +950,7 @@ abstract class HdmiCecLocalDevice {
    final void handleAddressAllocated(int logicalAddress, int reason) {
        assertRunOnServiceThread();
        mPreferredAddress = logicalAddress;
        updateDeviceFeatures();
        if (mService.getCecVersion() >= HdmiControlManager.HDMI_CEC_VERSION_2_0) {
            reportFeatures();
        }
+9 −7
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.server.hdmi;

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

import static com.android.server.hdmi.Constants.ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
import static com.android.server.hdmi.Constants.PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONTROL_ON_POWER_ON;
@@ -22,6 +25,7 @@ import static com.android.server.hdmi.Constants.USE_LAST_STATE_SYSTEM_AUDIO_CONT
import android.annotation.Nullable;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.hardware.hdmi.DeviceFeatures;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
@@ -177,14 +181,12 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
    }

    @Override
    protected List<Integer> getDeviceFeatures() {
        List<Integer> deviceFeatures = new ArrayList<>();

        if (SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) {
            deviceFeatures.add(Constants.DEVICE_FEATURE_SOURCE_SUPPORTS_ARC_RX);
        }
    protected DeviceFeatures computeDeviceFeatures() {
        boolean arcSupport = SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true);

        return deviceFeatures;
        return DeviceFeatures.NO_FEATURES_SUPPORTED.toBuilder()
                .setArcRxSupport(arcSupport ? FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED)
                .build();
    }

    @Override
+0 −7
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.hdmi.Constants.LocalActivePort;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;

import com.google.android.collect.Lists;

import java.util.ArrayList;
import java.util.List;

@@ -358,11 +356,6 @@ abstract class HdmiCecLocalDeviceSource extends HdmiCecLocalDevice {
        return features;
    }

    @Override
    protected List<Integer> getDeviceFeatures() {
        return Lists.newArrayList();
    }

    // Active source claiming needs to be handled in Service
    // since service can decide who will be the active source when the device supports
    // multiple device types in this method.
+9 −8
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.hdmi;

import static android.hardware.hdmi.DeviceFeatures.FEATURE_NOT_SUPPORTED;
import static android.hardware.hdmi.DeviceFeatures.FEATURE_SUPPORTED;
import static android.hardware.hdmi.HdmiControlManager.CLEAR_TIMER_STATUS_CEC_DISABLE;
import static android.hardware.hdmi.HdmiControlManager.CLEAR_TIMER_STATUS_CHECK_RECORDER_CONNECTION;
import static android.hardware.hdmi.HdmiControlManager.CLEAR_TIMER_STATUS_FAIL_TO_CLEAR_SELECTED_SOURCE;
@@ -31,6 +33,7 @@ import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGI
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;

import android.annotation.Nullable;
import android.hardware.hdmi.DeviceFeatures;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiPortInfo;
@@ -1548,9 +1551,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
    }

    @Override
    protected List<Integer> getDeviceFeatures() {
        List<Integer> deviceFeatures = new ArrayList<>();

    protected DeviceFeatures computeDeviceFeatures() {
        boolean hasArcPort = false;
        List<HdmiPortInfo> ports = mService.getPortInfo();
        for (HdmiPortInfo port : ports) {
@@ -1559,11 +1560,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
                break;
            }
        }
        if (hasArcPort) {
            deviceFeatures.add(Constants.DEVICE_FEATURE_SINK_SUPPORTS_ARC_TX);
        }
        deviceFeatures.add(Constants.DEVICE_FEATURE_TV_SUPPORTS_RECORD_TV_SCREEN);
        return deviceFeatures;

        return DeviceFeatures.NO_FEATURES_SUPPORTED.toBuilder()
                .setRecordTvScreenSupport(FEATURE_SUPPORTED)
                .setArcTxSupport(hasArcPort ? FEATURE_SUPPORTED : FEATURE_NOT_SUPPORTED)
                .build();
    }

    @Override
+10 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.hdmi;

import android.hardware.hdmi.DeviceFeatures;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;

@@ -699,7 +700,7 @@ public class HdmiCecMessageBuilder {
            @HdmiControlManager.HdmiCecVersion int cecVersion,
            List<Integer> allDeviceTypes, @Constants.RcProfile int rcProfile,
            List<Integer> rcFeatures,
            List<Integer> deviceFeatures) {
            DeviceFeatures deviceFeatures) {
        byte cecVersionByte = (byte) (cecVersion & 0xFF);
        byte deviceTypes = 0;
        for (Integer deviceType : allDeviceTypes) {
@@ -717,12 +718,15 @@ public class HdmiCecMessageBuilder {
            rcProfileByte |= rcProfileTv;
        }

        byte deviceFeaturesByte = 0;
        for (@Constants.DeviceFeature Integer deviceFeature : deviceFeatures) {
            deviceFeaturesByte |= 1 << deviceFeature;
        }
        byte[] fixedOperands = {cecVersionByte, deviceTypes, rcProfileByte};
        byte[] deviceFeaturesBytes = deviceFeatures.toOperand();

        // Concatenate fixed length operands and [Device Features]
        byte[] params = Arrays.copyOf(fixedOperands,
                fixedOperands.length + deviceFeaturesBytes.length);
        System.arraycopy(deviceFeaturesBytes, 0, params,
                fixedOperands.length, deviceFeaturesBytes.length);

        byte[] params = {cecVersionByte, deviceTypes, rcProfileByte, deviceFeaturesByte};
        return buildCommand(src, Constants.ADDR_BROADCAST, Constants.MESSAGE_REPORT_FEATURES,
                params);
    }
Loading