Merge "Use protoc-gen-javalite for java lite protos"
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index cc1f846..83c38db 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -44,6 +44,9 @@
 	Recovery_available *bool
 
 	InRecovery bool `blueprint:"mutated"`
+
+	// Whether this module is directly installable to one of the partitions. Default: true.
+	Installable *bool
 }
 
 type PrebuiltEtc struct {
@@ -96,6 +99,10 @@
 	return String(p.properties.Sub_dir)
 }
 
+func (p *PrebuiltEtc) Installable() bool {
+	return p.properties.Installable == nil || Bool(p.properties.Installable)
+}
+
 func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx ModuleContext) {
 	p.sourceFilePath = ctx.ExpandSource(String(p.properties.Src), "src")
 	filename := String(p.properties.Filename)
@@ -128,6 +135,7 @@
 			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 :=", p.outputFilePath.Base())
+			fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE :=", !p.Installable())
 			if p.additionalDependencies != nil {
 				fmt.Fprint(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=")
 				for _, path := range *p.additionalDependencies {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index fba38a2..e4904f2 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -1738,13 +1738,16 @@
 	ctx := testCc(t, `
 		cc_library_shared {
 			name: "libFoo",
+			srcs: ["foo.c"],
 			stubs: {
 				symbol_file: "foo.map.txt",
 				versions: ["1", "2", "3"],
 			},
 		}
+
 		cc_library_shared {
 			name: "libBar",
+			srcs: ["bar.c"],
 			shared_libs: ["libFoo#1"],
 		}`)
 
@@ -1786,4 +1789,11 @@
 	if !strings.Contains(libFlags, libFoo1StubPath) {
 		t.Errorf("%q is not found in %q", libFoo1StubPath, libFlags)
 	}
+
+	libBarCompileRule := ctx.ModuleForTests("libBar", "android_arm64_armv8-a_core_shared").Rule("cc")
+	cFlags := libBarCompileRule.Args["cFlags"]
+	libFoo1VersioningMacro := "-D__LIBFOO_API__=1"
+	if !strings.Contains(cFlags, libFoo1VersioningMacro) {
+		t.Errorf("%q is not found in %q", libFoo1VersioningMacro, cFlags)
+	}
 }
diff --git a/cc/library.go b/cc/library.go
index aafe365..975f325 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -15,7 +15,9 @@
 package cc
 
 import (
+	"regexp"
 	"strings"
+	"sync"
 
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/pathtools"
@@ -443,6 +445,8 @@
 	return name + library.MutatedProperties.VariantName
 }
 
+var versioningMacroNamesListMutex sync.Mutex
+
 func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) {
 	location := InstallInSystem
 	if library.baseLinker.sanitize.inSanitizerDir() {
@@ -453,6 +457,18 @@
 	// Let baseLinker know whether this variant is for stubs or not, so that
 	// it can omit things that are not required for linking stubs.
 	library.baseLinker.dynamicProperties.BuildStubs = library.buildStubs()
+
+	if library.buildStubs() {
+		macroNames := versioningMacroNamesList(ctx.Config())
+		myName := versioningMacroName(ctx.ModuleName())
+		versioningMacroNamesListMutex.Lock()
+		defer versioningMacroNamesListMutex.Unlock()
+		if (*macroNames)[myName] == "" {
+			(*macroNames)[myName] = ctx.ModuleName()
+		} else if (*macroNames)[myName] != ctx.ModuleName() {
+			ctx.ModuleErrorf("Macro name %q for versioning conflicts with macro name from module %q ", myName, (*macroNames)[myName])
+		}
+	}
 }
 
 func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
@@ -715,6 +731,10 @@
 		library.reuseExportedFlags = append(library.reuseExportedFlags, flags...)
 	}
 
+	if library.buildStubs() {
+		library.reexportFlags([]string{"-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion()})
+	}
+
 	return out
 }
 
@@ -823,6 +843,23 @@
 	return library.MutatedProperties.StubsVersion
 }
 
+func versioningMacroNamesList(config android.Config) *map[string]string {
+	return config.Once("versioningMacroNamesList", func() interface{} {
+		m := make(map[string]string)
+		return &m
+	}).(*map[string]string)
+}
+
+// alphanumeric and _ characters are preserved.
+// other characters are all converted to _
+var charsNotForMacro = regexp.MustCompile("[^a-zA-Z0-9_]+")
+
+func versioningMacroName(moduleName string) string {
+	macroName := charsNotForMacro.ReplaceAllString(moduleName, "_")
+	macroName = strings.ToUpper(moduleName)
+	return "__" + macroName + "_API__"
+}
+
 func NewLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
 	module := newModule(hod, android.MultilibBoth)
 
diff --git a/java/app_builder.go b/java/app_builder.go
index 476eb60..b0983bd 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -63,7 +63,7 @@
 	})
 
 func CreateAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
