HDMI: Fix BCD handling error
isValidHour/isValidMinute accept a parameter as BCD encoded value, but they check it without translating to raw value, so valid hour/minute may be detected as an error;
e.g.
18:00 is within 23:00 but 0x18(24) is over 23
* 0x18 should be decoded (0x10 >> 4) x 10 + 0x08 = 18
Fix to translate the parameter before checking by isWithinRange.
Bug: 357733495
Change-Id: Id0cfb1211048b1f2eaebf3db5814e3da0f34e5b9
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 16b00de..18a6e3dd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -486,6 +486,7 @@
* @return true if the hour is valid
*/
private static boolean isValidHour(int value) {
+ value = bcdToDecimal(value);
return isWithinRange(value, 0, 23);
}
@@ -497,6 +498,7 @@
* @return true if the minute is valid
*/
private static boolean isValidMinute(int value) {
+ value = bcdToDecimal(value);
return isWithinRange(value, 0, 59);
}
@@ -508,10 +510,24 @@
* @return true if the duration hours is valid
*/
private static boolean isValidDurationHours(int value) {
+ value = bcdToDecimal(value);
return isWithinRange(value, 0, 99);
}
/**
+ * Convert BCD value to decimal value.
+ *
+ * @param value BCD value
+ * @return decimal value
+ */
+ private static int bcdToDecimal(int value) {
+ int tens = (value & 0xF0) >> 4;
+ int ones = (value & 0x0F);
+
+ return tens * 10 + ones;
+ }
+
+ /**
* Check if the given value is a valid recording sequence. A valid value is adheres to range
* description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
*
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 ce7dbda..2446d2e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -249,120 +249,120 @@
assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06")
.isEqualTo(ERROR_PARAMETER_SHORT);
// Out of range Day of Month
- assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:20:0C:22:15:08:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
// Out of range Month of Year
- assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:33:0C:00:16:30:04:48:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Hour
- assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:04:0C:24:15:08:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Minute
- assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:33:0C:08:16:60:04:48:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Duration Hours
- assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:04:0C:22:15:9A:55:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Minute
- assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:33:0C:08:16:30:04:60:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
- assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:04:0C:22:15:08:55:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
- assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:33:0C:08:16:30:04:48:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
// Out of range Analogue Broadcast Type
- assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:04:0C:22:15:08:55:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER);
// Out of range Analogue Frequency
- assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:33:0C:08:16:30:04:48:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER);
// Out of range Broadcast System
- assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:34:04:0C:22:15:08:55:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
}
@Test
public void isValid_setDigitalTimer_clearDigitalTimer() {
// Services identified by Digital IDs - ARIB Broadcast System
- assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK);
+ assertMessageValidity("04:99:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75:30").isEqualTo(OK);
// Service identified by Digital IDs - ATSC Broadcast System
- assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK);
+ assertMessageValidity("04:97:1E:07:18:32:80:40:01:01:8B:5E:39:5A").isEqualTo(OK);
// Service identified by Digital IDs - DVB Broadcast System
- assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK);
+ assertMessageValidity("04:99:05:0C:06:10:25:59:40:19:8B:44:03:11:04:FC").isEqualTo(OK);
// Service identified by Channel - 1 part channel number
- assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK);
+ assertMessageValidity("04:97:12:06:12:45:90:25:08:91:04:00:B1").isEqualTo(OK);
// Service identified by Channel - 2 part channel number
- assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK);
+ assertMessageValidity("04:99:15:09:00:15:00:45:04:82:09:C8:72:C8").isEqualTo(OK);
- assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30")
+ assertMessageValidity("4F:97:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75:30")
.isEqualTo(ERROR_DESTINATION);
- assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("F0:99:15:09:00:15:00:45:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE);
assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A")
.isEqualTo(ERROR_PARAMETER_SHORT);
// Out of range Day of Month
- assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC")
+ assertMessageValidity("04:99:24:0C:06:10:25:59:40:19:8B:44:03:11:04:FC")
.isEqualTo(ERROR_PARAMETER);
// Out of range Month of Year
- assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:97:12:10:12:45:90:25:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Hour
- assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30")
+ assertMessageValidity("04:99:0C:08:24:05:04:30:00:00:C4:C2:11:D8:75:30")
.isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Minute
- assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8")
+ assertMessageValidity("04:97:15:09:00:60:00:45:04:82:09:C8:72:C8")
.isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Duration Hours
- assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A")
+ assertMessageValidity("04:99:1E:07:18:32:9A:40:01:01:8B:5E:39:5A")
.isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Minute
- assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC")
+ assertMessageValidity("04:97:05:0C:06:10:25:60:40:19:8B:44:03:11:04:FC")
.isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
- assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:99:12:06:12:45:90:25:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
assertMessageValidity("04:97:0C:08:15:05:04:1E:A1:00:C4:C2:11:D8:75:30")
.isEqualTo(ERROR_PARAMETER);
// Invalid Digital Broadcast System
- assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A")
+ assertMessageValidity("04:99:1E:07:18:32:80:40:01:04:8B:5E:39:5A")
.isEqualTo(ERROR_PARAMETER);
// Invalid Digital Broadcast System
- assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC")
+ assertMessageValidity("04:97:05:0C:06:10:25:59:40:93:8B:44:03:11:04:FC")
.isEqualTo(ERROR_PARAMETER);
// Insufficient data for ARIB Broadcast system
- assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75")
+ assertMessageValidity("04:99:0C:08:21:05:04:30:00:00:C4:C2:11:D8:75")
.isEqualTo(ERROR_PARAMETER);
// Insufficient data for ATSC Broadcast system
- assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:97:1E:07:18:32:80:40:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER);
// Insufficient data for DVB Broadcast system
- assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04")
+ assertMessageValidity("04:99:05:0C:06:10:25:59:40:19:8B:44:03:11:04")
.isEqualTo(ERROR_PARAMETER);
// Insufficient data for 2 part channel number
- assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:97:15:09:00:15:00:45:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER);
// Invalid Channel Number format
- assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:99:12:06:12:45:90:25:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER);
}
@Test
public void isValid_setExternalTimer_clearExternalTimer() {
- assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK);
- assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK);
+ assertMessageValidity("40:A1:0C:08:21:05:04:30:02:04:20").isEqualTo(OK);
+ assertMessageValidity("40:A2:14:09:18:40:75:25:10:05:10:00").isEqualTo(OK);
- assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION);
- assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE);
- assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT);
+ assertMessageValidity("4F:A1:0C:08:21:05:04:30:02:04:20").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F4:A2:14:09:18:40:75:25:10:05:10:00").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("40:A1:0C:08:21:05:04:30:02:04").isEqualTo(ERROR_PARAMETER_SHORT);
// Out of range Day of Month
- assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:28:09:18:40:75:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
// Out of range Month of Year
- assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A1:0C:0F:21:05:04:30:02:04:20").isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Hour
- assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:14:09:24:40:75:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
// Out of range Start Time - Minute
- assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A1:0C:08:21:60:04:30:02:04:20").isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Duration Hours
- assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:14:09:18:40:9A:25:10:05:10:00").isEqualTo(ERROR_PARAMETER);
// Out of range Duration - Minute
- assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A1:0C:08:21:05:04:60:02:04:20").isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
- assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:14:09:18:40:75:25:84:05:10:00").isEqualTo(ERROR_PARAMETER);
// Invalid Recording Sequence
assertMessageValidity("40:A1:0C:08:15:05:04:1E:94:04:20").isEqualTo(ERROR_PARAMETER);
// Invalid external source specifier
- assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:14:09:18:40:75:25:10:08:10:00").isEqualTo(ERROR_PARAMETER);
// Invalid External PLug
- assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("04:A1:0C:08:21:05:04:30:02:04:00").isEqualTo(ERROR_PARAMETER);
// Invalid Physical Address
- assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:10").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:A2:14:09:18:40:75:25:10:05:10:10").isEqualTo(ERROR_PARAMETER);
}
@Test
@@ -395,9 +395,9 @@
// Non programmed - Invalid not programmed error info
assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER);
// Programmed - Might not be enough space available - Invalid duration hours
- assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:35:BB:9A:28").isEqualTo(ERROR_PARAMETER);
// Not programmed - Duplicate - Invalid duration minutes
- assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
+ assertMessageValidity("40:35:EE:82:60").isEqualTo(ERROR_PARAMETER);
}
@Test