Merge "Don't enforce <uses-library> checks if dexpreopt for apps is disabled."
diff --git a/apex/apex.go b/apex/apex.go
index 66c598c..80d9615 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -93,8 +93,14 @@
 	Multilib apexMultilibProperties
 
 	// List of boot images that are embedded inside this APEX bundle.
+	//
+	// deprecated: Use Bootclasspath_fragments
+	// TODO(b/177892522): Remove after has been replaced by Bootclasspath_fragments
 	Boot_images []string
 
+	// List of bootclasspath fragments that are embedded inside this APEX bundle.
+	Bootclasspath_fragments []string
+
 	// List of java libraries that are embedded inside this APEX bundle.
 	Java_libs []string
 
@@ -748,6 +754,7 @@
 	// Common-arch dependencies come next
 	commonVariation := ctx.Config().AndroidCommonTarget.Variations()
 	ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Boot_images...)
+	ctx.AddFarVariationDependencies(commonVariation, bootImageTag, a.properties.Bootclasspath_fragments...)
 	ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
 	ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
 	ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 91b45fc..debeee8 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -160,24 +160,29 @@
 	android.AssertTrimmedStringEquals(t, "invalid paths for "+moduleName, expectedBootImageFiles, strings.Join(allPaths, "\n"))
 }
 
-func TestBootImageInApex(t *testing.T) {
+func TestBootImageInArtApex(t *testing.T) {
 	result := android.GroupFixturePreparers(
 		prepareForTestWithBootImage,
-		prepareForTestWithMyapex,
-		// Configure some libraries in the framework boot image.
-		dexpreopt.FixtureSetBootJars("platform:foo", "platform:bar"),
+		prepareForTestWithArtApex,
+
+		// Configure some libraries in the art boot image.
+		dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
 	).RunTestWithBp(t, `
 		apex {
-			name: "myapex",
-			key: "myapex.key",
+			name: "com.android.art",
+			key: "com.android.art.key",
 			boot_images: [
 				"mybootimage",
 			],
+			java_libs: [
+				"foo",
+				"bar",
+			],
 			updatable: false,
 		}
 
 		apex_key {
-			name: "myapex.key",
+			name: "com.android.art.key",
 			public_key: "testkey.avbpubkey",
 			private_key: "testkey.pem",
 		}
@@ -186,52 +191,123 @@
 			name: "foo",
 			srcs: ["b.java"],
 			installable: true,
+			apex_available: [
+				"com.android.art",
+			],
 		}
 
 		java_library {
 			name: "bar",
 			srcs: ["b.java"],
 			installable: true,
+			apex_available: [
+				"com.android.art",
+			],
 		}
 
 		boot_image {
 			name: "mybootimage",
-			image_name: "boot",
+			image_name: "art",
 			apex_available: [
-				"myapex",
+				"com.android.art",
 			],
 		}
 
 		// Make sure that a preferred prebuilt doesn't affect the apex.
 		prebuilt_boot_image {
 			name: "mybootimage",
-			image_name: "boot",
+			image_name: "art",
 			prefer: true,
 			apex_available: [
-				"myapex",
+				"com.android.art",
 			],
 		}
 	`)
 
-	ensureExactContents(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
+	ensureExactContents(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+		"javalib/arm/boot.art",
+		"javalib/arm/boot.oat",
+		"javalib/arm/boot.vdex",
 		"javalib/arm/boot-bar.art",
 		"javalib/arm/boot-bar.oat",
 		"javalib/arm/boot-bar.vdex",
-		"javalib/arm/boot-foo.art",
-		"javalib/arm/boot-foo.oat",
-		"javalib/arm/boot-foo.vdex",
+		"javalib/arm64/boot.art",
+		"javalib/arm64/boot.oat",
+		"javalib/arm64/boot.vdex",
 		"javalib/arm64/boot-bar.art",
 		"javalib/arm64/boot-bar.oat",
 		"javalib/arm64/boot-bar.vdex",
-		"javalib/arm64/boot-foo.art",
-		"javalib/arm64/boot-foo.oat",
-		"javalib/arm64/boot-foo.vdex",
+		"javalib/bar.jar",
+		"javalib/foo.jar",
 	})
 
-	java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex_image", []string{
-		`myapex.key`,
+	java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art_image", []string{
+		`bar`,
+		`com.android.art.key`,
+		`foo`,
 		`mybootimage`,
 	})
 }
 
