Support including apk inside an apex

New property "apps" is added to APEX soong module. This property
configure a list of APKs to package inside APEX payload. For each
android_app module package it's APK into /app/$(android_app module Name)
directory.

Bug: 139906763
Test: m -j
Change-Id: Ic6655f211951af08097c76e157a07ebc52425718
diff --git a/apex/apex.go b/apex/apex.go
index f8eca8e..13e9cb9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -142,6 +142,7 @@
 	keyTag         = dependencyTag{name: "key"}
 	certificateTag = dependencyTag{name: "certificate"}
 	usesTag        = dependencyTag{name: "uses"}
+	androidAppTag  = dependencyTag{name: "androidApp"}
 )
 
 var (
@@ -333,6 +334,9 @@
 
 	// A txt file containing list of files that are whitelisted to be included in this APEX.
 	Whitelisted_files *string
+
+	// List of APKs to package inside APEX
+	Apps []string
 }
 
 type apexTargetBundleProperties struct {
@@ -367,6 +371,7 @@
 	goBinary
 	javaSharedLib
 	nativeTest
+	app
 )
 
 type apexPackaging int
@@ -431,6 +436,8 @@
 		return "JAVA_LIBRARIES"
 	case nativeTest:
 		return "NATIVE_TESTS"
+	case app:
+		return "APPS"
 	default:
 		panic(fmt.Errorf("unknown class %d", class))
 	}
@@ -633,6 +640,10 @@
 		{Mutator: "arch", Variation: "android_common"},
 	}, javaLibTag, a.properties.Java_libs...)
 
+	ctx.AddFarVariationDependencies([]blueprint.Variation{
+		{Mutator: "arch", Variation: "android_common"},
+	}, androidAppTag, a.properties.Apps...)
+
 	if String(a.properties.Key) == "" {
 		ctx.ModuleErrorf("key is missing")
 		return
@@ -813,6 +824,12 @@
 	return
 }
 
+func getCopyManifestForAndroidApp(app *java.AndroidApp, pkgName string) (fileToCopy android.Path, dirInApex string) {
+	dirInApex = filepath.Join("app", pkgName)
+	fileToCopy = app.OutputFile()
+	return
+}
+
 // Context "decorator", overriding the InstallBypassMake method to always reply `true`.
 type flattenedApexContext struct {
 	android.ModuleContext
@@ -977,6 +994,14 @@
 				if prebuilt, ok := child.(*Prebuilt); ok && prebuilt.isForceDisabled() {
 					a.prebuiltFileToDelete = prebuilt.InstallFilename()
 				}
+			case androidAppTag:
+				if ap, ok := child.(*java.AndroidApp); ok {
+					fileToCopy, dirInApex := getCopyManifestForAndroidApp(ap, ctx.DeviceConfig().OverridePackageNameFor(depName))
+					filesInfo = append(filesInfo, apexFile{fileToCopy, depName, dirInApex, app, ap, nil})
+					return true
+				} else {
+					ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
+				}
 			}
 		} else {
 			// indirect dependencies
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 8de4cef..e2d85ae 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -103,6 +103,7 @@
 	ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory))
 	ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
 	ctx.RegisterModuleType("java_import", android.ModuleFactoryAdaptor(java.ImportFactory))
+	ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(java.AndroidAppFactory))
 
 	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
 		ctx.BottomUp("prebuilts", android.PrebuiltMutator).Parallel()
@@ -210,31 +211,33 @@
 		"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
 		"system/sepolicy/apex/otherapex-file_contexts":      nil,
 		"system/sepolicy/apex/commonapex-file_contexts":     nil,
-		"mylib.cpp":                            nil,
-		"mylib_common.cpp":                     nil,
-		"mytest.cpp":                           nil,
-		"mytest1.cpp":                          nil,
-		"mytest2.cpp":                          nil,
-		"mytest3.cpp":                          nil,
-		"myprebuilt":                           nil,
-		"my_include":                           nil,
-		"foo/bar/MyClass.java":                 nil,
-		"prebuilt.jar":                         nil,
-		"vendor/foo/devkeys/test.x509.pem":     nil,
-		"vendor/foo/devkeys/test.pk8":          nil,
-		"testkey.x509.pem":                     nil,
-		"testkey.pk8":                          nil,
-		"testkey.override.x509.pem":            nil,
-		"testkey.override.pk8":                 nil,
-		"vendor/foo/devkeys/testkey.avbpubkey": nil,
-		"vendor/foo/devkeys/testkey.pem":       nil,
-		"NOTICE":                               nil,
-		"custom_notice":                        nil,
-		"testkey2.avbpubkey":                   nil,
-		"testkey2.pem":                         nil,
-		"myapex-arm64.apex":                    nil,
-		"myapex-arm.apex":                      nil,
-		"frameworks/base/api/current.txt":      nil,
+		"mylib.cpp":                                  nil,
+		"mylib_common.cpp":                           nil,
+		"mytest.cpp":                                 nil,
+		"mytest1.cpp":                                nil,
+		"mytest2.cpp":                                nil,
+		"mytest3.cpp":                                nil,
+		"myprebuilt":                                 nil,
+		"my_include":                                 nil,
+		"foo/bar/MyClass.java":                       nil,
+		"prebuilt.jar":                               nil,
+		"vendor/foo/devkeys/test.x509.pem":           nil,
+		"vendor/foo/devkeys/test.pk8":                nil,
+		"testkey.x509.pem":                           nil,
+		"testkey.pk8":                                nil,
+		"testkey.override.x509.pem":                  nil,
+		"testkey.override.pk8":                       nil,
+		"vendor/foo/devkeys/testkey.avbpubkey":       nil,
+		"vendor/foo/devkeys/testkey.pem":             nil,
+		"NOTICE":                                     nil,
+		"custom_notice":                              nil,
+		"testkey2.avbpubkey":                         nil,
+		"testkey2.pem":                               nil,
+		"myapex-arm64.apex":                          nil,
+		"myapex-arm.apex":                            nil,
+		"frameworks/base/api/current.txt":            nil,
+		"build/make/core/proguard.flags":             nil,
+		"build/make/core/proguard_basic_keeps.flags": nil,
 	})
 
 	return ctx, config
@@ -1977,6 +1980,38 @@
 	`)
 }
 
+func TestApexWithApps(t *testing.T) {
+	ctx, _ := testApex(t, `
+		apex {
+			name: "myapex",
+			key: "myapex.key",
+			apps: [
+				"AppFoo",
+			],
+		}
+
+		apex_key {
+			name: "myapex.key",
+			public_key: "testkey.avbpubkey",
+			private_key: "testkey.pem",
+		}
+
+		android_app {
+			name: "AppFoo",
+			srcs: ["foo/bar/MyClass.java"],
+			sdk_version: "none",
+			system_modules: "none",
+		}
+	`)
+
+	module := ctx.ModuleForTests("myapex", "android_common_myapex")
+	apexRule := module.Rule("apexRule")
+	copyCmds := apexRule.Args["copy_commands"]
+
+	ensureContains(t, copyCmds, "image.apex/app/AppFoo/AppFoo.apk")
+
+}
+
 func TestMain(m *testing.M) {
 	run := func() int {
 		setUp()
diff --git a/java/app.go b/java/app.go
index 0af89fd..d00c4c0 100644
--- a/java/app.go
+++ b/java/app.go
@@ -139,6 +139,10 @@
 	return nil
 }
 
+func (a *AndroidApp) OutputFile() android.Path {
+	return a.outputFile
+}
+
 var _ AndroidLibraryDependency = (*AndroidApp)(nil)
 
 type Certificate struct {