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

Commit 0b6a6cea authored by Amy Zhang's avatar Amy Zhang Committed by Android (Google) Code Review
Browse files

Merge "resolve merge conflicts of e4ed430a to master"

parents 782672aa 860ccd3c
Loading
Loading
Loading
Loading
+177 −13
Original line number Diff line number Diff line
@@ -148,9 +148,25 @@ public class HdmiCecMessageValidator {
        addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE,
                new AsciiValidator(3), DEST_BROADCAST);

        // TODO: Handle messages for the Deck Control.
        ParameterValidator statusRequestValidator = new OneByteRangeValidator(0x01, 0x03);
        addValidationInfo(
                Constants.MESSAGE_DECK_CONTROL, new OneByteRangeValidator(0x01, 0x04), DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_DECK_STATUS, new OneByteRangeValidator(0x11, 0x1F), DEST_DIRECT);
        addValidationInfo(Constants.MESSAGE_GIVE_DECK_STATUS, statusRequestValidator, DEST_DIRECT);
        addValidationInfo(Constants.MESSAGE_PLAY, new PlayModeValidator(), DEST_DIRECT);

        // TODO: Handle messages for the Tuner Control.
        addValidationInfo(
                Constants.MESSAGE_GIVE_TUNER_DEVICE_STATUS, statusRequestValidator, DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_SELECT_ANALOG_SERVICE,
                new SelectAnalogueServiceValidator(),
                DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_SELECT_DIGITAL_SERVICE,
                new SelectDigitalServiceValidator(),
                DEST_DIRECT);

        // Messages for the Vendor Specific Commands.
        VariableLengthValidator maxLengthValidator = new VariableLengthValidator(0, 14);
