Bp2Build converter for android_library_import and android_library.

Minor refactor of android_app converted to account for common attributes
between library and app.

Test: go test
Test: ../bazel/ci/bp2build.sh
Change-Id: I60b06eef6d2b9bc2d91f8b83522747ebbe76bbb6
Bug: 215230093
Bug: 215230095
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index b668042..b05c64b 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -169,6 +169,7 @@
 		"packages/apps/DevCamera":                                Bp2BuildDefaultTrue,
 		"packages/apps/HTMLViewer":                               Bp2BuildDefaultTrue,
 		"packages/apps/Protips":                                  Bp2BuildDefaultTrue,
+		"packages/apps/WallpaperPicker":                          Bp2BuildDefaultTrue,
 		"packages/modules/StatsD/lib/libstatssocket":             Bp2BuildDefaultTrueRecursively,
 		"packages/modules/adb":                                   Bp2BuildDefaultTrue,
 		"packages/modules/adb/apex":                              Bp2BuildDefaultTrue,
@@ -182,6 +183,8 @@
 		"packages/screensavers/Basic":                            Bp2BuildDefaultTrue,
 		"packages/services/Car/tests/SampleRearViewCamera":       Bp2BuildDefaultTrue,
 		"prebuilts/clang/host/linux-x86":                         Bp2BuildDefaultTrueRecursively,
+		"prebuilts/sdk/current/extras/app-toolkit":               Bp2BuildDefaultTrue,
+		"prebuilts/sdk/current/support":                          Bp2BuildDefaultTrue,
 		"prebuilts/tools/common/m2":                              Bp2BuildDefaultTrue,
 		"system/apex":                                            Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
 		"system/apex/apexer":                                     Bp2BuildDefaultTrue,
@@ -258,7 +261,6 @@
 
 		"packages/apps/Music":/* recursive = */ true,
 		"packages/apps/QuickSearchBox":/* recursive = */ true,
-		"packages/apps/WallpaperPicker":/* recursive = */ false,
 
 		"prebuilts/bazel":/* recursive = */ true,
 		"prebuilts/bundletool":/* recursive = */ true,
@@ -267,8 +269,6 @@
 		"prebuilts/jdk/jdk11":/* recursive = */ false,
 		"prebuilts/misc":/* recursive = */ false, // not recursive because we need bp2build converted build files in prebuilts/misc/common/asm
 		"prebuilts/sdk":/* recursive = */ false,
