Merge changes from topic "libc-bionic"

* changes:
  Give a knob to have apex ignore system-lib special cases
  Add limited target-specific configuration to apex.
diff --git a/apex/apex.go b/apex/apex.go
index aeeff78..f6daf9b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -177,6 +177,29 @@
 	}
 }
 
+type apexNativeDependencies struct {
+	// List of native libraries
+	Native_shared_libs []string
+	// List of native executables
+	Binaries []string
+}
+type apexMultilibProperties struct {
+	// Native dependencies whose compile_multilib is "first"
+	First apexNativeDependencies
+
+	// Native dependencies whose compile_multilib is "both"
+	Both apexNativeDependencies
+
+	// Native dependencies whose compile_multilib is "prefer32"
+	Prefer32 apexNativeDependencies
+
+	// Native dependencies whose compile_multilib is "32"
+	Lib32 apexNativeDependencies
+
+	// Native dependencies whose compile_multilib is "64"
+	Lib64 apexNativeDependencies
+}
+
 type apexBundleProperties struct {
 	// Json manifest file describing meta info of this APEX bundle. Default:
 	// "apex_manifest.json"
@@ -218,36 +241,29 @@
 	// Default is false.
 	Use_vendor *bool
 
-	Multilib struct {
-		First struct {
-			// List of native libraries whose compile_multilib is "first"
-			Native_shared_libs []string
-			// List of native executables whose compile_multilib is "first"
-			Binaries []string
+	// For telling the apex to ignore special handling for system libraries such as bionic. Default is false.
+	Ignore_system_library_special_case *bool
+
+	Multilib apexMultilibProperties
+}
+
+type apexTargetBundleProperties struct {
+	Target struct {
+		// Multilib properties only for android.
+		Android struct {
+			Multilib apexMultilibProperties
 		}
-		Both struct {
-			// List of native libraries whose compile_multilib is "both"
-			Native_shared_libs []string
-			// List of native executables whose compile_multilib is "both"
-			Binaries []string
+		// Multilib properties only for host.
+		Host struct {
+			Multilib apexMultilibProperties
 		}
-		Prefer32 struct {
-			// List of native libraries whose compile_multilib is "prefer32"
-			Native_shared_libs []string
-			// List of native executables whose compile_multilib is "prefer32"
-			Binaries []string
+		// Multilib properties only for host linux_bionic.
+		Linux_bionic struct {
+			Multilib apexMultilibProperties
 		}
-		Lib32 struct {
-			// List of native libraries whose compile_multilib is "32"
-			Native_shared_libs []string
-			// List of native executables whose compile_multilib is "32"
-			Binaries []string
-		}
-		Lib64 struct {
-			// List of native libraries whose compile_multilib is "64"
-			Native_shared_libs []string
-			// List of native executables whose compile_multilib is "64"
-			Binaries []string
+		// Multilib properties only for host linux_glibc.
+		Linux_glibc struct {
+			Multilib apexMultilibProperties
 		}
 	}
 }
@@ -339,7 +355,8 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 
-	properties apexBundleProperties
+	properties       apexBundleProperties
+	targetProperties apexTargetBundleProperties
 
 	apexTypes apexPackaging
 
@@ -372,9 +389,26 @@
 	}, executableTag, binaries...)
 }
 
+func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
+	if ctx.Os().Class == android.Device {
+		proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Android.Multilib, nil)
+	} else {
+		proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Host.Multilib, nil)
+		if ctx.Os().Bionic() {
+			proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_bionic.Multilib, nil)
+		} else {
+			proptools.AppendProperties(&a.properties.Multilib, &a.targetProperties.Target.Linux_glibc.Multilib, nil)
+		}
+	}
+}
+
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
+
 	targets := ctx.MultiTargets()
 	config := ctx.DeviceConfig()
