diff options
| -rw-r--r-- | services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java | 88 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java | 39 |
2 files changed, 124 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java index 28bd97e4843c..d4593afe18fe 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java @@ -128,7 +128,7 @@ public class HdmiCecMessageValidator { FixedLengthValidator oneByteValidator = new FixedLengthValidator(1); addValidationInfo(Constants.MESSAGE_CEC_VERSION, oneByteValidator, DEST_DIRECT); addValidationInfo(Constants.MESSAGE_SET_MENU_LANGUAGE, - new FixedLengthValidator(3), DEST_BROADCAST); + new AsciiValidator(3), DEST_BROADCAST); // TODO: Handle messages for the Deck Control. @@ -148,8 +148,8 @@ public class HdmiCecMessageValidator { maxLengthValidator, DEST_ALL | SRC_UNREGISTERED); // Messages for the OSD. - addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, maxLengthValidator, DEST_DIRECT); - addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, maxLengthValidator, DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_SET_OSD_STRING, new OsdStringValidator(), DEST_DIRECT); + addValidationInfo(Constants.MESSAGE_SET_OSD_NAME, new AsciiValidator(1, 14), DEST_DIRECT); // Messages for the Device Menu Control. addValidationInfo(Constants.MESSAGE_MENU_REQUEST, oneByteValidator, DEST_DIRECT); @@ -299,6 +299,37 @@ public class HdmiCecMessageValidator { return (value >= min && value <= max); } + /** + * Check if the given value is a valid Display Control. A valid value is one which falls within + * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param value Display Control + * @return true if the Display Control is valid + */ + private boolean isValidDisplayControl(int value) { + value = value & 0xFF; + return (value == 0x00 || value == 0x40 || value == 0x80 || value == 0xC0); + } + + /** + * Check if the given params has valid ASCII characters. + * A valid ASCII character is a printable character. It should fall within range description + * defined in CEC 1.4 Specification : Operand Descriptions (Section 17) + * + * @param params parameter consisting of string + * @param offset Start offset of string + * @param maxLength Maximum length of string to be evaluated + * @return true if the given type is valid + */ + private boolean isValidAsciiString(byte[] params, int offset, int maxLength) { + for (int i = offset; i < params.length && i < maxLength; i++) { + if (!isWithinRange(params[i], 0x20, 0x7E)) { + return false; + } + } + return true; + } + private class PhysicalAddressValidator implements ParameterValidator { @Override public int isValid(byte[] params) { @@ -359,4 +390,55 @@ public class HdmiCecMessageValidator { || params[0] == 0x1F); } } + + /** + * Check if the given parameters represents printable characters. + * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 + * Specification : Operand Descriptions (Section 17) + */ + private class AsciiValidator implements ParameterValidator { + private final int mMinLength; + private final int mMaxLength; + + AsciiValidator(int length) { + mMinLength = length; + mMaxLength = length; + } + + AsciiValidator(int minLength, int maxLength) { + mMinLength = minLength; + mMaxLength = maxLength; + } + + @Override + public int isValid(byte[] params) { + // If the length is longer than expected, we assume it's OK since the parameter can be + // extended in the future version. + if (params.length < mMinLength) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode(isValidAsciiString(params, 0, mMaxLength)); + } + } + + /** + * Check if the given parameters is valid OSD String. + * A valid parameter should lie within the range description of ASCII defined in CEC 1.4 + * Specification : Operand Descriptions (Section 17) + */ + private class OsdStringValidator implements ParameterValidator { + @Override + public int isValid(byte[] params) { + // If the length is longer than expected, we assume it's OK since the parameter can be + // extended in the future version. + if (params.length < 2) { + return ERROR_PARAMETER_SHORT; + } + return toErrorCode( + // Display Control + isValidDisplayControl(params[0]) + // OSD String + && isValidAsciiString(params, 1, 14)); + } + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java index 5a05fc6eda4c..debf20bffe28 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java @@ -17,6 +17,7 @@ package com.android.server.hdmi; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_DESTINATION; +import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_PARAMETER_SHORT; import static com.android.server.hdmi.HdmiCecMessageValidator.ERROR_SOURCE; import static com.android.server.hdmi.HdmiCecMessageValidator.OK; @@ -71,6 +72,44 @@ public class HdmiCecMessageValidatorTest { assertMessageValidity("04:90").isEqualTo(ERROR_PARAMETER_SHORT); } + @Test + public void isValid_setMenuLanguage() { + assertMessageValidity("4F:32:53:50:41").isEqualTo(OK); + assertMessageValidity("0F:32:45:4E:47:8C:49:D3:48").isEqualTo(OK); + + assertMessageValidity("40:32:53:50:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:32").isEqualTo(ERROR_SOURCE); + assertMessageValidity("4F:32:45:55").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("4F:32:19:7F:83").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdString() { + assertMessageValidity("40:64:80:41").isEqualTo(OK); + // Even though the parameter string in this message is longer than 14 bytes, it is accepted + // as this parameter might be extended in future versions. + assertMessageValidity("04:64:00:4C:69:76:69:6E:67:52:6F:6F:6D:20:54:56:C4").isEqualTo(OK); + + assertMessageValidity("4F:64:40:41").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:64:C0:41").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:64:00").isEqualTo(ERROR_PARAMETER_SHORT); + // Invalid Display Control + assertMessageValidity("40:64:20:4C:69:76").isEqualTo(ERROR_PARAMETER); + // Invalid ASCII characters + assertMessageValidity("40:64:40:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + + @Test + public void isValid_setOsdName() { + assertMessageValidity("40:47:4C:69:76:69:6E:67:52:6F:6F:6D:54:56").isEqualTo(OK); + assertMessageValidity("40:47:54:56").isEqualTo(OK); + + assertMessageValidity("4F:47:54:56").isEqualTo(ERROR_DESTINATION); + assertMessageValidity("F0:47:54:56").isEqualTo(ERROR_SOURCE); + assertMessageValidity("40:47").isEqualTo(ERROR_PARAMETER_SHORT); + assertMessageValidity("40:47:4C:69:7F").isEqualTo(ERROR_PARAMETER); + } + private IntegerSubject assertMessageValidity(String message) { return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message))); } |