-	resJarFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
+	packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
 
 	unsignedApk := android.PathForModuleOut(ctx, "unsigned.apk")
 
@@ -71,7 +71,7 @@
 	if dexJarFile != nil {
 		inputs = append(inputs, dexJarFile)
 	}
-	inputs = append(inputs, resJarFile)
+	inputs = append(inputs, packageFile)
 	if jniJarFile != nil {
 		inputs = append(inputs, jniJarFile)
 	}
@@ -136,45 +136,65 @@
 
 var buildBundleModule = pctx.AndroidStaticRule("buildBundleModule",
 	blueprint.RuleParams{
-		Command: `${config.Zip2ZipCmd} -i ${in} -o ${out}.res.zip AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*" &&` +
-			`${config.Zip2ZipCmd} -i ${dexJar} -o ${out}.dex.zip "classes*.dex:dex/" && ` +
-			`${config.MergeZipsCmd} ${out} ${out}.res.zip ${out}.dex.zip ${jniJar} && ` +
-			`rm ${out}.res.zip ${out}.dex.zip`,
-		CommandDeps: []string{
-			"${config.Zip2ZipCmd}",
-			"${config.MergeZipsCmd}",
-		},
-	}, "dexJar", "jniJar")
+		Command:     `${config.MergeZipsCmd} ${out} ${in}`,
+		CommandDeps: []string{"${config.MergeZipsCmd}"},
+	})
+
+var bundleMungePackage = pctx.AndroidStaticRule("bundleMungePackage",
+	blueprint.RuleParams{
+		Command:     `${config.Zip2ZipCmd} -i ${in} -o ${out} AndroidManifest.xml:manifest/AndroidManifest.xml resources.pb "res/**/*" "assets/**/*"`,
+		CommandDeps: []string{"${config.Zip2ZipCmd}"},
+	})
+
+var bundleMungeDexJar = pctx.AndroidStaticRule("bundleMungeDexJar",
+	blueprint.RuleParams{
+		Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} "classes*.dex:dex/" && ` +
+			`${config.Zip2ZipCmd} -i ${in} -o ${resJar} -x "classes*.dex" "**/*:root/"`,
+		CommandDeps: []string{"${config.Zip2ZipCmd}"},
+	}, "resJar")
 
 // Builds an app into a module suitable for input to bundletool
 func BuildBundleModule(ctx android.ModuleContext, outputFile android.WritablePath,
-	resJarFile, jniJarFile, dexJarFile android.Path) {
+	packageFile, jniJarFile, dexJarFile android.Path) {
 
 	protoResJarFile := android.PathForModuleOut(ctx, "package-res.pb.apk")
-	aapt2Convert(ctx, protoResJarFile, resJarFile)
+	aapt2Convert(ctx, protoResJarFile, packageFile)
 
-	var deps android.Paths
-	var jniPath string
-	var dexPath string
+	var zips android.Paths
+
+	mungedPackage := android.PathForModuleOut(ctx, "bundle", "apk.zip")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        bundleMungePackage,
+		Input:       protoResJarFile,
+		Output:      mungedPackage,
+		Description: "bundle apk",
+	})
+	zips = append(zips, mungedPackage)
+
 	if dexJarFile != nil {
-		deps = append(deps, dexJarFile)
-		dexPath = dexJarFile.String()
+		mungedDexJar := android.PathForModuleOut(ctx, "bundle", "dex.zip")
+		mungedResJar := android.PathForModuleOut(ctx, "bundle", "res.zip")
+		ctx.Build(pctx, android.BuildParams{
+			Rule:           bundleMungeDexJar,
+			Input:          dexJarFile,
+			Output:         mungedDexJar,
+			ImplicitOutput: mungedResJar,
+			Description:    "bundle dex",
+			Args: map[string]string{
+				"resJar": mungedResJar.String(),
+			},
+		})
+		zips = append(zips, mungedDexJar, mungedResJar)
 	}
 	if jniJarFile != nil {
-		deps = append(deps, jniJarFile)
-		jniPath = jniJarFile.String()
+		zips = append(zips, jniJarFile)
 	}
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        buildBundleModule,
-		Implicits:   deps,
-		Input:       protoResJarFile,
+		Inputs:      zips,
 		Output:      outputFile,
 		Description: "bundle",
-		Args: map[string]string{
-			"dexJar": dexPath,
-			"jniJar": jniPath,
-		},
 	})
 }