Merge "Add support for versioned stubs."
diff --git a/Android.bp b/Android.bp
index 5faefe6..1b93c0d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -77,6 +77,7 @@
         "android/neverallow_test.go",
         "android/paths_test.go",
         "android/prebuilt_test.go",
+        "android/prebuilt_etc_test.go",
         "android/util_test.go",
         "android/variable_test.go",
     ],
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index fbc9de2..cc1f846 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -37,6 +37,9 @@
 	// optional subdirectory under which this file is installed into
 	Sub_dir *string `android:"arch_variant"`
 
+	// optional name for the installed file. If unspecified, name of the module is used as the file name
+	Filename *string `android:"arch_variant"`
+
 	// Make this module available when building for recovery.
 	Recovery_available *bool
 
@@ -95,7 +98,11 @@
 
 func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
 	p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
-	p.outputFilePath = PathForModuleOut(ctx, ctx.ModuleName()).OutputPath
+	filename := String(p.properties.Filename)
+	if filename == "" {
+		filename = ctx.ModuleName()
+	}
+	p.outputFilePath = PathForModuleOut(ctx, filename).OutputPath
 	p.installDirPath = PathForModuleInstall(ctx, "etc", String(p.properties.Sub_dir))
 
 	// This ensures that outputFilePath has the same name as this module.
@@ -120,7 +127,7 @@
 			fmt.Fprintln(w, "LOCAL_MODULE_TAGS := optional")
 			fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", p.outputFilePath.String())
 			fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", "$(OUT_DIR)/"+p.installDirPath.RelPathString())
-			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", name)
+			fmt.Fprintln(w, "LOCAL_INSTALLED_MODULE_STEM :=", p.outputFilePath.Base())
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index 9244647..1ecdf79 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -91,3 +91,18 @@
 		t.Errorf("expected 1, got %#v", bar_variants)
 	}
 }
+
+func TestPrebuiltEtcOutputPath(t *testing.T) {
+	ctx := testPrebuiltEtc(t, `
+		prebuilt_etc {
+			name: "foo.conf",
+			src: "foo.conf",
+			filename: "foo.installed.conf",
+		}
+	`)
+
+	p := ctx.ModuleForTests("foo.conf", "android_common_core").Module().(*PrebuiltEtc)
+	if p.outputFilePath.Base() != "foo.installed.conf" {
+		t.Errorf("expected foo.installed.conf, got %q", p.outputFilePath.Base())
+	}
+}
diff --git a/apex/apex.go b/apex/apex.go
index 5390114..07a53b3 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -176,6 +176,39 @@
 
 	// Name of the apex_key module that provides the private key to sign APEX
 	Key *string
+
+	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
+		}
+		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
+		}
+		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
+		}
+		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
+		}
+	}
 }
 
 type apexBundle struct {
@@ -188,22 +221,83 @@
 	installDir android.OutputPath
 }
 
+func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
+	native_shared_libs []string, binaries []string, arch string) {
+	// Use *FarVariation* to be able to depend on modules having
+	// conflicting variations with this module. This is required since
+	// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
+	// for native shared libs.
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+		{Mutator: "link", Variation: "shared"},
+	}, sharedLibTag, native_shared_libs...)
+
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: arch},
+		{Mutator: "image", Variation: "core"},
+	}, executableTag, binaries...)
+}
+
 func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
-	for _, arch := range ctx.MultiTargets() {
-		// Use *FarVariation* to be able to depend on modules having
-		// conflicting variations with this module. This is required since
-		// arch variant of an APEX bundle is 'common' but it is 'arm' or 'arm64'
-		// for native shared libs.
+	targets := ctx.MultiTargets()
+	has32BitTarget := false
+	for _, target := range targets {
+		if target.Arch.ArchType.Multilib == "lib32" {
+			has32BitTarget = true
+		}
+	}
+	for i, target := range targets {
+		// When multilib.* is omitted for native_shared_libs, it implies
+		// multilib.both.
 		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
+			{Mutator: "arch", Variation: target.String()},
 			{Mutator: "image", Variation: "core"},
 			{Mutator: "link", Variation: "shared"},
 		}, sharedLibTag, a.properties.Native_shared_libs...)
 
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "arch", Variation: arch.String()},
-			{Mutator: "image", Variation: "core"},
-		}, executableTag, a.properties.Binaries...)
+		// Add native modules targetting both ABIs
+		addDependenciesForNativeModules(ctx,
+			a.properties.Multilib.Both.Native_shared_libs,
+			a.properties.Multilib.Both.Binaries, target.String())
+
+		if i == 0 {
+			// When multilib.* is omitted for binaries, it implies
+			// multilib.first.
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "arch", Variation: target.String()},
+				{Mutator: "image", Variation: "core"},
+			}, executableTag, a.properties.Binaries...)
+
+			// Add native modules targetting the first ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.First.Native_shared_libs,
+				a.properties.Multilib.First.Binaries, target.String())
+		}
+
+		switch target.Arch.ArchType.Multilib {
+		case "lib32":
+			// Add native modules targetting 32-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib32.Native_shared_libs,
+				a.properties.Multilib.Lib32.Binaries, target.String())
+
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Prefer32.Native_shared_libs,
+				a.properties.Multilib.Prefer32.Binaries, target.String())
+		case "lib64":
+			// Add native modules targetting 64-bit ABI
+			addDependenciesForNativeModules(ctx,
+				a.properties.Multilib.Lib64.Native_shared_libs,
+				a.properties.Multilib.Lib64.Binaries, target.String())
+
+			if !has32BitTarget {
+				addDependenciesForNativeModules(ctx,
+					a.properties.Multilib.Prefer32.Native_shared_libs,
+					a.properties.Multilib.Prefer32.Binaries, target.String())
+			}
+		}
+
 	}
 
 	ctx.AddFarVariationDependencies([]blueprint.Variation{
@@ -407,6 +501,10 @@
 func apexBundleFactory() android.Module {
 	module := &apexBundle{}
 	module.AddProperties(&module.properties)
+	module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase,
+		class android.OsClass) bool {
+		return class == android.Device && ctx.Config().DevicePrefer32BitExecutables()
+	})
 	android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
 	android.InitDefaultableModule(module)
 	return module