Loading services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +177 −13 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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( Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; } } } } services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +141 −0 Original line number Diff line number Diff line Loading @@ -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))); } Loading Loading
services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +177 −13 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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( Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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; } } } }
services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +141 −0 Original line number Diff line number Diff line Loading @@ -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))); } Loading