@@ -176,9 +192,10 @@ public class HdmiCecMessageValidator {
                Constants.MESSAGE_MENU_STATUS, new OneByteRangeValidator(0x00, 0x01), DEST_DIRECT);

        // Messages for the Remote Control Passthrough.
        // TODO: Parse the first parameter and determine if it can have the next parameter.
        addValidationInfo(Constants.MESSAGE_USER_CONTROL_PRESSED,
                new VariableLengthValidator(1, 2), DEST_DIRECT);
        addValidationInfo(
                Constants.MESSAGE_USER_CONTROL_PRESSED,
                new UserControlPressedValidator(),
                DEST_DIRECT);

        // Messages for the Power Status.
        addValidationInfo(
@@ -525,6 +542,28 @@ public class HdmiCecMessageValidator {
        return (isAribDbs(value) || isAtscDbs(value) || isDvbDbs(value));
    }

    /**
     * Check if the given value is a valid Channel Identifier. A valid value is one which falls
     * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
     * 17)
     *
     * @param params Channel Identifier parameters
     * @param offset start offset of Channel Identifier
     * @return true if the Channel Identifier is valid
     */
    private boolean isValidChannelIdentifier(byte[] params, int offset) {
        // First 6 bits contain Channel Number Format
        int channelNumberFormat = params[offset] & 0xFC;
        if (channelNumberFormat == 0x04) {
            // Validate it contains 1-part Channel Number data (16 bits)
            return params.length - offset >= 3;
        } else if (channelNumberFormat == 0x08) {
            // Validate it contains Major Channel Number and Minor Channel Number (26 bits)
            return params.length - offset >= 4;
        }
        return false;
    }

    /**
     * Check if the given value is a valid Digital Service Identification. A valid value is one
     * which falls within the range description defined in CEC 1.4 Specification : Operand
@@ -555,15 +594,7 @@ public class HdmiCecMessageValidator {
        } else if (serviceIdentificationMethod == 0x80) {
            // Services identified by Channel
            if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) {
                // First 6 bits contain Channel Number Format
                int channelNumberFormat = params[offset] & 0xFC;
                if (channelNumberFormat == 0x04) {
                    // Validate it contains 1-part Channel Number data (16 bits)
                    return params.length - offset >= 3;
                } else if (channelNumberFormat == 0x08) {
                    // Validate it contains Major Channel Number and Minor Channel Number (26 bits)
                    return params.length - offset >= 4;
                }
                return isValidChannelIdentifier(params, offset);
            }
        }
        return false;
@@ -643,6 +674,65 @@ public class HdmiCecMessageValidator {
        return false;
    }

    /**
     * Check if the given value is a valid Play mode. A valid value is one which falls within the
     * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
     *
     * @param value Play mode
     * @return true if the Play mode is valid
     */
    private boolean isValidPlayMode(int value) {
        return (isWithinRange(value, 0x05, 0x07)
                || isWithinRange(value, 0x09, 0x0B)
                || isWithinRange(value, 0x15, 0x17)
                || isWithinRange(value, 0x19, 0x1B)
                || isWithinRange(value, 0x24, 0x25)
                || (value == 0x20));
    }

    /**
     * Check if the given value is a valid UI Broadcast type. A valid value is one which falls
     * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
     * 17)
     *
     * @param value UI Broadcast type
     * @return true if the UI Broadcast type is valid
     */
    private boolean isValidUiBroadcastType(int value) {
        return ((value == 0x00)
                || (value == 0x01)
                || (value == 0x10)
                || (value == 0x20)
                || (value == 0x30)
                || (value == 0x40)
                || (value == 0x50)
                || (value == 0x60)
                || (value == 0x70)
                || (value == 0x80)
                || (value == 0x90)
                || (value == 0x91)
                || (value == 0xA0));
    }

    /**
     * Check if the given value is a valid UI Sound Presenation Control. A valid value is one which
     * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions
     * (Section 17)
     *
     * @param value UI Sound Presenation Control
     * @return true if the UI Sound Presenation Control is valid
     */
    private boolean isValidUiSoundPresenationControl(int value) {
        value = value & 0xFF;
        return ((value == 0x20)
                || (value == 0x30)
                || (value == 0x80)
                || (value == 0x90)
                || (value == 0xA0)
                || (isWithinRange(value, 0xB1, 0xB3))
                || (isWithinRange(value, 0xC1, 0xC3)));
    }

    private class PhysicalAddressValidator implements ParameterValidator {
        @Override
        public int isValid(byte[] params) {
@@ -874,4 +964,78 @@ public class HdmiCecMessageValidator {
            return toErrorCode(isValidTimerStatusData(params, 0));
        }
    }

    /**
     * Check if the given play mode parameter is valid. A valid parameter should lie within the
     * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
     */
    private class PlayModeValidator implements ParameterValidator {
        @Override
        public int isValid(byte[] params) {
            if (params.length < 1) {
                return ERROR_PARAMETER_SHORT;
            }
            return toErrorCode(isValidPlayMode(params[0]));
        }
    }

    /**
     * Check if the given select analogue service parameter is valid. A valid parameter should lie
     * within the range description defined in CEC 1.4 Specification : Operand Descriptions
     * (Section 17)
     */
    private class SelectAnalogueServiceValidator implements ParameterValidator {
        @Override
        public int isValid(byte[] params) {
            if (params.length < 4) {
                return ERROR_PARAMETER_SHORT;
            }
            return toErrorCode(isValidAnalogueBroadcastType(params[0])
                    && isValidAnalogueFrequency(HdmiUtils.twoBytesToInt(params, 1))
                    && isValidBroadcastSystem(params[3]));
        }
    }

    /**
     * Check if the given select digital service parameter is valid. A valid parameter should lie
     * within the range description defined in CEC 1.4 Specification : Operand Descriptions
     * (Section 17)
     */
    private class SelectDigitalServiceValidator implements ParameterValidator {
        @Override
        public int isValid(byte[] params) {
            if (params.length < 4) {
                return ERROR_PARAMETER_SHORT;
            }
            return toErrorCode(isValidDigitalServiceIdentification(params, 0));
        }
    }

    /** Check if the given user control press parameter is valid. */
    private class UserControlPressedValidator implements ParameterValidator {
        @Override
        public int isValid(byte[] params) {
            if (params.length < 1) {
                return ERROR_PARAMETER_SHORT;
            }
            if (params.length == 1) {
                return OK;
            }
            int uiCommand = params[0];
            switch (uiCommand) {
                case HdmiCecKeycode.CEC_KEYCODE_PLAY_FUNCTION:
                    return toErrorCode(isValidPlayMode(params[1]));
                case HdmiCecKeycode.CEC_KEYCODE_TUNE_FUNCTION:
                    return (params.length >= 4
                            ? toErrorCode(isValidChannelIdentifier(params, 1))
                            : ERROR_PARAMETER_SHORT);
                case HdmiCecKeycode.CEC_KEYCODE_SELECT_BROADCAST_TYPE:
                    return toErrorCode(isValidUiBroadcastType(params[1]));
                case HdmiCecKeycode.CEC_KEYCODE_SELECT_SOUND_PRESENTATION:
                    return toErrorCode(isValidUiSoundPresenationControl(params[1]));
                default:
                    return OK;
            }
        }
    }
}
+141 −0
Original line number Diff line number Diff line
@@ -371,6 +371,147 @@ public class HdmiCecMessageValidatorTest {
        assertMessageValidity("0F:A6").isEqualTo(ERROR_PARAMETER_SHORT);
    }

    @Test
    public void isValid_deckControl() {
        assertMessageValidity("40:42:01:6E").isEqualTo(OK);
        assertMessageValidity("40:42:04").isEqualTo(OK);

        assertMessageValidity("4F:42:01").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:42:04").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:42").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:42:05").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_deckStatus() {
        assertMessageValidity("40:1B:11:58").isEqualTo(OK);
        assertMessageValidity("40:1B:1F").isEqualTo(OK);

        assertMessageValidity("4F:1B:11").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:1B:1F").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:1B").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:1B:10").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:1B:20").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_statusRequest() {
        assertMessageValidity("40:08:01").isEqualTo(OK);
        assertMessageValidity("40:08:02:5C").isEqualTo(OK);
        assertMessageValidity("40:1A:01:F8").isEqualTo(OK);
        assertMessageValidity("40:1A:03").isEqualTo(OK);

        assertMessageValidity("4F:08:01").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:08:03").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("4F:1A:01").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:1A:03").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:08").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:1A").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:08:00").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:08:05").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:1A:00").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:1A:04").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_play() {
        assertMessageValidity("40:41:16:E3").isEqualTo(OK);
        assertMessageValidity("40:41:20").isEqualTo(OK);

        assertMessageValidity("4F:41:16").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:41:20").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:41").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:41:04").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:41:18").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:41:23").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:41:26").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_selectAnalogueService() {
        assertMessageValidity("40:92:00:13:0F:00:96").isEqualTo(OK);
        assertMessageValidity("40:92:02:EA:60:1F").isEqualTo(OK);

        assertMessageValidity("4F:92:00:13:0F:00").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:92:02:EA:60:1F").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:92:00:13:0F").isEqualTo(ERROR_PARAMETER_SHORT);
        // Invalid Analogue Broadcast type
        assertMessageValidity("40:92:03:EA:60:1F").isEqualTo(ERROR_PARAMETER);
        // Invalid Analogue Frequency
        assertMessageValidity("40:92:00:FF:FF:00").isEqualTo(ERROR_PARAMETER);
        // Invalid Broadcast system
        assertMessageValidity("40:92:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_selectDigitalService() {
        assertMessageValidity("40:93:00:11:CE:90:0F:00:78").isEqualTo(OK);
        assertMessageValidity("40:93:10:13:0B:34:38").isEqualTo(OK);
        assertMessageValidity("40:93:9A:06:F9:D3:E6").isEqualTo(OK);
        assertMessageValidity("40:93:91:09:F4:40:C8").isEqualTo(OK);

        assertMessageValidity("4F:93:00:11:CE:90:0F:00:78").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:93:10:13:0B:34:38").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:93:9A:06:F9").isEqualTo(ERROR_PARAMETER_SHORT);
        // Invalid Digital Broadcast System
        assertMessageValidity("40:93:14:11:CE:90:0F:00:78").isEqualTo(ERROR_PARAMETER);
        // Invalid Digital Broadcast System
        assertMessageValidity("40:93:A0:07:95:F1").isEqualTo(ERROR_PARAMETER);
        // Insufficient data for ARIB Broadcast system
        assertMessageValidity("40:93:00:11:CE:90:0F:00").isEqualTo(ERROR_PARAMETER);
        // Insufficient data for ATSC Broadcast system
        assertMessageValidity("40:93:10:13:0B:34").isEqualTo(ERROR_PARAMETER);
        // Insufficient data for DVB Broadcast system
        assertMessageValidity("40:93:18:BE:77:00:7D:01").isEqualTo(ERROR_PARAMETER);
        // Invalid channel number format
        assertMessageValidity("40:93:9A:10:F9:D3").isEqualTo(ERROR_PARAMETER);
        // Insufficient data for 2 part channel number
        assertMessageValidity("40:93:91:09:F4:40").isEqualTo(ERROR_PARAMETER);
    }

    @Test
    public void isValid_UserControlPressed() {
        assertMessageValidity("40:44:07").isEqualTo(OK);
        assertMessageValidity("40:44:52:A7").isEqualTo(OK);

        assertMessageValidity("40:44:60").isEqualTo(OK);
        assertMessageValidity("40:44:60:1A").isEqualTo(OK);

        assertMessageValidity("40:44:67").isEqualTo(OK);
        assertMessageValidity("40:44:67:04:00:B1").isEqualTo(OK);
        assertMessageValidity("40:44:67:09:C8:72:C8").isEqualTo(OK);

        assertMessageValidity("40:44:68").isEqualTo(OK);
        assertMessageValidity("40:44:68:93").isEqualTo(OK);
        assertMessageValidity("40:44:69").isEqualTo(OK);
        assertMessageValidity("40:44:69:7C").isEqualTo(OK);
        assertMessageValidity("40:44:6A").isEqualTo(OK);
        assertMessageValidity("40:44:6A:B4").isEqualTo(OK);

        assertMessageValidity("40:44:56").isEqualTo(OK);
        assertMessageValidity("40:44:56:60").isEqualTo(OK);

        assertMessageValidity("40:44:57").isEqualTo(OK);
        assertMessageValidity("40:44:57:A0").isEqualTo(OK);

        assertMessageValidity("4F:44:07").isEqualTo(ERROR_DESTINATION);
        assertMessageValidity("F0:44:52:A7").isEqualTo(ERROR_SOURCE);
        assertMessageValidity("40:44").isEqualTo(ERROR_PARAMETER_SHORT);
        assertMessageValidity("40:44:67:04:B1").isEqualTo(ERROR_PARAMETER_SHORT);
        // Invalid Play mode
        assertMessageValidity("40:44:60:04").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:44:60:08").isEqualTo(ERROR_PARAMETER);
        assertMessageValidity("40:44:60:26").isEqualTo(ERROR_PARAMETER);
        // Invalid Channel Identifier - Channel number format
        assertMessageValidity("40:44:67:11:8A:42").isEqualTo(ERROR_PARAMETER);
        // Insufficient data for 2 - part channel number
        assertMessageValidity("40:44:67:09:C8:72").isEqualTo(ERROR_PARAMETER);
        // Invalid UI Broadcast type
        assertMessageValidity("40:44:56:11").isEqualTo(ERROR_PARAMETER);
        // Invalid UI Sound Presentation Control
        assertMessageValidity("40:44:57:40").isEqualTo(ERROR_PARAMETER);
    }

    private IntegerSubject assertMessageValidity(String message) {
        return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
    }