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

Commit 9ab0dd09 authored by Shraddha Basantwani's avatar Shraddha Basantwani
Browse files

CEC : Add validator for user control pressed message

Test: atest HdmiCecMessageValidatorTest
Bug: 170811408
Change-Id: Ib7d4be7071e4b81e78f7fe19b5836d9c3caa4915
parent c0cd3291
Loading
Loading
Loading
Loading
+115 −18
Original line number Diff line number Diff line
@@ -192,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(
@@ -530,6 +531,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
@@ -560,15 +583,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;
@@ -648,6 +663,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) {
@@ -890,12 +964,7 @@ public class HdmiCecMessageValidator {
            if (params.length < 1) {
                return ERROR_PARAMETER_SHORT;
            }
            return toErrorCode(isWithinRange(params[0], 0x05, 0x07)
                    || isWithinRange(params[0], 0x09, 0x0B)
                    || isWithinRange(params[0], 0x15, 0x17)
                    || isWithinRange(params[0], 0x19, 0x1B)
                    || isWithinRange(params[0], 0x24, 0x25)
                    || (params[0] == 0x20));
            return toErrorCode(isValidPlayMode(params[0]));
        }
    }

@@ -930,4 +999,32 @@ public class HdmiCecMessageValidator {
            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;
            }
        }
    }
}
+43 −0
Original line number Diff line number Diff line
@@ -451,6 +451,49 @@ public class HdmiCecMessageValidatorTest {
        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)));
    }