+func TestBootImageInPrebuiltArtApex(t *testing.T) {
+	result := android.GroupFixturePreparers(
+		prepareForTestWithBootImage,
+		prepareForTestWithArtApex,
+
+		android.FixtureMergeMockFs(android.MockFS{
+			"com.android.art-arm64.apex": nil,
+			"com.android.art-arm.apex":   nil,
+		}),
+
+		// Configure some libraries in the art boot image.
+		dexpreopt.FixtureSetArtBootJars("com.android.art:foo", "com.android.art:bar"),
+	).RunTestWithBp(t, `
+		prebuilt_apex {
+			name: "com.android.art",
+			arch: {
+				arm64: {
+					src: "com.android.art-arm64.apex",
+				},
+				arm: {
+					src: "com.android.art-arm.apex",
+				},
+			},
+			exported_java_libs: ["foo", "bar"],
+		}
+
+		java_import {
+			name: "foo",
+			jars: ["foo.jar"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		java_import {
+			name: "bar",
+			jars: ["bar.jar"],
+			apex_available: [
+				"com.android.art",
+			],
+		}
+
+		prebuilt_boot_image {
+			name: "mybootimage",
+			image_name: "art",
+			apex_available: [
+				"com.android.art",
+			],
+		}
+	`)
+
+	java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common", []string{
+		`prebuilt_bar`,
+		`prebuilt_foo`,
+	})
+
+	java.CheckModuleDependencies(t, result.TestContext, "mybootimage", "android_common", []string{
+		`dex2oatd`,
+	})
+}
+
 // TODO(b/177892522) - add test for host apex.
diff --git a/java/boot_image.go b/java/boot_image.go
index a14940d..8fb893f 100644
--- a/java/boot_image.go
+++ b/java/boot_image.go
@@ -27,24 +27,36 @@
 func init() {
 	RegisterBootImageBuildComponents(android.InitRegistrationContext)
 
+	// TODO(b/177892522): Remove after has been replaced by bootclasspath_fragments
 	android.RegisterSdkMemberType(&bootImageMemberType{
 		SdkMemberTypeBase: android.SdkMemberTypeBase{
 			PropertyName: "boot_images",
 			SupportsSdk:  true,
 		},
 	})
+
+	android.RegisterSdkMemberType(&bootImageMemberType{
+		SdkMemberTypeBase: android.SdkMemberTypeBase{
+			PropertyName: "bootclasspath_fragments",
+			SupportsSdk:  true,
+		},
+	})
 }
 
 func RegisterBootImageBuildComponents(ctx android.RegistrationContext) {
+	// TODO(b/177892522): Remove after has been replaced by bootclasspath_fragment
 	ctx.RegisterModuleType("boot_image", bootImageFactory)
 	ctx.RegisterModuleType("prebuilt_boot_image", prebuiltBootImageFactory)
+
+	ctx.RegisterModuleType("bootclasspath_fragment", bootImageFactory)
+	ctx.RegisterModuleType("prebuilt_bootclasspath_fragment", prebuiltBootImageFactory)
 }
 
 type bootImageProperties struct {
 	// The name of the image this represents.
 	//
 	// Must be one of "art" or "boot".
-	Image_name string
+	Image_name *string
 }
 
 type BootImageModule struct {
@@ -127,14 +139,8 @@
 	// GenerateSingletonBuildActions method as it cannot create it for itself.
 	dexpreopt.GetGlobalSoongConfig(ctx)
 
-	// Get a map of the image configs that are supported.
-	imageConfigs := genBootImageConfigs(ctx)
-
-	// Retrieve the config for this image.
-	imageName := b.properties.Image_name
-	imageConfig := imageConfigs[imageName]
+	imageConfig := b.getImageConfig(ctx)
 	if imageConfig == nil {
-		ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
 		return
 	}
 
@@ -145,6 +151,25 @@
 	ctx.SetProvider(BootImageInfoProvider, info)
 }
 