-		"prebuilts/sdk/current/extras/app-toolkit":/* recursive = */ false,
-		"prebuilts/sdk/current/support":/* recursive = */ false,
 		"prebuilts/sdk/tools":/* recursive = */ false,
 		"prebuilts/r8":/* recursive = */ false,
 	}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 07557d6..713ee09 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -34,6 +34,7 @@
         "soong-ui-metrics",
     ],
     testSrcs: [
+        "aar_conversion_test.go",
         "android_app_certificate_conversion_test.go",
         "android_app_conversion_test.go",
         "apex_conversion_test.go",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
new file mode 100644
index 0000000..8e7c2b5
--- /dev/null
+++ b/bp2build/aar_conversion_test.go
@@ -0,0 +1,138 @@
+// Copyright 2022 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package bp2build
+
+import (
+	"android/soong/android"
+	"android/soong/java"
+	"fmt"
+
+	"testing"
+)
+
+func TestConvertAndroidLibrary(t *testing.T) {
+	t.Helper()
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+		Description:                "Android Library - simple example",
+		ModuleTypeUnderTest:        "android_library",
+		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+		Filesystem: map[string]string{
+			"lib.java":                     "",
+			"arm.java":                     "",
+			"x86.java":                     "",
+			"res/res.png":                  "",
+			"manifest/AndroidManifest.xml": "",
+		},
+		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
+android_library {
+        name: "TestLib",
+        srcs: ["lib.java"],
+        arch: {
+			arm: {
+				srcs: ["arm.java"],
+			},
+			x86: {
+				srcs: ["x86.java"],
+			}
+		},
+        manifest: "manifest/AndroidManifest.xml",
+        static_libs: ["static_lib_dep"],
+        java_version: "7",
+}
+`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget(
+				"android_library",
+				"TestLib",
+				AttrNameToString{
+					"srcs": `["lib.java"] + select({
+        "//build/bazel/platforms/arch:arm": ["arm.java"],
+        "//build/bazel/platforms/arch:x86": ["x86.java"],
+        "//conditions:default": [],
+    })`,
+					"manifest":       `"manifest/AndroidManifest.xml"`,
+					"resource_files": `["res/res.png"]`,
+					"deps":           `[":static_lib_dep"]`,
+					"exports":        `[":static_lib_dep"]`,
+					"javacopts":      `["-source 1.7 -target 1.7"]`,
+				}),
+		}})
+}
+
+func TestConvertAndroidLibraryWithNoSources(t *testing.T) {
+	t.Helper()
+	RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
+		Description:                "Android Library - modules with deps must have sources",
+		ModuleTypeUnderTest:        "android_library",
+		ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
+		Filesystem: map[string]string{
+			"res/res.png":         "",
+			"AndroidManifest.xml": "",
+		},
+		Blueprint: simpleModuleDoNotConvertBp2build("android_library", "lib_dep") + `
+android_library {
+        name: "TestLib",
+        srcs: [],
+        manifest: "AndroidManifest.xml",
+        libs: ["lib_dep"],
+}
+`,
+		ExpectedErr:          fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
+		ExpectedBazelTargets: []string{},
+	})
+}
+
+func TestConvertAndroidLibraryImport(t *testing.T) {
+	t.Helper()
+	RunBp2BuildTestCase(
+		t,
+		func(ctx android.RegistrationContext) {
+			ctx.RegisterModuleType("android_library", java.AndroidLibraryFactory)
+		},
+		Bp2buildTestCase{
+			Description:                "Android Library Import",
+			ModuleTypeUnderTest:        "android_library_import",
+			ModuleTypeUnderTestFactory: java.AARImportFactory,
+			Filesystem: map[string]string{
+				"import.aar": "",
+			},
+			// Bazel's aar_import can only export *_import targets, so we expect
+			// only "static_import_dep" in exports, but both "static_lib_dep" and
+			// "static_import_dep" in deps
+			Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") +
+				simpleModuleDoNotConvertBp2build("android_library_import", "static_import_dep") + `
+android_library_import {
+        name: "TestImport",
+        aars: ["import.aar"],
+        static_libs: ["static_lib_dep", "static_import_dep"],
+}
+`,
+			ExpectedBazelTargets: []string{
+				makeBazelTarget(
+					"aar_import",
+					"TestImport",
+					AttrNameToString{
+						"aar": `"import.aar"`,
+						"deps": `[
+        ":static_lib_dep",
+        ":static_import_dep",
+    ]`,
+						"exports": `[":static_import_dep"]`,
+					},
+				),
+			},
+		},
+	)
+}
diff --git a/java/aar.go b/java/aar.go
index a59ecb8..d5996ba 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -21,6 +21,7 @@
 	"strings"
 
 	"android/soong/android"
+	"android/soong/bazel"
 	"android/soong/dexpreopt"
 
 	"github.com/google/blueprint"
@@ -490,6 +491,7 @@
 type AndroidLibrary struct {
 	Library
 	aapt
+	android.BazelModuleBase
 
 	androidLibraryProperties androidLibraryProperties
 
@@ -605,6 +607,7 @@
 
 	android.InitApexModule(module)
 	InitJavaModule(module, android.DeviceSupported)
+	android.InitBazelModule(module)
 	return module
 }
 
@@ -643,6 +646,7 @@
 	android.ModuleBase
 	android.DefaultableModuleBase
 	android.ApexModuleBase
+	android.BazelModuleBase
 	prebuilt android.Prebuilt
 
 	// Functionality common to Module and Import.
@@ -973,5 +977,96 @@
 	android.InitPrebuiltModule(module, &module.properties.Aars)
 	android.InitApexModule(module)
 	InitJavaModuleMultiTargets(module, android.DeviceSupported)
+	android.InitBazelModule(module)
 	return module
 }
+
+type bazelAapt struct {
+	Manifest       bazel.Label
+	Resource_files bazel.LabelListAttribute
+}
+
+type bazelAndroidLibrary struct {
+	*javaLibraryAttributes
+	*bazelAapt
+}
+
+type bazelAndroidLibraryImport struct {
+	Aar     bazel.Label
+	Deps    bazel.LabelListAttribute
+	Exports bazel.LabelListAttribute
+}
+
+func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) *bazelAapt {
+	manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
+
+	resourceFiles := bazel.LabelList{
+		Includes: []bazel.Label{},
+	}
+	for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
+		files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
+		resourceFiles.Includes = append(resourceFiles.Includes, files...)
+	}
+	return &bazelAapt{
+		android.BazelLabelForModuleSrcSingle(ctx, manifest),
+		bazel.MakeLabelListAttribute(resourceFiles),
+	}
+}
+
+func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{})
+	exportableStaticLibs := []string{}
+	// TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel.
+	for _, depName := range a.properties.Static_libs {
+		if dep, ok := ctx.ModuleFromName(depName); ok {
+			switch dep.(type) {
+			case *AARImport, *Import:
+				exportableStaticLibs = append(exportableStaticLibs, depName)
+			}
+		}
+	}
+	name := android.RemoveOptionalPrebuiltPrefix(a.Name())
+	deps := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(append(a.properties.Static_libs, a.properties.Libs...))))
+	exports := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(exportableStaticLibs))
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "aar_import",
+			Bzl_load_location: "@rules_android//rules:rules.bzl",
+		},
+		android.CommonAttributes{Name: name},
+		&bazelAndroidLibraryImport{
+			Aar:     aars.Includes[0],
+			Deps:    bazel.MakeLabelListAttribute(deps),
+			Exports: bazel.MakeLabelListAttribute(exports),
+		},
+	)
+
+}
+
+func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+	commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
+
+	deps := depLabels.Deps
+	if !commonAttrs.Srcs.IsEmpty() {
+		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
+	} else if !depLabels.Deps.IsEmpty() {
+		ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
+	}
+
+	ctx.CreateBazelTargetModule(
+		bazel.BazelTargetModuleProperties{
+			Rule_class:        "android_library",
+			Bzl_load_location: "@rules_android//rules:rules.bzl",
+		},
+		android.CommonAttributes{Name: a.Name()},
+		&bazelAndroidLibrary{
+			&javaLibraryAttributes{
+				javaCommonAttributes: commonAttrs,
+				Deps:                 deps,
+				Exports:              depLabels.StaticDeps,
+			},
+			a.convertAaptAttrsWithBp2Build(ctx),
+		},
+	)
+}
diff --git a/java/app.go b/java/app.go
index c369978..7b5efc7 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1444,10 +1444,9 @@
 
 type bazelAndroidAppAttributes struct {
 	*javaCommonAttributes
+	*bazelAapt
 	Deps             bazel.LabelListAttribute
-	Manifest         bazel.Label
 	Custom_package   *string
-	Resource_files   bazel.LabelListAttribute
 	Certificate      *bazel.Label
 	Certificate_name *string
 }
@@ -1457,23 +1456,9 @@
 	commonAttrs, depLabels := a.convertLibraryAttrsBp2Build(ctx)
 
 	deps := depLabels.Deps
-	if !commonAttrs.Srcs.IsEmpty() {
-		deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
-	} else if !deps.IsEmpty() || !depLabels.StaticDeps.IsEmpty() {
-		ctx.ModuleErrorf("android_app has dynamic or static dependencies but no sources." +
-			" Bazel does not allow direct dependencies without sources nor exported" +
-			" dependencies on android_binary rule.")
-	}
+	deps.Append(depLabels.StaticDeps)
 
-	manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
-
-	resourceFiles := bazel.LabelList{
-		Includes: []bazel.Label{},
-	}
-	for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
-		files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
-		resourceFiles.Includes = append(resourceFiles.Includes, files...)
-	}
+	aapt := a.convertAaptAttrsWithBp2Build(ctx)
 
 	var certificate *bazel.Label
 	certificateNamePtr := a.overridableAppProperties.Certificate
@@ -1484,14 +1469,12 @@
 		certificate = &c
 		certificateNamePtr = nil
 	}
-
 	attrs := &bazelAndroidAppAttributes{
 		commonAttrs,
+		aapt,
 		deps,
-		android.BazelLabelForModuleSrcSingle(ctx, manifest),
 		// TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
 		a.overridableAppProperties.Package_name,
-		bazel.MakeLabelListAttribute(resourceFiles),
 		certificate,
 		certificateNamePtr,
 	}
@@ -1500,7 +1483,6 @@
 		Rule_class:        "android_binary",
 		Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
 	}
-
 	ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: a.Name()}, attrs)
 
 }
diff --git a/java/java.go b/java/java.go
index f4ec04e..481c625 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2333,12 +2333,12 @@
 
 	var deps bazel.LabelList
 	if m.properties.Libs != nil {
-		deps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Libs))
+		deps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Libs))))
 	}
 
 	var staticDeps bazel.LabelList
 	if m.properties.Static_libs != nil {
-		staticDeps.Append(android.BazelLabelForModuleDeps(ctx, m.properties.Static_libs))
+		staticDeps.Append(android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(m.properties.Static_libs))))
 	}
 
 	protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])