Fix flattened apex install dir

This fixes the bug: flattened apex is installed under
/system/apex/<soong module name> not /system/apex/<apex name>.

Flattened apexes can be seen as pre-activated under /system/apex, which
is bind-mount to /apex. Therefore, install dir for flattend apex should
be the same with the activation point(or mountpoint) of non-flattened apex.

When apex_name: is set, it should be used as its name instead of name:.

This change also emits makevar APEX_FILE_CONTEXTS_INFOS which is list of
pairs(<apex_name>:<file_contexts>) and is used by sepolicy to modify
file_contexts files for flattened apexes properly.

Bug: 123314817
Bug: 142300241
Test: add a test apex module(foo) with apex_name(foobar)
Test: OVERRIDE_TARGET_FLATTEN_APEX=true m foo
Test: see if the apex is installed correctly(/system/apex/foobar)
Test: see if the file_contexts for foo is correctly modified
Change-Id: I97a07de5cc772cd1d91e95ae059d282038028916
diff --git a/apex/apex.go b/apex/apex.go
index 000792a..b2d34d2 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -187,6 +187,12 @@
 		ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
 	})
 	android.PostDepsMutators(RegisterPostDepsMutators)
+
+	android.RegisterMakeVarsProvider(pctx, func(ctx android.MakeVarsContext) {
+		apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+		sort.Strings(*apexFileContextsInfos)
+		ctx.Strict("APEX_FILE_CONTEXTS_INFOS", strings.Join(*apexFileContextsInfos, " "))
+	})
 }
 
 func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -273,14 +279,40 @@
 func apexMutator(mctx android.BottomUpMutatorContext) {
 	if am, ok := mctx.Module().(android.ApexModule); ok && am.CanHaveApexVariants() {
 		am.CreateApexVariations(mctx)
-	} else if _, ok := mctx.Module().(*apexBundle); ok {
+	} else if a, ok := mctx.Module().(*apexBundle); ok {
 		// apex bundle itself is mutated so that it and its modules have same
 		// apex variant.
 		apexBundleName := mctx.ModuleName()
 		mctx.CreateVariations(apexBundleName)
+
+		// collects APEX list
+		if mctx.Device() && a.installable() {
+			addApexFileContextsInfos(mctx, a)
+		}
 	}
 }
 
+var (
+	apexFileContextsInfosKey   = android.NewOnceKey("apexFileContextsInfosKey")
+	apexFileContextsInfosMutex sync.Mutex
+)
+
+func apexFileContextsInfos(config android.Config) *[]string {
+	return config.Once(apexFileContextsInfosKey, func() interface{} {
+		return &[]string{}
+	}).(*[]string)
+}
+
+func addApexFileContextsInfos(ctx android.BaseModuleContext, a *apexBundle) {
+	apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+	fileContextsName := proptools.StringDefault(a.properties.File_contexts, ctx.ModuleName())
+
+	apexFileContextsInfosMutex.Lock()
+	defer apexFileContextsInfosMutex.Unlock()
+	apexFileContextsInfos := apexFileContextsInfos(ctx.Config())
+	*apexFileContextsInfos = append(*apexFileContextsInfos, apexName+":"+fileContextsName)
+}
+
 func apexFlattenedMutator(mctx android.BottomUpMutatorContext) {
 	if ab, ok := mctx.Module().(*apexBundle); ok {
 		if !mctx.Config().FlattenApex() || mctx.Config().UnbundledBuild() {
@@ -1240,7 +1272,8 @@
 	// 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}
-	a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", factx.ModuleName())
+	apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
+	a.flattenedOutput = android.PathForModuleInstall(&factx, "apex", apexName)
 
 	if a.apexTypes.zip() {
 		a.buildUnflattenedApex(ctx, zipApex)
@@ -1540,8 +1573,9 @@
 		a.filesInfo = append(a.filesInfo, apexFile{copiedPubkey, ctx.ModuleName() + ".apex_pubkey", ".", etc, nil, nil})
 
 		if ctx.Config().FlattenApex() {
+			apexName := proptools.StringDefault(a.properties.Apex_name, ctx.ModuleName())
 			for _, fi := range a.filesInfo {
-				dir := filepath.Join("apex", ctx.ModuleName(), fi.installDir)
+				dir := filepath.Join("apex", apexName, fi.installDir)
 				target := ctx.InstallFile(android.PathForModuleInstall(ctx, dir), fi.builtFile.Base(), fi.builtFile)
 				for _, sym := range fi.symlinks {
 					ctx.InstallSymlink(android.PathForModuleInstall(ctx, dir), sym, target)
@@ -1572,7 +1606,7 @@
 		}}
 }
 
-func (a *apexBundle) androidMkForFiles(w io.Writer, name, moduleDir string, apexType apexPackaging) []string {
+func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string, apexType apexPackaging) []string {
 	moduleNames := []string{}
 
 	for _, fi := range a.filesInfo {
@@ -1596,12 +1630,11 @@
 		fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 		fmt.Fprintln(w, "LOCAL_MODULE :=", fi.moduleName+suffix)
 		// /apex/<apex_name>/{lib|framework|...}
-		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex",
-			proptools.StringDefault(a.properties.Apex_name, name), fi.installDir)
+		pathWhenActivated := filepath.Join("$(PRODUCT_OUT)", "apex", apexName, fi.installDir)
 		if a.properties.Flattened && apexType.image() {
 			// /system/apex/<name>/{lib|framework|...}
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", filepath.Join(a.installDir.ToMakePath().String(),
-				name, fi.installDir))
+				apexName, fi.installDir))
 			if !a.isFlattenedVariant() {
 				fmt.Fprintln(w, "LOCAL_SOONG_SYMBOL_PATH :=", pathWhenActivated)
 			}
@@ -1681,7 +1714,8 @@
 		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
 			moduleNames := []string{}
 			if a.installable() {
-				moduleNames = a.androidMkForFiles(w, name, moduleDir, apexType)
+				apexName := proptools.StringDefault(a.properties.Apex_name, name)
+				moduleNames = a.androidMkForFiles(w, apexName, moduleDir, apexType)
 			}
 
 			if a.isFlattenedVariant() {