check-flagged-apis: record interfaces when parsing classes

Extend ClassSymbol with a list of the interfaces that class implements.
This will be used in a follow-up CL to improve the logic that checks if
a class member exists in the api-versions.xml data.

Bug: 334870672
Test: atest --host check-flagged-apis-test
Change-Id: I4db7ff47c3ce40ca892cb872810dd559426dfcb8
diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
index 4835461..29604f4 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/CheckFlaggedApisTest.kt
@@ -95,7 +95,7 @@
   fun testParseApiSignature() {
     val expected =
         setOf(
-            Pair(Symbol.createClass("android/Clazz"), Flag("android.flag.foo")),
+            Pair(Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")),
             Pair(Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
             Pair(Symbol.createField("android/Clazz", "FOO"), Flag("android.flag.foo")),
             Pair(Symbol.createMethod("android/Clazz", "getErrorCode()"), Flag("android.flag.foo")),
@@ -108,7 +108,7 @@
             Pair(
                 Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
                 Flag("android.flag.foo")),
-            Pair(Symbol.createClass("android/Clazz/Builder"), Flag("android.flag.bar")),
+            Pair(Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")),
         )
     val actual = parseApiSignature("in-memory", API_SIGNATURE.byteInputStream())
     assertEquals(expected, actual)
@@ -126,14 +126,14 @@
   fun testParseApiVersions() {
     val expected: Set<Symbol> =
         setOf(
-            Symbol.createClass("android/Clazz"),
+            Symbol.createClass("android/Clazz", setOf()),
             Symbol.createMethod("android/Clazz", "Clazz()"),
             Symbol.createField("android/Clazz", "FOO"),
             Symbol.createMethod("android/Clazz", "getErrorCode()"),
             Symbol.createMethod("android/Clazz", "setData(I[[ILandroid/util/Utility;)"),
             Symbol.createMethod("android/Clazz", "setVariableData(I[Landroid/util/Atom;)"),
             Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
-            Symbol.createClass("android/Clazz/Builder"),
+            Symbol.createClass("android/Clazz/Builder", setOf()),
         )
     val actual = parseApiVersions(API_VERSIONS.byteInputStream())
     assertEquals(expected, actual)
@@ -153,7 +153,7 @@
             .trim()
     val expected: Set<Symbol> =
         setOf(
-            Symbol.createClass("android/Clazz/Foo/Bar"),
+            Symbol.createClass("android/Clazz/Foo/Bar", setOf()),
             Symbol.createMethod("android/Clazz/Foo/Bar", "Bar()"),
         )
     val actual = parseApiVersions(apiVersions.byteInputStream())
@@ -176,7 +176,7 @@
     val expected =
         setOf<ApiError>(
             DisabledFlaggedApiIsPresentError(
-                Symbol.createClass("android/Clazz"), Flag("android.flag.foo")),
+                Symbol.createClass("android/Clazz", setOf()), Flag("android.flag.foo")),
             DisabledFlaggedApiIsPresentError(
                 Symbol.createMethod("android/Clazz", "Clazz()"), Flag("android.flag.foo")),
             DisabledFlaggedApiIsPresentError(
@@ -193,7 +193,7 @@
                 Symbol.createMethod("android/Clazz", "innerClassArg(Landroid/Clazz/Builder;)"),
                 Flag("android.flag.foo")),
             DisabledFlaggedApiIsPresentError(
-                Symbol.createClass("android/Clazz/Builder"), Flag("android.flag.bar")),
+                Symbol.createClass("android/Clazz/Builder", setOf()), Flag("android.flag.bar")),
         )
     val actual =
         findErrors(
diff --git a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
index 4ff9880..0f58aa5 100644
--- a/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
+++ b/tools/check-flagged-apis/src/com/android/checkflaggedapis/Main.kt
@@ -58,8 +58,8 @@
   companion object {
     private val FORBIDDEN_CHARS = listOf('#', '$', '.')
 
-    fun createClass(clazz: String): Symbol {
-      return ClassSymbol(toInternalFormat(clazz))
+    fun createClass(clazz: String, interfaces: Set<String>): Symbol {
+      return ClassSymbol(toInternalFormat(clazz), interfaces.map { toInternalFormat(it) }.toSet())
     }
 
     fun createField(clazz: String, field: String): Symbol {
@@ -83,7 +83,7 @@
   abstract fun toPrettyString(): String
 }
 
-internal data class ClassSymbol(val clazz: String) : Symbol() {
+internal data class ClassSymbol(val clazz: String, val interfaces: Set<String>) : Symbol() {
   override fun toPrettyString(): String = "$clazz"
 }
 
@@ -195,7 +195,10 @@
       object : BaseItemVisitor() {
         override fun visitClass(cls: ClassItem) {
           getFlagOrNull(cls)?.let { flag ->
-            val symbol = Symbol.createClass(cls.baselineElementId())
+            val symbol =
+                Symbol.createClass(
+                    cls.baselineElementId(),
+                    cls.allInterfaces().map { it.baselineElementId() }.toSet())
             output.add(Pair(symbol, flag))
           }
         }
@@ -257,7 +260,19 @@
         requireNotNull(cls.getAttribute("name")) {
           "Bad XML: <class> element without name attribute"
         }
-    output.add(Symbol.createClass(className))
+    val interfaces = mutableSetOf<String>()
+    val children = cls.getChildNodes()
+    for (j in 0.rangeUntil(children.getLength())) {
+      val child = children.item(j)
+      if (child.getNodeName() == "implements") {
+        val interfaceName =
+            requireNotNull(child.getAttribute("name")) {
+              "Bad XML: <implements> element without name attribute"
+            }
+        interfaces.add(interfaceName)
+      }
+    }
+    output.add(Symbol.createClass(className, interfaces))
   }
 
   val fields = document.getElementsByTagName("field")