Merge "CTS Coverage Report Support for generic types" into mnc-dev
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
index f5abd5e5..73cea67 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
@@ -24,6 +24,8 @@
 /** Representation of a class in the API with constructors and methods. */
 class ApiClass implements Comparable<ApiClass>, HasCoverage {
 
+    private static final String VOID = "void";
+
     private final String mName;
 
     private final boolean mDeprecated;
@@ -156,18 +158,83 @@
 
     private ApiMethod getMethod(String name, List<String> parameterTypes, String returnType) {
         for (ApiMethod method : mApiMethods) {
-            if (name.equals(method.getName())
-                    && parameterTypes.equals(method.getParameterTypes())
-                    && returnType.equals(method.getReturnType())) {
+            boolean methodNameMatch = name.equals(method.getName());
+            boolean parameterTypeMatch =
+                    compareParameterTypes(method.getParameterTypes(), parameterTypes);
+            boolean returnTypeMatch = compareType(method.getReturnType(), returnType);
+            if (methodNameMatch && parameterTypeMatch && returnTypeMatch) {
                 return method;
             }
         }
         return null;
     }
 
+    /**
+     * The method compares two lists of parameters. If the {@code apiParameterTypeList} contains
+     * generic types, test parameter types are ignored.
+     *
+     * @param apiParameterTypeList The list of parameter types from the API
+     * @param testParameterTypeList The list of parameter types used in a test
+     * @return true iff the list of types are the same.
+     */
+    private static boolean compareParameterTypes(
+            List<String> apiParameterTypeList, List<String> testParameterTypeList) {
+        if (apiParameterTypeList.equals(testParameterTypeList)) {
+            return true;
+        }
+        if (apiParameterTypeList.size() != testParameterTypeList.size()) {
+            return false;
+        }
+
+        for (int i = 0; i < apiParameterTypeList.size(); i++) {
+            String apiParameterType = apiParameterTypeList.get(i);
+            String testParameterType = testParameterTypeList.get(i);
+            if (!compareType(apiParameterType, testParameterType)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compare class types.
+     * @param apiType The type as reported by the api
+     * @param testType The type as found used in a test
+     * @return true iff the strings are equal,
+     * or the apiType is generic and the test type is not void
+     */
+    private static boolean compareType(String apiType, String testType) {
+        return apiType.equals(testType) ||
+                isGenericType(apiType) && !testType.equals(VOID) ||
+                isGenericArrayType(apiType) && isArrayType(testType) ;
+    }
+
+    /**
+     * @return true iff the given parameterType is a generic type.
+     */
+    private static boolean isGenericType(String type) {
+        return type.length() == 1 &&
+                type.charAt(0) >= 'A' &&
+                type.charAt(0) <= 'Z';
+    }
+
+    /**
+     * @return true iff {@code type} ends with an [].
+     */
+    private static boolean isArrayType(String type) {
+        return type.endsWith("[]");
+    }
+
+    /**
+     * @return true iff the given parameterType is an array of generic type.
+     */
+    private static boolean isGenericArrayType(String type) {
+        return type.length() == 3 && isGenericType(type.substring(0, 1)) && isArrayType(type);
+    }
+
     private ApiConstructor getConstructor(List<String> parameterTypes) {
         for (ApiConstructor constructor : mApiConstructors) {
-            if (parameterTypes.equals(constructor.getParameterTypes())) {
+            if (compareParameterTypes(constructor.getParameterTypes(), parameterTypes)) {
                 return constructor;
             }
         }