+
+	a.combineProperties(ctx)
+
 	has32BitTarget := false
 	for _, target := range targets {
 		if target.Arch.ArchType.Multilib == "lib32" {
@@ -497,7 +531,7 @@
 	return android.InList(sanitizerName, globalSanitizerNames)
 }
 
-func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, dirInApex string) {
+func getCopyManifestForNativeLibrary(cc *cc.Module, handleSpecialLibs bool) (fileToCopy android.Path, dirInApex string) {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
 	switch cc.Arch().ArchType.Multilib {
@@ -509,18 +543,20 @@
 	if !cc.Arch().Native {
 		dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
 	}
-	switch cc.Name() {
-	case "libc", "libm", "libdl":
-		// Special case for bionic libs. This is to prevent the bionic libs
-		// from being included in the search path /apex/com.android.apex/lib.
-		// This exclusion is required because bionic libs in the runtime APEX
-		// are available via the legacy paths /system/lib/libc.so, etc. By the
-		// init process, the bionic libs in the APEX are bind-mounted to the
-		// legacy paths and thus will be loaded into the default linker namespace.
-		// If the bionic libs are directly in /apex/com.android.apex/lib then
-		// the same libs will be again loaded to the runtime linker namespace,
-		// which will result double loading of bionic libs that isn't supported.
-		dirInApex = filepath.Join(dirInApex, "bionic")
+	if handleSpecialLibs {
+		switch cc.Name() {
+		case "libc", "libm", "libdl":
+			// Special case for bionic libs. This is to prevent the bionic libs
+			// from being included in the search path /apex/com.android.apex/lib.
+			// This exclusion is required because bionic libs in the runtime APEX
+			// are available via the legacy paths /system/lib/libc.so, etc. By the
+			// init process, the bionic libs in the APEX are bind-mounted to the
+			// legacy paths and thus will be loaded into the default linker namespace.
+			// If the bionic libs are directly in /apex/com.android.apex/lib then
+			// the same libs will be again loaded to the runtime linker namespace,
+			// which will result double loading of bionic libs that isn't supported.
+			dirInApex = filepath.Join(dirInApex, "bionic")
+		}
 	}
 
 	fileToCopy = cc.OutputFile().Path()
@@ -563,6 +599,8 @@
 		return
 	}
 
+	handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
+
 	ctx.WalkDeps(func(child, parent android.Module) bool {
 		if _, ok := parent.(*apexBundle); ok {
 			// direct dependencies
@@ -571,7 +609,7 @@
 			switch depTag {
 			case sharedLibTag:
 				if cc, ok := child.(*cc.Module); ok {
-					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				} else {
@@ -639,7 +677,7 @@
 						return false
 					}
 					depName := ctx.OtherModuleName(child)
-					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc)
+					fileToCopy, dirInApex := getCopyManifestForNativeLibrary(cc, handleSpecialLibs)
 					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, nativeSharedLib, cc, nil})
 					return true
 				}
@@ -1028,6 +1066,7 @@
 		outputFiles: map[apexPackaging]android.WritablePath{},
 	}
 	module.AddProperties(&module.properties)
+	module.AddProperties(&module.targetProperties)
 	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
 		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
 	})
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 7ae49f6..9d33060 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -864,3 +864,83 @@
 	// Ensure that the include path of the header lib is exported to 'otherlib'
 	ensureContains(t, cFlags, "-Imy_include")
 }
+
+func TestApexWithTarget(t *testing.T) {
+	ctx := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			multilib: {
+				first: {
+					native_shared_libs: ["mylib_common"],
+				}
+			},
+			target: {
+				android: {
+					multilib: {
+						first: {
+							native_shared_libs: ["mylib"],
+						}
+					}
+				},
+				host: {
+					multilib: {
+						first: {
+							native_shared_libs: ["mylib2"],
+						}
+					}
+				}
+			}
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		cc_library {
+			name: "mylib",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+		}
+
+		cc_library {
+			name: "mylib_common",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			compile_multilib: "first",
+		}
+
+		cc_library {
+			name: "mylib2",
+			srcs: ["mylib.cpp"],
+			system_shared_libs: [],
+			stl: "none",
+			compile_multilib: "first",
+		}
+	`)
+
+	apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	// Ensure that main rule creates an output
+	ensureContains(t, apexRule.Output.String(), "myapex.apex.unsigned")
+
+	// Ensure that apex variant is created for the direct dep
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared_myapex")
+	ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared_myapex")
+
+	// Ensure that both direct and indirect deps are copied into apex
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
+	ensureContains(t, copyCmds, "image.apex/lib64/mylib_common.so")
+	ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
+
+	// Ensure that the platform variant ends with _core_shared
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common"), "android_arm64_armv8-a_core_shared")
+	ensureListContains(t, ctx.ModuleVariantsForTests("mylib2"), "android_arm64_armv8-a_core_shared")
+}