apex: emit file_contexts for flattened apex

Flattened APEXes are installed in /<partition>/apex/<name>, so its
file_contexts file should be amended accordingly.
For example, file_contexts of an apex "com.android.foo" with should be
modified by prepending actual install path to the path regex.

/bin/foo <sepolicy label>
=> /system/apex/com\.android\.foo/bin/foo <sepolicy label>

File_contexts file is emitted to "make" via LOCAL_FILE_CONTEXTS variable
for apex_manifest.pb module.

Make collects these files and use them to build file_contexts.bin.

Also removed global state which is used to keep the list of all
flattened apexes.

Bug: 166518492
Test: m file_contexts.bin
      check intermediate file_contexts.modules.tmp file
      in $OUT/obj/ETC/file_contexts.bin_intermediates/
Change-Id: I780370b6e576964a5c09f9477f3361f341dd576b
diff --git a/apex/builder.go b/apex/builder.go
index c5680ad..b835379 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -257,15 +257,34 @@
 
 	output := android.PathForModuleOut(ctx, "file_contexts")
 	rule := android.NewRuleBuilder()
-	// remove old file
-	rule.Command().Text("rm").FlagWithOutput("-f ", output)
-	// copy file_contexts
-	rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
-	// new line
-	rule.Command().Text("echo").Text(">>").Output(output)
-	// force-label /apex_manifest.pb and / as system_file so that apexd can read them
-	rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
-	rule.Command().Text("echo").Flag("/ u:object_r:system_file:s0").Text(">>").Output(output)
+
+	if a.properties.ApexType == imageApex {
+		// remove old file
+		rule.Command().Text("rm").FlagWithOutput("-f ", output)
+		// copy file_contexts
+		rule.Command().Text("cat").Input(fileContexts).Text(">>").Output(output)
+		// new line
+		rule.Command().Text("echo").Text(">>").Output(output)
+		// force-label /apex_manifest.pb and / as system_file so that apexd can read them
+		rule.Command().Text("echo").Flag("/apex_manifest\\\\.pb u:object_r:system_file:s0").Text(">>").Output(output)
+		rule.Command().Text("echo").Flag("/ u:object_r:system_file:s0").Text(">>").Output(output)
+	} else {
+		// For flattened apexes, install path should be prepended.
+		// File_contexts file should be emiited to make via LOCAL_FILE_CONTEXTS
+		// so that it can be merged into file_contexts.bin
+		apexPath := android.InstallPathToOnDevicePath(ctx, a.installDir.Join(ctx, a.Name()))
+		apexPath = strings.ReplaceAll(apexPath, ".", `\\.`)
+		// remove old file
+		rule.Command().Text("rm").FlagWithOutput("-f ", output)
+		// copy file_contexts
+		rule.Command().Text("awk").Text(`'/object_r/{printf("` + apexPath + `%s\n", $0)}'`).Input(fileContexts).Text(">").Output(output)
+		// new line
+		rule.Command().Text("echo").Text(">>").Output(output)
+		// force-label /apex_manifest.pb and / as system_file so that apexd can read them
+		rule.Command().Text("echo").Flag(apexPath + `/apex_manifest\\.pb u:object_r:system_file:s0`).Text(">>").Output(output)
+		rule.Command().Text("echo").Flag(apexPath + "/ u:object_r:system_file:s0").Text(">>").Output(output)
+	}
+
 	rule.Build(pctx, ctx, "file_contexts."+a.Name(), "Generate file_contexts")
 
 	a.fileContexts = output.OutputPath
@@ -687,14 +706,7 @@
 	// instead of `android.PathForOutput`) to return the correct path to the flattened
 	// APEX (as its contents is installed by Make, not Soong).
 	factx := flattenedApexContext{ctx}
-	apexBundleName := a.Name()
-	a.outputFile = android.PathForModuleInstall(&factx, "apex", apexBundleName)
-
-	if a.installable() {
-		installPath := android.PathForModuleInstall(ctx, "apex", apexBundleName)
-		devicePath := android.InstallPathToOnDevicePath(ctx, installPath)
-		addFlattenedFileContextsInfos(ctx, apexBundleName+":"+devicePath+":"+a.fileContexts.String())
-	}
+	a.outputFile = android.PathForModuleInstall(&factx, "apex", a.Name())
 	a.buildFilesInfo(ctx)
 }