Add filename property to android_app_import

Test: app_test.go
Bug: 137218697
Change-Id: If2b20a355bb6e9e8dbcd57347c0e2c6fa041a932
diff --git a/java/androidmk.go b/java/androidmk.go
index 90fdd0f..886c274 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -594,28 +594,23 @@
 	}
 }
 
-func (app *AndroidAppImport) AndroidMk() android.AndroidMkData {
-	return android.AndroidMkData{
+func (a *AndroidAppImport) AndroidMkEntries() android.AndroidMkEntries {
+	return android.AndroidMkEntries{
 		Class:      "APPS",
-		OutputFile: android.OptionalPathForPath(app.outputFile),
+		OutputFile: android.OptionalPathForPath(a.outputFile),
 		Include:    "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
-		Extra: []android.AndroidMkExtraFunc{
-			func(w io.Writer, outputFile android.Path) {
-				if Bool(app.properties.Privileged) {
-					fmt.Fprintln(w, "LOCAL_PRIVILEGED_MODULE := true")
-				}
-				if app.certificate != nil {
-					fmt.Fprintln(w, "LOCAL_CERTIFICATE :=", app.certificate.Pem.String())
-				} else {
-					fmt.Fprintln(w, "LOCAL_CERTIFICATE := PRESIGNED")
-				}
-				if len(app.properties.Overrides) > 0 {
-					fmt.Fprintln(w, "LOCAL_OVERRIDES_PACKAGES :=", strings.Join(app.properties.Overrides, " "))
-				}
-				if len(app.dexpreopter.builtInstalled) > 0 {
-					fmt.Fprintln(w, "LOCAL_SOONG_BUILT_INSTALLED :=", app.dexpreopter.builtInstalled)
-				}
-			},
+		AddCustomEntries: func(name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+			entries.SetBoolIfTrue("LOCAL_PRIVILEGED_MODULE", Bool(a.properties.Privileged))
+			if a.certificate != nil {
+				entries.SetString("LOCAL_CERTIFICATE", a.certificate.Pem.String())
+			} else {
+				entries.SetString("LOCAL_CERTIFICATE", "PRESIGNED")
+			}
+			entries.AddStrings("LOCAL_OVERRIDES_PACKAGES", a.properties.Overrides...)
+			if len(a.dexpreopter.builtInstalled) > 0 {
+				entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", a.dexpreopter.builtInstalled)
+			}
+			entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel())
 		},
 	}
 }
diff --git a/java/app.go b/java/app.go
index 3442658..ce4eb32 100644
--- a/java/app.go
+++ b/java/app.go
@@ -736,6 +736,8 @@
 	dexpreopter
 
 	usesLibrary usesLibrary
+
+	installPath android.OutputPath
 }
 
 type AndroidAppImportProperties struct {
@@ -761,6 +763,9 @@
 	// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
 	// from PRODUCT_PACKAGES.
 	Overrides []string
+
+	// Optional name for the installed app. If unspecified, it is derived from the module name.
+	Filename *string
 }
 
 // Chooses a source APK path to use based on the module and product specs.
@@ -913,7 +918,8 @@
 
 	// TODO: Optionally compress the output apk.
 
-	ctx.InstallFile(installDir, a.BaseModuleName()+".apk", a.outputFile)
+	a.installPath = ctx.InstallFile(installDir,
+		proptools.StringDefault(a.properties.Filename, a.BaseModuleName()+".apk"), a.outputFile)
 
 	// TODO: androidmk converter jni libs
 }
diff --git a/java/app_test.go b/java/app_test.go
index 32de019..f21d450 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -1182,6 +1182,53 @@
 	}
 }
 
+func TestAndroidAppImport_Filename(t *testing.T) {
+	ctx, config := testJava(t, `
+		android_app_import {
+			name: "foo",
+			apk: "prebuilts/apk/app.apk",
+			presigned: true,
+		}
+
+		android_app_import {
+			name: "bar",
+			apk: "prebuilts/apk/app.apk",
+			presigned: true,
+			filename: "bar_sample.apk"
+		}
+		`)
+
+	testCases := []struct {
+		name     string
+		expected string
+	}{
+		{
+			name:     "foo",
+			expected: "foo.apk",
+		},
+		{
+			name:     "bar",
+			expected: "bar_sample.apk",
+		},
+	}
+
+	for _, test := range testCases {
+		variant := ctx.ModuleForTests(test.name, "android_common")
+		if variant.MaybeOutput(test.expected).Rule == nil {
+			t.Errorf("can't find output named %q - all outputs: %v", test.expected, variant.AllOutputs())
+		}
+
+		a := variant.Module().(*AndroidAppImport)
+		expectedValues := []string{test.expected}
+		actualValues := android.AndroidMkEntriesForTest(
+			t, config, "", a).EntryMap["LOCAL_INSTALLED_MODULE_STEM"]
+		if !reflect.DeepEqual(actualValues, expectedValues) {
+			t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
+				actualValues, expectedValues)
+		}
+	}
+}
+
 func TestStl(t *testing.T) {
 	ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+`
 		cc_library {