+func (b *BootImageModule) getImageConfig(ctx android.EarlyModuleContext) *bootImageConfig {
+	// Get a map of the image configs that are supported.
+	imageConfigs := genBootImageConfigs(ctx)
+
+	// Retrieve the config for this image.
+	imageNamePtr := b.properties.Image_name
+	if imageNamePtr == nil {
+		return nil
+	}
+
+	imageName := *imageNamePtr
+	imageConfig := imageConfigs[imageName]
+	if imageConfig == nil {
+		ctx.PropertyErrorf("image_name", "Unknown image name %q, expected one of %s", imageName, strings.Join(android.SortedStringKeys(imageConfigs), ", "))
+		return nil
+	}
+	return imageConfig
+}
+
 type bootImageMemberType struct {
 	android.SdkMemberTypeBase
 }
@@ -159,7 +184,11 @@
 }
 
 func (b *bootImageMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
-	return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
+	if b.PropertyName == "boot_images" {
+		return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_boot_image")
+	} else {
+		return ctx.SnapshotBuilder().AddPrebuiltModule(member, "prebuilt_bootclasspath_fragment")
+	}
 }
 
 func (b *bootImageMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
@@ -169,7 +198,7 @@
 type bootImageSdkMemberProperties struct {
 	android.SdkMemberPropertiesBase
 
-	Image_name string
+	Image_name *string
 }
 
 func (b *bootImageSdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
@@ -179,8 +208,8 @@
 }
 
 func (b *bootImageSdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
-	if b.Image_name != "" {
-		propertySet.AddProperty("image_name", b.Image_name)
+	if b.Image_name != nil {
+		propertySet.AddProperty("image_name", *b.Image_name)
 	}
 }
 
diff --git a/java/boot_image_test.go b/java/boot_image_test.go
index 65e590d..37906ff 100644
--- a/java/boot_image_test.go
+++ b/java/boot_image_test.go
@@ -16,25 +16,51 @@
 
 import (
 	"testing"
+
+	"android/soong/android"
+	"android/soong/dexpreopt"
 )
 
 // Contains some simple tests for boot_image logic, additional tests can be found in
 // apex/boot_image_test.go as the ART boot image requires modules from the ART apex.
 
+var prepareForTestWithBootImage = android.GroupFixturePreparers(
+	PrepareForTestWithJavaDefaultModules,
+	dexpreopt.PrepareForTestByEnablingDexpreopt,
+)
+
 func TestUnknownBootImage(t *testing.T) {
-	testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", `
-		boot_image {
-			name: "unknown-boot-image",
-			image_name: "unknown",
-		}
-`)
+	prepareForTestWithBootImage.
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+			`\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+		RunTestWithBp(t, `
+			boot_image {
+				name: "unknown-boot-image",
+				image_name: "unknown",
+			}
+		`)
+}
+
+func TestUnknownBootclasspathFragmentImageName(t *testing.T) {
+	prepareForTestWithBootImage.
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+			`\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+		RunTestWithBp(t, `
+			bootclasspath_fragment {
+				name: "unknown-boot-image",
+				image_name: "unknown",
+			}
+		`)
 }
 
 func TestUnknownPrebuiltBootImage(t *testing.T) {
-	testJavaError(t, "image_name: Unknown image name \\\"unknown\\\", expected one of art, boot", `
-		prebuilt_boot_image {
-			name: "unknown-boot-image",
-			image_name: "unknown",
-		}
-`)
+	prepareForTestWithBootImage.
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+			`\Qimage_name: Unknown image name "unknown", expected one of art, boot\E`)).
+		RunTestWithBp(t, `
+			prebuilt_boot_image {
+				name: "unknown-boot-image",
+				image_name: "unknown",
+			}
+		`)
 }
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index ff548e5..da80a47 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -27,7 +27,11 @@
 
 func init() {
 	pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
-	android.RegisterModuleType("linker_config", linkerConfigFactory)
+	registerLinkerConfigBuildComponent(android.InitRegistrationContext)
+}
+
+func registerLinkerConfigBuildComponent(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("linker_config", linkerConfigFactory)
 }
 
 type linkerConfigProperties struct {
diff --git a/linkerconfig/linkerconfig_test.go b/linkerconfig/linkerconfig_test.go
index 8eed4b5a4..939e4bb 100644
--- a/linkerconfig/linkerconfig_test.go
+++ b/linkerconfig/linkerconfig_test.go
@@ -15,65 +15,29 @@
 package linkerconfig
 
 import (
-	"android/soong/android"
-	"io/ioutil"
 	"os"
 	"reflect"
 	"testing"
+
+	"android/soong/android"
 )
 
-var buildDir string
-
-func setUp() {
-	var err error
-	buildDir, err = ioutil.TempDir("", "soong_etc_test")
-	if err != nil {
-		panic(err)
-	}
-}
-
-func tearDown() {
-	os.RemoveAll(buildDir)
-}
-
 func TestMain(m *testing.M) {
-	run := func() int {
-		setUp()
-		defer tearDown()
-
-		return m.Run()
-	}
-
-	os.Exit(run())
+	os.Exit(m.Run())
 }
 
-func testContext(t *testing.T, bp string) *android.TestContext {
-	t.Helper()
-
-	fs := map[string][]byte{
-		"linker.config.json": nil,
-	}
-
-	config := android.TestArchConfig(buildDir, nil, bp, fs)
-
-	ctx := android.NewTestArchContext(config)
-	ctx.RegisterModuleType("linker_config", linkerConfigFactory)
-	ctx.Register()
-
-	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
-	android.FailIfErrored(t, errs)
-	_, errs = ctx.PrepareBuildActions(config)
-	android.FailIfErrored(t, errs)
-
-	return ctx
-}
+var prepareForLinkerConfigTest = android.GroupFixturePreparers(
+	android.PrepareForTestWithAndroidBuildComponents,
+	android.FixtureRegisterWithContext(registerLinkerConfigBuildComponent),
+	android.FixtureAddFile("linker.config.json", nil),
+)
 
 func TestBaseLinkerConfig(t *testing.T) {
-	ctx := testContext(t, `
-	linker_config {
-		name: "linker-config-base",
-		src: "linker.config.json",
-	}
+	result := prepareForLinkerConfigTest.RunTestWithBp(t, `
+		linker_config {
+			name: "linker-config-base",
+			src: "linker.config.json",
+		}
 	`)
 
 	expected := map[string][]string{
@@ -82,13 +46,13 @@
 		"LOCAL_INSTALLED_MODULE_STEM": {"linker.config.pb"},
 	}
 
-	p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+	p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
 
 	if p.outputFilePath.Base() != "linker.config.pb" {
 		t.Errorf("expected linker.config.pb, got %q", p.outputFilePath.Base())
 	}
 
-	entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
+	entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)[0]
 	for k, expectedValue := range expected {
 		if value, ok := entries.EntryMap[k]; ok {
 			if !reflect.DeepEqual(value, expectedValue) {
@@ -105,18 +69,18 @@
 }
 
 func TestUninstallableLinkerConfig(t *testing.T) {
-	ctx := testContext(t, `
-	linker_config {
-		name: "linker-config-base",
-		src: "linker.config.json",
-		installable: false,
-	}
+	result := prepareForLinkerConfigTest.RunTestWithBp(t, `
+		linker_config {
+			name: "linker-config-base",
+			src: "linker.config.json",
+			installable: false,
+		}
 	`)
 
 	expected := []string{"true"}
 
-	p := ctx.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
-	entries := android.AndroidMkEntriesForTest(t, ctx, p)[0]
+	p := result.ModuleForTests("linker-config-base", "android_arm64_armv8-a").Module().(*linkerConfig)
+	entries := android.AndroidMkEntriesForTest(t, result.TestContext, p)[0]
 	if value, ok := entries.EntryMap["LOCAL_UNINSTALLABLE_MODULE"]; ok {
 		if !reflect.DeepEqual(value, expected) {
 			t.Errorf("LOCAL_UNINSTALLABLE_MODULE is expected to be true but %s", value)