summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java88
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java39
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)));
}