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

Commit 5f812220 authored by Yan Han's avatar Yan Han
Browse files

Create class for building and parsing <Report Features>

The new class handles validation (instead of HdmiCecMessageValidator)
and construction (instead of HdmiCecMessageBuilder). It also
parses and exposes some of the parameters.

Bug: 207359637
Bug: 204854610
Test: atest ReportFeaturesMessageTest
Change-Id: I1c862e86e074754f80faaa27d1bda929be02107f
parent f430140f
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -685,9 +685,15 @@ abstract class HdmiCecLocalDevice {
        List<Integer> rcFeatures = getRcFeatures();
        DeviceFeatures deviceFeatures = getDeviceFeatures();


        int logicalAddress;
        synchronized (mLock) {
            logicalAddress = mDeviceInfo.getLogicalAddress();
        }

        mService.sendCecCommand(
                HdmiCecMessageBuilder.buildReportFeatures(
                        mDeviceInfo.getLogicalAddress(),
                ReportFeaturesMessage.build(
                        logicalAddress,
                        mService.getCecVersion(),
                        localDeviceTypes,
                        rcProfile,
+6 −1
Original line number Diff line number Diff line
@@ -74,7 +74,12 @@ public class HdmiCecMessage {
     * instance of that class that exposes parsed parameters.
     */
    static HdmiCecMessage build(int source, int destination, int opcode, byte[] params) {
        return new HdmiCecMessage(source, destination, opcode, params);
        switch (opcode & 0xFF) {
            case Constants.MESSAGE_REPORT_FEATURES:
                return ReportFeaturesMessage.build(source, destination, params);
            default:
                return new HdmiCecMessage(source, destination, opcode & 0xFF, params);
        }
    }

    static HdmiCecMessage build(int source, int destination, int opcode) {
+0 −61
Original line number Diff line number Diff line
@@ -16,15 +16,9 @@

package com.android.server.hdmi;

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

import com.android.server.hdmi.Constants.AudioCodec;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.List;

/**
 * A helper class to build {@link HdmiCecMessage} from various cec commands.
@@ -689,41 +683,6 @@ public class HdmiCecMessageBuilder {
        return HdmiCecMessage.build(src, dest, Constants.MESSAGE_GIVE_FEATURES);
    }

    static HdmiCecMessage buildReportFeatures(int src,
            @HdmiControlManager.HdmiCecVersion int cecVersion,
            List<Integer> allDeviceTypes, @Constants.RcProfile int rcProfile,
            List<Integer> rcFeatures,
            DeviceFeatures deviceFeatures) {
        byte cecVersionByte = (byte) (cecVersion & 0xFF);
        byte deviceTypes = 0;
        for (Integer deviceType : allDeviceTypes) {
            deviceTypes |= 1 << hdmiDeviceInfoDeviceTypeToShiftValue(deviceType);
        }

        byte rcProfileByte = 0;
        rcProfileByte |= rcProfile << 6;
        if (rcProfile == Constants.RC_PROFILE_SOURCE) {
            for (@Constants.RcProfileSource Integer rcFeature : rcFeatures) {
                rcProfileByte |= 1 << rcFeature;
            }
        } else {
            @Constants.RcProfileTv byte rcProfileTv = (byte) (rcFeatures.get(0) & 0xFFFF);
            rcProfileByte |= rcProfileTv;
        }

        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);

        return HdmiCecMessage.build(
                src, Constants.ADDR_BROADCAST, Constants.MESSAGE_REPORT_FEATURES, params);
    }

    /***** Please ADD new buildXXX() methods above. ******/

    /**
@@ -749,24 +708,4 @@ public class HdmiCecMessageBuilder {
                (byte) (physicalAddress & 0xFF)
        };
    }

    @Constants.DeviceType
    private static int hdmiDeviceInfoDeviceTypeToShiftValue(int deviceType) {
        switch (deviceType) {
            case HdmiDeviceInfo.DEVICE_TV:
                return Constants.ALL_DEVICE_TYPES_TV;
            case HdmiDeviceInfo.DEVICE_RECORDER:
                return Constants.ALL_DEVICE_TYPES_RECORDER;
            case HdmiDeviceInfo.DEVICE_TUNER:
                return Constants.ALL_DEVICE_TYPES_TUNER;
            case HdmiDeviceInfo.DEVICE_PLAYBACK:
                return Constants.ALL_DEVICE_TYPES_PLAYBACK;
            case HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM:
                return Constants.ALL_DEVICE_TYPES_AUDIO_SYSTEM;
            case HdmiDeviceInfo.DEVICE_PURE_CEC_SWITCH:
                return Constants.ALL_DEVICE_TYPES_SWITCH;
            default:
                throw new IllegalArgumentException("Unhandled device type: " + deviceType);
        }
    }
}
+0 −2
Original line number Diff line number Diff line
@@ -245,8 +245,6 @@ public class HdmiCecMessageValidator {
        // Messages for Feature Discovery.
        addValidationInfo(Constants.MESSAGE_GIVE_FEATURES, noneValidator,
                DEST_DIRECT | SRC_UNREGISTERED);
        addValidationInfo(Constants.MESSAGE_REPORT_FEATURES, new VariableLengthValidator(4, 14),
                DEST_BROADCAST);

        // Messages for Dynamic Auto Lipsync
        addValidationInfo(Constants.MESSAGE_REQUEST_CURRENT_LATENCY, physicalAddressValidator,
+21 −0
Original line number Diff line number Diff line
@@ -556,6 +556,27 @@ final class HdmiUtils {
        return HdmiCecMessage.build(src, dest, opcode, params);
    }

    /**
     * Some operands in the CEC spec consist of a variable number of bytes, where each byte except
     * the last one has bit 7 set to 1.
     * Given the index of a byte in such an operand, this method returns the index of the last byte
     * in the operand, or -1 if the input is invalid (e.g. operand not terminated properly).
     * @param params Byte array representing a CEC message's parameters
     * @param offset Index of a byte in the operand to find the end of
     */
    public static int getEndOfSequence(byte[] params, int offset) {
        if (offset < 0) {
            return -1;
        }
        while (offset < params.length && ((params[offset] >> 7) & 1) == 1) {
            offset++;
        }
        if (offset >= params.length) {
            return -1;
        }
        return offset;
    }

    public static class ShortAudioDescriptorXmlParser {
        // We don't use namespaces
        private static final String NS = null;
Loading