Forbid services from extending any other interfaces

Test: ./gradlew :privacysandbox:tools:tools-{apigenerator,apicompiler,apipackager,core}:test
Bug: 265266769
Change-Id: I3bdc69dbfa7e0d56f4f8c161e3baed319d173a02
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/parser/InterfaceParserTest.kt b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/parser/InterfaceParserTest.kt
index 730e107..98bf7a3 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/parser/InterfaceParserTest.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/test/java/androidx/privacysandbox/tools/apicompiler/parser/InterfaceParserTest.kt
@@ -265,16 +265,20 @@
             "com/mysdk/MySdk.kt", """
                     package com.mysdk
                     import androidx.privacysandbox.tools.PrivacySandboxService
+                    import androidx.privacysandbox.tools.PrivacySandboxInterface
 
                     interface FooInterface {}
 
                     @PrivacySandboxService
-                    interface MySdk : FooInterface {
+                    interface MySdk {}
+
+                    @PrivacySandboxInterface
+                    interface MyInterface : FooInterface {
                         suspend fun foo(): Int
                     }"""
         )
         checkSourceFails(source).containsExactlyErrors(
-            "Error in com.mysdk.MySdk: annotated interface inherits prohibited types (" +
+            "Error in com.mysdk.MyInterface: annotated interface inherits prohibited types (" +
                 "FooInterface)."
         )
     }
@@ -285,6 +289,7 @@
             "com/mysdk/MySdk.kt", """
                     package com.mysdk
                     import androidx.privacysandbox.tools.PrivacySandboxService
+                    import androidx.privacysandbox.tools.PrivacySandboxInterface
 
                     interface A {}
                     interface B {}
@@ -292,13 +297,16 @@
                     interface D {}
 
                     @PrivacySandboxService
-                    interface MySdk : B, C, D, A {
+                    interface MySdk {}
+
+                    @PrivacySandboxInterface
+                    interface MyInterface : B, C, D, A {
                         suspend fun foo(): Int
                     }"""
         )
         checkSourceFails(source).containsExactlyErrors(
-            "Error in com.mysdk.MySdk: annotated interface inherits prohibited types (A, B, C, " +
-                "...)."
+            "Error in com.mysdk.MyInterface: annotated interface inherits prohibited types (A, " +
+                "B, C, ...)."
         )
     }
 
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
index 15aa5e0..bc6aeb5 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
@@ -36,6 +36,7 @@
 
     private fun validate(): ValidationResult {
         validateSingleService()
+        validateServiceSupertypes()
         validateNonSuspendFunctionsReturnUnit()
         validateServiceAndInterfaceMethods()
         validateValuePropertyTypes()
@@ -52,6 +53,24 @@
         }
     }
 
+    private fun validateServiceSupertypes() {
+        val superTypes = api.services.first().superTypes
+        if (superTypes.isNotEmpty()) {
+            if (superTypes.contains(Types.sandboxedUiAdapter)) {
+                errors.add(
+                    "Interfaces annotated with @PrivacySandboxService may not extend any other " +
+                        "interface. To define a SandboxedUiAdapter, use @PrivacySandboxInterface " +
+                        "and return it from this service."
+                )
+            } else {
+                errors.add(
+                    "Interfaces annotated with @PrivacySandboxService may not extend any other " +
+                        "interface. Found: ${superTypes.joinToString { it.qualifiedName }}."
+                )
+            }
+        }
+    }
+
     private fun validateNonSuspendFunctionsReturnUnit() {
         val annotatedInterfaces = api.services + api.interfaces
         for (annotatedInterface in annotatedInterfaces) {
diff --git a/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/validator/ModelValidatorTest.kt b/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/validator/ModelValidatorTest.kt
index 3a967ad..ab69a85 100644
--- a/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/validator/ModelValidatorTest.kt
+++ b/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/validator/ModelValidatorTest.kt
@@ -169,6 +169,25 @@
     }
 
     @Test
+    fun serviceExtendsUiAdapter_throws() {
+        val api = ParsedApi(
+            services = setOf(
+                AnnotatedInterface(
+                    type = Type(packageName = "com.mysdk", simpleName = "MySdk"),
+                    superTypes = listOf(Types.sandboxedUiAdapter),
+                ),
+            )
+        )
+        val validationResult = ModelValidator.validate(api)
+        assertThat(validationResult.isFailure).isTrue()
+        assertThat(validationResult.errors).containsExactly(
+            "Interfaces annotated with @PrivacySandboxService may not extend any other " +
+                "interface. To define a SandboxedUiAdapter, use @PrivacySandboxInterface and " +
+                "return it from this service."
+        )
+    }
+
+    @Test
     fun nonSuspendFunctionReturningValue_throws() {
         val api = ParsedApi(
             services = setOf(