Merge changes Ib7d4be70,Ia0f12e9b,I540c2900,Ife9ad043,Ie81c995b, ...
* changes: CEC : Add validator for user control pressed message CEC : Add validator for select digital service message CEC : Add validator for select analogue service message CEC : Add validator for give tuner device status message CEC : Add validator for play message CEC : Add validator for give deck status message CEC : Add validator for deck status message CEC : Add validator for deck control message
This commit is contained in:
@@ -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(
|
||||
@@ -514,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
|
||||
@@ -544,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;
|
||||
@@ -632,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) {
|
||||
@@ -863,4 +953,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,6 +353,147 @@ public class HdmiCecMessageValidatorTest {
|
||||
assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
|
||||
}
|
||||
|
||||
@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)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user