CEC: Don't send <Feature Abort> on the short message

Bug: 18261915
Change-Id: I722392afacc29ec9f2af27df49b68bd773b53e3d
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index d703989..f1529a7 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -29,11 +29,16 @@
     static final int ERROR_SOURCE = 1;
     static final int ERROR_DESTINATION = 2;
     static final int ERROR_PARAMETER = 3;
+    static final int ERROR_PARAMETER_SHORT = 4;
 
     private final HdmiControlService mService;
 
     interface ParameterValidator {
-        boolean isValid(byte[] params);
+        /**
+         * @return errorCode errorCode can be {@link #OK}, {@link #ERROR_PARAMETER} or
+         *         {@link #ERROR_PARAMETER_SHORT}.
+         */
+        int isValid(byte[] params);
     }
 
     // Only the direct addressing is allowed.
@@ -213,9 +218,10 @@
         }
 
         // Check the parameter type.
-        if (!info.parameterValidator.isValid(message.getParams())) {
+        int errorCode = info.parameterValidator.isValid(message.getParams());
+        if (errorCode != OK) {
             HdmiLogger.warning("Unexpected parameters: " + message);
-            return ERROR_PARAMETER;
+            return errorCode;
         }
         return OK;
     }
@@ -228,8 +234,10 @@
         }
 
         @Override
-        public boolean isValid(byte[] params) {
-            return params.length == mLength;
+        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.
+            return params.length < mLength ? ERROR_PARAMETER_SHORT : OK;
         }
     }
 
@@ -243,8 +251,8 @@
         }
 
         @Override
-        public boolean isValid(byte[] params) {
-            return params.length >= mMinLength && params.length <= mMaxLength;
+        public int isValid(byte[] params) {
+            return params.length < mMinLength ? ERROR_PARAMETER_SHORT : OK;
         }
     }
 
@@ -270,8 +278,7 @@
      * Check if the given type is valid. A valid type is one of the actual logical device types
      * defined in the standard ({@link HdmiDeviceInfo#DEVICE_TV},
      * {@link HdmiDeviceInfo#DEVICE_PLAYBACK}, {@link HdmiDeviceInfo#DEVICE_TUNER},
-     * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and
-     * {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
+     * {@link HdmiDeviceInfo#DEVICE_RECORDER}, and {@link HdmiDeviceInfo#DEVICE_AUDIO_SYSTEM}).
      *
      * @param type device type
      * @return true if the given type is valid
@@ -282,33 +289,38 @@
                 && type != HdmiDeviceInfo.DEVICE_RESERVED;
     }
 
+    private static int toErrorCode(boolean success) {
+        return success ? OK : ERROR_PARAMETER;
+    }
+
     private class PhysicalAddressValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 2) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 2) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0);
+            return toErrorCode(isValidPhysicalAddress(params, 0));
         }
     }
 
     private class ReportPhysicalAddressValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 3) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 3) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0) && isValidType(params[2]);
+            return toErrorCode(isValidPhysicalAddress(params, 0) && isValidType(params[2]));
         }
     }
 
     private class RoutingChangeValidator implements ParameterValidator {
         @Override
-        public boolean isValid(byte[] params) {
-            if (params.length != 4) {
-                return false;
+        public int isValid(byte[] params) {
+            if (params.length < 4) {
+                return ERROR_PARAMETER_SHORT;
             }
-            return isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2);
+            return toErrorCode(
+                    isValidPhysicalAddress(params, 0) && isValidPhysicalAddress(params, 2));
         }
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d8d513e..907a49a 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -719,7 +719,8 @@
         assertRunOnServiceThread();
         int errorCode = mMessageValidator.isValid(message);
         if (errorCode != HdmiCecMessageValidator.OK) {
-            // We'll not response on the messages with the invalid source or destination.
+            // We'll not response on the messages with the invalid source or destination
+            // or with parameter length shorter than specified in the standard.
             if (errorCode == HdmiCecMessageValidator.ERROR_PARAMETER) {
                 maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND);
             }