Support API compatibility check in Soong

Test: m -j api-stubs-docs
Bug: b/78245848
Change-Id: Id88a3e3716f9f07f0dc0071aa56a328c4712fcc9
diff --git a/java/droiddoc.go b/java/droiddoc.go
index b1e3ea8..ac4f86f 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -288,9 +288,10 @@
 	doclavaDocsFlags  string
 	postDoclavaCmds   string
 
-	metalavaStubsFlags       string
-	metalavaAnnotationsFlags string
-	metalavaJavadocFlags     string
+	metalavaStubsFlags              string
+	metalavaAnnotationsFlags        string
+	metalavaJavadocFlags            string
+	metalavaCompatibilityCheckFlags string
 
 	metalavaDokkaFlags string
 }
@@ -1013,6 +1014,38 @@
 		docStubsDir + " " + classpathArgs + " -format dac -dacRoot /reference/kotlin -output " + outDir
 }
 
+func (d *Droiddoc) collectMetalavaCompatibilityCheckFlags(ctx android.ModuleContext,
+	implicits *android.Paths) string {
+	var flags string
+	if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() {
+		apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file),
+			"check_api.current.api_file")
+		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file),
+			"check_api.current_removed_api_file")
+
+		*implicits = append(*implicits, apiFile)
+		*implicits = append(*implicits, removedApiFile)
+
+		flags = " --check-compatibility:api:current " + apiFile.String() +
+			" --check-compatibility:removed:current " + removedApiFile.String() + " "
+	}
+
+	if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
+		apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
+			"check_api.last_released.api_file")
+		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
+			"check_api.last_released.removed_api_file")
+
+		*implicits = append(*implicits, apiFile)
+		*implicits = append(*implicits, removedApiFile)
+
+		flags = flags + " --check-compatibility:api:released " + apiFile.String() +
+			" --check-compatibility:removed:released " + removedApiFile.String() + " "
+	}
+
+	return flags
+}
+
 func (d *Droiddoc) transformMetalava(ctx android.ModuleContext, implicits android.Paths,
 	implicitOutputs android.WritablePaths, outDir, docStubsDir, javaVersion,
 	bootclasspathArgs, classpathArgs, opts string) {
@@ -1067,7 +1100,7 @@
 	checkApiClasspath classpath, msg, opts string, output android.WritablePath) {
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        apiCheck,
-		Description: "Check API",
+		Description: "Doclava Check API",
 		Output:      output,
 		Inputs:      nil,
 		Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile},
@@ -1126,6 +1159,7 @@
 	flags.doclavaStubsFlags, flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs)
 	if Bool(d.properties.Metalava_enabled) {
 		flags.metalavaAnnotationsFlags = d.collectMetalavaAnnotationsFlags(ctx, &implicits, &implicitOutputs)
+		flags.metalavaCompatibilityCheckFlags = d.collectMetalavaCompatibilityCheckFlags(ctx, &implicits)
 		outDir := android.PathForModuleOut(ctx, "out").String()
 		docStubsDir := android.PathForModuleOut(ctx, "docStubsDir").String()
 		// TODO(nanzhang): Add a Soong property to handle documentation args.
@@ -1135,7 +1169,8 @@
 					flags.dokkaClasspathArgs, outDir, docStubsDir)
 				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
-						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaAnnotationsFlags+" "+flags.metalavaCompatibilityCheckFlags+" "+
+						strings.Split(flags.args, "--generate-documentation")[0]+
 						flags.metalavaDokkaFlags+" "+strings.Split(flags.args, "--generate-documentation")[1])
 			} else {
 				flags.metalavaJavadocFlags = d.collectMetalavaJavadocFlags(
@@ -1143,14 +1178,16 @@
 				flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
 				d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 					flags.bootClasspathArgs, flags.classpathArgs, flags.metalavaStubsFlags+
-						flags.metalavaAnnotationsFlags+" "+strings.Split(flags.args, "--generate-documentation")[0]+
+						flags.metalavaAnnotationsFlags+" "+flags.metalavaCompatibilityCheckFlags+" "+
+						strings.Split(flags.args, "--generate-documentation")[0]+
 						flags.metalavaJavadocFlags+flags.doclavaDocsFlags+
 						" "+strings.Split(flags.args, "--generate-documentation")[1])
 			}
 		} else {
 			d.transformMetalava(ctx, implicits, implicitOutputs, outDir, docStubsDir, javaVersion,
 				flags.bootClasspathArgs, flags.classpathArgs,
-				flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.args)
+				flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+" "+
+					flags.metalavaCompatibilityCheckFlags+flags.args)
 		}
 	} else {
 		flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava)
@@ -1180,11 +1217,6 @@
 					`      you will need approval.\n`+
 					`******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args),
 				d.checkCurrentApiTimestamp)
-		} else {
-			// TODO(nanzhang): Refactor below when Metalava support API check.
-			if d.apiFile == nil || d.removedApiFile == nil {
-				ctx.ModuleErrorf("api_filename and removed_api_filename properties cannot be empty for API check!")
-			}
 		}
 
 		d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp")
@@ -1192,19 +1224,21 @@
 	}
 
 	if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() {
-		d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
-
 		apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file),
 			"check_api.last_released.api_file")
 		removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file),
 			"check_api.last_released.removed_api_file")
 
-		d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
-			`\n******************************\n`+
-				`You have tried to change the API from what has been previously released in\n`+
-				`an SDK.  Please fix the errors listed above.\n`+
-				`******************************\n`, String(d.properties.Check_api.Last_released.Args),
-			d.checkLastReleasedApiTimestamp)
+		if !Bool(d.properties.Metalava_enabled) {
+			d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp")
+
+			d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath,
+				`\n******************************\n`+
+					`You have tried to change the API from what has been previously released in\n`+
+					`an SDK.  Please fix the errors listed above.\n`+
+					`******************************\n`, String(d.properties.Check_api.Last_released.Args),
+				d.checkLastReleasedApiTimestamp)
+		}
 	}
 }