Add android_library.package_name

If the only reason that an android_library needs a manifest file is to
specify the package name, that can be specified in the Android.bp file.

Bug: b/307962763
Test: Manual, TH
Change-Id: Ifa778b77be8e86c963f0dd854f83b5768326eef6
diff --git a/java/aar.go b/java/aar.go
index f608d4e..33d96db 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -108,6 +108,9 @@
 
 	// Names of aconfig_declarations modules that specify aconfig flags that the module depends on.
 	Flags_packages []string
+
+	// The package name of this app. May not be used if `manifest` or `additional_manifests` are provided.
+	Package_name proptools.Configurable[string]
 }
 
 type aapt struct {
@@ -452,9 +455,21 @@
 	opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)
 
 	// App manifest file
+	packageNameProp := a.aaptProperties.Package_name.Get(ctx)
 	var manifestFilePath android.Path
 	if opts.manifestForAapt != nil {
 		manifestFilePath = opts.manifestForAapt
+	} else if a.isLibrary && packageNameProp.IsPresent() && a.aaptProperties.Manifest == nil && a.aaptProperties.Additional_manifests == nil {
+		// If the only reason that a library needs a manifest file is to give the package name, allow them to do that in
+		// the module declaration.  If they are already supplying a manifest, then do not autogenerate a manifest file.
+		generatedManifestPath := android.PathForModuleOut(ctx, "GeneratedManifest.xml")
+		manifestString := `<?xml version="1.0" encoding="utf-8"?>
+<!-- Automatically generated by Soong. -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="` + packageNameProp.Get() + `" />
+`
+		android.WriteFileRule(ctx, generatedManifestPath, manifestString)
+		ctx.SetOutputFiles([]android.Path{generatedManifestPath}, ".gen_xml")
+		manifestFilePath = generatedManifestPath
 	} else {
 		manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
 		manifestFilePath = android.PathForModuleSrc(ctx, manifestFile)
@@ -975,6 +990,17 @@
 }
 
 func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	packageNameProp := a.aaptProperties.Package_name.Get(ctx)
+	if packageNameProp.IsPresent() {
+		if a.aaptProperties.Manifest != nil {
+			ctx.PropertyErrorf("package_name", "cannot be used with `manifest`")
+			return
+		}
+		if a.aaptProperties.Additional_manifests != nil {
+			ctx.PropertyErrorf("package_name", "cannot be used with `additional_manifests`")
+			return
+		}
+	}
 	a.aapt.isLibrary = true
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
 	if a.usesLibrary.shouldDisableDexpreopt {
diff --git a/java/aar_test.go b/java/aar_test.go
index 088ad6c..9c1524d 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -181,3 +181,29 @@
 	android.AssertStringEquals(t, "baz relative output path",
 		"baz.jar", bazOutputPaths[0].Rel())
 }
+
+func TestAndroidLibraryManifests(t *testing.T) {
+	t.Parallel()
+	result := android.GroupFixturePreparers(
+		PrepareForTestWithJavaDefaultModules,
+	).RunTestWithBp(t, `
+		android_library {
+			name: "foo",
+			package_name: "com.android.foo",
+			java_resources: ["foo.txt"],
+		}
+	`)
+
+	foo := result.ModuleForTests(t, "foo", "android_common")
+
+	fooOutputPaths := foo.OutputFiles(result.TestContext, t, "")
+
+	android.AssertPathsRelativeToTopEquals(t, "foo manifest path",
+		[]string{"out/soong/.intermediates/foo/android_common/GeneratedManifest.xml"},
+		foo.OutputFiles(result.TestContext, t, ".gen_xml"))
+	android.AssertPathsRelativeToTopEquals(t, "foo output path",
+		[]string{"out/soong/.intermediates/foo/android_common/withres/foo.jar"}, fooOutputPaths)
+
+	android.AssertStringEquals(t, "foo relative output path",
+		"foo.jar", fooOutputPaths[0].Rel())
+}