Merge "analyze_bcpf: Explain why a package is split/single"
diff --git a/android/bazel.go b/android/bazel.go
index fafb68b..e3fb0a6 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -570,12 +570,9 @@
 		"art-script",     // depends on unconverted modules: dalvikvm, dex2oat
 		"dex2oat-script", // depends on unconverted modules: dex2oat
 
-		"prebuilt_car-ui-androidx-core-common",                               // b/224773339, genrule dependency creates an .aar, not a .jar
-		"prebuilt_art-module-host-exports_okhttp-norepackage@current",        // aosp/1999250, needs Jars (arch variant)
-		"prebuilt_conscrypt-unbundled",                                       // aosp/1999250, needs Jars (arch variant)
-		"prebuilt_conscrypt-module-host-exports_conscrypt-unbundled@current", // aosp/1999250, needs Jars (arch variant)
-		"prebuilt_platform-robolectric-4.4-prebuilt",                         // aosp/1999250, needs .aar support in Jars
-		"prebuilt_platform-robolectric-4.5.1-prebuilt",                       // aosp/1999250, needs .aar support in Jars
+		"prebuilt_car-ui-androidx-core-common",         // b/224773339, genrule dependency creates an .aar, not a .jar
+		"prebuilt_platform-robolectric-4.4-prebuilt",   // aosp/1999250, needs .aar support in Jars
+		"prebuilt_platform-robolectric-4.5.1-prebuilt", // aosp/1999250, needs .aar support in Jars
 	}
 
 	// Per-module denylist of cc_library modules to only generate the static
diff --git a/android/neverallow.go b/android/neverallow.go
index 6f9ae58..f87cebb 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -249,7 +249,7 @@
 			continue
 		}
 
-		if !n.appliesToProperties(ctx, properties) {
+		if !n.appliesToProperties(properties) {
 			continue
 		}
 
@@ -261,20 +261,12 @@
 			continue
 		}
 
-		if !n.appliesToBootclasspathJar(ctx) {
-			continue
-		}
-
 		ctx.ModuleErrorf("violates " + n.String())
 	}
 }
 
-type ValueMatcherContext interface {
-	Config() Config
-}
-
 type ValueMatcher interface {
-	Test(ValueMatcherContext, string) bool
+	Test(string) bool
 	String() string
 }
 
@@ -282,7 +274,7 @@
 	expected string
 }
 
-func (m *equalMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *equalMatcher) Test(value string) bool {
 	return m.expected == value
 }
 
@@ -293,7 +285,7 @@
 type anyMatcher struct {
 }
 
-func (m *anyMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *anyMatcher) Test(value string) bool {
 	return true
 }
 
@@ -307,7 +299,7 @@
 	prefix string
 }
 
-func (m *startsWithMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *startsWithMatcher) Test(value string) bool {
 	return strings.HasPrefix(value, m.prefix)
 }
 
@@ -319,7 +311,7 @@
 	re *regexp.Regexp
 }
 
-func (m *regexMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *regexMatcher) Test(value string) bool {
 	return m.re.MatchString(value)
 }
 
@@ -331,7 +323,7 @@
 	allowed []string
 }
 
-func (m *notInListMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *notInListMatcher) Test(value string) bool {
 	return !InList(value, m.allowed)
 }
 
@@ -341,7 +333,7 @@
 
 type isSetMatcher struct{}
 
-func (m *isSetMatcher) Test(ctx ValueMatcherContext, value string) bool {
+func (m *isSetMatcher) Test(value string) bool {
 	return value != ""
 }
 
@@ -351,19 +343,6 @@
 
 var isSetMatcherInstance = &isSetMatcher{}
 
-type sdkVersionMatcher struct {
-	condition   func(ctx ValueMatcherContext, spec SdkSpec) bool
-	description string
-}
-
-func (m *sdkVersionMatcher) Test(ctx ValueMatcherContext, value string) bool {
-	return m.condition(ctx, SdkSpecFromWithConfig(ctx.Config(), value))
-}
-
-func (m *sdkVersionMatcher) String() string {
-	return ".sdk-version(" + m.description + ")"
-}
-
 type ruleProperty struct {
 	fields  []string // e.x.: Vndk.Enabled
 	matcher ValueMatcher
@@ -397,8 +376,6 @@
 
 	NotModuleType(types ...string) Rule
 
-	BootclasspathJar() Rule
-
 	With(properties, value string) Rule
 
 	WithMatcher(properties string, matcher ValueMatcher) Rule
@@ -514,12 +491,6 @@
 	return r
 }
 
-// BootclasspathJar whether this rule only applies to Jars in the Bootclasspath
-func (r *rule) BootclasspathJar() Rule {
-	r.onlyBootclasspathJar = true
-	return r
-}
-
 func (r *rule) String() string {
 	s := []string{"neverallow requirements. Not allowed:"}
 	if len(r.paths) > 0 {
@@ -537,9 +508,6 @@
 	if len(r.osClasses) > 0 {
 		s = append(s, fmt.Sprintf("os class(es): %q", r.osClasses))
 	}
-	if r.onlyBootclasspathJar {
-		s = append(s, "in bootclasspath jar")
-	}
 	if len(r.unlessPaths) > 0 {
 		s = append(s, fmt.Sprintf("EXCEPT in dirs: %q", r.unlessPaths))
 	}
@@ -580,14 +548,6 @@
 	return matches
 }
 
-func (r *rule) appliesToBootclasspathJar(ctx BottomUpMutatorContext) bool {
-	if !r.onlyBootclasspathJar {
-		return true
-	}
-
-	return InList(ctx.ModuleName(), ctx.Config().BootJars())
-}
-
 func (r *rule) appliesToOsClass(osClass OsClass) bool {
 	if len(r.osClasses) == 0 {
 		return true
@@ -606,10 +566,9 @@
 	return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
 }
 
-func (r *rule) appliesToProperties(ctx ValueMatcherContext,
-	properties []interface{}) bool {
-	includeProps := hasAllProperties(ctx, properties, r.props)
-	excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
+func (r *rule) appliesToProperties(properties []interface{}) bool {
+	includeProps := hasAllProperties(properties, r.props)
+	excludeProps := hasAnyProperty(properties, r.unlessProps)
 	return includeProps && !excludeProps
 }
 
@@ -629,16 +588,6 @@
 	return &notInListMatcher{allowed}
 }
 
-func LessThanSdkVersion(sdk string) ValueMatcher {
-	return &sdkVersionMatcher{
-		condition: func(ctx ValueMatcherContext, spec SdkSpec) bool {
-			return spec.ApiLevel.LessThan(
-				SdkSpecFromWithConfig(ctx.Config(), sdk).ApiLevel)
-		},
-		description: "lessThan=" + sdk,
-	}
-}
-
 // assorted utils
 
 func cleanPaths(paths []string) []string {
@@ -657,28 +606,25 @@
 	return names
 }
 
-func hasAnyProperty(ctx ValueMatcherContext, properties []interface{},
-	props []ruleProperty) bool {
+func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
 	for _, v := range props {
-		if hasProperty(ctx, properties, v) {
+		if hasProperty(properties, v) {
 			return true
 		}
 	}
 	return false
 }
 
-func hasAllProperties(ctx ValueMatcherContext, properties []interface{},
-	props []ruleProperty) bool {
+func hasAllProperties(properties []interface{}, props []ruleProperty) bool {
 	for _, v := range props {
-		if !hasProperty(ctx, properties, v) {
+		if !hasProperty(properties, v) {
 			return false
 		}
 	}
 	return true
 }
 
-func hasProperty(ctx ValueMatcherContext, properties []interface{},
-	prop ruleProperty) bool {
+func hasProperty(properties []interface{}, prop ruleProperty) bool {
 	for _, propertyStruct := range properties {
 		propertiesValue := reflect.ValueOf(propertyStruct).Elem()
 		for _, v := range prop.fields {
@@ -692,7 +638,7 @@
 		}
 
 		check := func(value string) bool {
-			return prop.matcher.Test(ctx, value)
+			return prop.matcher.Test(value)
 		}
 
 		if matchValue(propertiesValue, check) {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 59016d4..8afe9e0 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -327,48 +327,6 @@
 			"Only boot images may be imported as a makefile goal.",
 		},
 	},
-	{
-		name: "min_sdk too low",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "min_sdk_too_low",
-					min_sdk_version: "30",
-				}`),
-		},
-		rules: []Rule{
-			NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
-		},
-		expectedErrors: []string{
-			"module \"min_sdk_too_low\": violates neverallow",
-		},
-	},
-	{
-		name: "min_sdk high enough",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "min_sdk_high_enough",
-					min_sdk_version: "31",
-				}`),
-		},
-		rules: []Rule{
-			NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
-		},
-	},
-	{
-		name: "current min_sdk high enough",
-		fs: map[string][]byte{
-			"Android.bp": []byte(`
-				java_library {
-					name: "current_min_sdk_high_enough",
-					min_sdk_version: "current",
-				}`),
-		},
-		rules: []Rule{
-			NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
-		},
-	},
 }
 
 var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -452,10 +410,9 @@
 }
 
 type mockJavaLibraryProperties struct {
-	Libs            []string
-	Min_sdk_version *string
-	Sdk_version     *string
-	Uncompress_dex  *bool
+	Libs           []string
+	Sdk_version    *string
+	Uncompress_dex *bool
 }
 
 type mockJavaLibraryModule struct {
diff --git a/apex/apex.go b/apex/apex.go
index cb88f02..2fe17da 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -3278,21 +3278,19 @@
 }
 
 func init() {
-	android.AddNeverAllowRules(createApexPermittedPackagesRules(qModulesPackages())...)
-	android.AddNeverAllowRules(createApexPermittedPackagesRules(rModulesPackages())...)
+	android.AddNeverAllowRules(createBcpPermittedPackagesRules(qBcpPackages())...)
+	android.AddNeverAllowRules(createBcpPermittedPackagesRules(rBcpPackages())...)
 }
 
-func createApexPermittedPackagesRules(modules_packages map[string][]string) []android.Rule {
-	rules := make([]android.Rule, 0, len(modules_packages))
-	for module_name, module_packages := range modules_packages {
+func createBcpPermittedPackagesRules(bcpPermittedPackages map[string][]string) []android.Rule {
+	rules := make([]android.Rule, 0, len(bcpPermittedPackages))
+	for jar, permittedPackages := range bcpPermittedPackages {
 		permittedPackagesRule := android.NeverAllow().
-			BootclasspathJar().
-			With("apex_available", module_name).
-			WithMatcher("permitted_packages", android.NotInList(module_packages)).
-			WithMatcher("min_sdk_version", android.LessThanSdkVersion("Tiramisu")).
-			Because("jars that are part of the " + module_name +
-				" module may only use these package prefixes: " + strings.Join(module_packages, ",") +
-				" with min_sdk < T. Please consider the following alternatives:\n" +
+			With("name", jar).
+			WithMatcher("permitted_packages", android.NotInList(permittedPackages)).
+			Because(jar +
+				" bootjar may only use these package prefixes: " + strings.Join(permittedPackages, ",") +
+				". Please consider the following alternatives:\n" +
 				"    1. If the offending code is from a statically linked library, consider " +
 				"removing that dependency and using an alternative already in the " +
 				"bootclasspath, or perhaps a shared library." +
@@ -3300,55 +3298,56 @@
 				"    3. Jarjar the offending code. Please be mindful of the potential system " +
 				"health implications of bundling that code, particularly if the offending jar " +
 				"is part of the bootclasspath.")
+
 		rules = append(rules, permittedPackagesRule)
 	}
 	return rules
 }
 
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on Q/R/S.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
 // Adding code to the bootclasspath in new packages will cause issues on module update.
-func qModulesPackages() map[string][]string {
+func qBcpPackages() map[string][]string {
 	return map[string][]string{
-		"com.android.conscrypt": []string{
+		"conscrypt": []string{
 			"android.net.ssl",
 			"com.android.org.conscrypt",
 		},
-		"com.android.media": []string{
+		"updatable-media": []string{
 			"android.media",
 		},
 	}
 }
 
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on R/S.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
 // Adding code to the bootclasspath in new packages will cause issues on module update.
-func rModulesPackages() map[string][]string {
+func rBcpPackages() map[string][]string {
 	return map[string][]string{
-		"com.android.mediaprovider": []string{
+		"framework-mediaprovider": []string{
 			"android.provider",
 		},
-		"com.android.permission": []string{
+		"framework-permission": []string{
 			"android.permission",
 			"android.app.role",
 			"com.android.permission",
 			"com.android.role",
 		},
-		"com.android.sdkext": []string{
+		"framework-sdkextensions": []string{
 			"android.os.ext",
 		},
-		"com.android.os.statsd": []string{
+		"framework-statsd": []string{
 			"android.app",
 			"android.os",
 			"android.util",
 			"com.android.internal.statsd",
 			"com.android.server.stats",
 		},
-		"com.android.wifi": []string{
+		"framework-wifi": []string{
 			"com.android.server.wifi",
 			"com.android.wifi.x",
 			"android.hardware.wifi",
 			"android.net.wifi",
 		},
-		"com.android.tethering": []string{
+		"framework-tethering": []string{
 			"android.net",
 		},
 	}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index ec815c4..5706a2c 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -7580,7 +7580,7 @@
 	})
 }
 
-func testApexPermittedPackagesRules(t *testing.T, errmsg, bp string, bootJars []string, rules []android.Rule) {
+func testBootJarPermittedPackagesRules(t *testing.T, errmsg, bp string, bootJars []string, rules []android.Rule) {
 	t.Helper()
 	bp += `
 	apex_key {
@@ -7619,11 +7619,11 @@
 
 func TestApexPermittedPackagesRules(t *testing.T) {
 	testcases := []struct {
-		name            string
-		expectedError   string
-		bp              string
-		bootJars        []string
-		modulesPackages map[string][]string
+		name                 string
+		expectedError        string
+		bp                   string
+		bootJars             []string
+		bcpPermittedPackages map[string][]string
 	}{
 
 		{
@@ -7637,7 +7637,6 @@
 					apex_available: ["myapex"],
 					sdk_version: "none",
 					system_modules: "none",
-					min_sdk_version: "30",
 				}
 				java_library {
 					name: "nonbcp_lib2",
@@ -7646,25 +7645,23 @@
 					permitted_packages: ["a.b"],
 					sdk_version: "none",
 					system_modules: "none",
-					min_sdk_version: "30",
 				}
 				apex {
 					name: "myapex",
-					min_sdk_version: "30",
 					key: "myapex.key",
 					java_libs: ["bcp_lib1", "nonbcp_lib2"],
 					updatable: false,
 				}`,
 			bootJars: []string{"bcp_lib1"},
-			modulesPackages: map[string][]string{
-				"myapex": []string{
+			bcpPermittedPackages: map[string][]string{
+				"bcp_lib1": []string{
 					"foo.bar",
 				},
 			},
 		},
 		{
-			name:          "Bootclasspath apex jar not satisfying allowed module packages on Q.",
-			expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only use these package prefixes: foo.bar with min_sdk < T. Please consider the following alternatives:\n    1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library.    2. Move the offending code into an allowed package.\n    3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
+			name:          "Bootclasspath apex jar not satisfying allowed module packages.",
+			expectedError: `(?s)module "bcp_lib2" .* which is restricted because bcp_lib2 bootjar may only use these package prefixes: foo.bar. Please consider the following alternatives:\n    1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library.    2. Move the offending code into an allowed package.\n    3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
 			bp: `
 				java_library {
 					name: "bcp_lib1",
@@ -7673,7 +7670,6 @@
 					permitted_packages: ["foo.bar"],
 					sdk_version: "none",
 					system_modules: "none",
-					min_sdk_version: "29",
 				}
 				java_library {
 					name: "bcp_lib2",
@@ -7682,102 +7678,67 @@
 					permitted_packages: ["foo.bar", "bar.baz"],
 					sdk_version: "none",
 					system_modules: "none",
-					min_sdk_version: "29",
 				}
 				apex {
 					name: "myapex",
-					min_sdk_version: "29",
 					key: "myapex.key",
 					java_libs: ["bcp_lib1", "bcp_lib2"],
 					updatable: false,
 				}
 			`,
 			bootJars: []string{"bcp_lib1", "bcp_lib2"},
-			modulesPackages: map[string][]string{
-				"myapex": []string{
+			bcpPermittedPackages: map[string][]string{
+				"bcp_lib1": []string{
+					"foo.bar",
+				},
+				"bcp_lib2": []string{
 					"foo.bar",
 				},
 			},
 		},
 		{
-			name:          "Bootclasspath apex jar not satisfying allowed module packages on R.",
-			expectedError: `(?s)module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only use these package prefixes: foo.bar with min_sdk < T. Please consider the following alternatives:\n    1. If the offending code is from a statically linked library, consider removing that dependency and using an alternative already in the bootclasspath, or perhaps a shared library.    2. Move the offending code into an allowed package.\n    3. Jarjar the offending code. Please be mindful of the potential system health implications of bundling that code, particularly if the offending jar is part of the bootclasspath.`,
-			bp: `
-				java_library {
-					name: "bcp_lib1",
-					srcs: ["lib1/src/*.java"],
-					apex_available: ["myapex"],
-					permitted_packages: ["foo.bar"],
-					sdk_version: "none",
-					system_modules: "none",
-					min_sdk_version: "30",
-				}
-				java_library {
-					name: "bcp_lib2",
-					srcs: ["lib2/src/*.java"],
-					apex_available: ["myapex"],
-					permitted_packages: ["foo.bar", "bar.baz"],
-					sdk_version: "none",
-					system_modules: "none",
-					min_sdk_version: "30",
-				}
-				apex {
-					name: "myapex",
-					min_sdk_version: "30",
-					key: "myapex.key",
-					java_libs: ["bcp_lib1", "bcp_lib2"],
-					updatable: false,
-				}
-			`,
-			bootJars: []string{"bcp_lib1", "bcp_lib2"},
-			modulesPackages: map[string][]string{
-				"myapex": []string{
-					"foo.bar",
-				},
-			},
-		},
-		{
-			name:          "Bootclasspath apex jar >= T not satisfying Q/R/S allowed module packages.",
+			name:          "Updateable Bootclasspath apex jar not satisfying allowed module packages.",
 			expectedError: "",
 			bp: `
 				java_library {
-					name: "bcp_lib1",
+					name: "bcp_lib_restricted",
 					srcs: ["lib1/src/*.java"],
 					apex_available: ["myapex"],
 					permitted_packages: ["foo.bar"],
 					sdk_version: "none",
+					min_sdk_version: "29",
 					system_modules: "none",
-					min_sdk_version: "current",
 				}
 				java_library {
-					name: "bcp_lib2",
+					name: "bcp_lib_unrestricted",
 					srcs: ["lib2/src/*.java"],
 					apex_available: ["myapex"],
 					permitted_packages: ["foo.bar", "bar.baz"],
 					sdk_version: "none",
+					min_sdk_version: "29",
 					system_modules: "none",
-					min_sdk_version: "current",
 				}
 				apex {
 					name: "myapex",
-					min_sdk_version: "current",
 					key: "myapex.key",
-					java_libs: ["bcp_lib1", "bcp_lib2"],
-					updatable: false,
+					java_libs: ["bcp_lib_restricted", "bcp_lib_unrestricted"],
+					updatable: true,
+					min_sdk_version: "29",
 				}
 			`,
 			bootJars: []string{"bcp_lib1", "bcp_lib2"},
-			modulesPackages: map[string][]string{
-				"myapex": []string{
+			bcpPermittedPackages: map[string][]string{
+				"bcp_lib1_non_updateable": []string{
 					"foo.bar",
 				},
+				// bcp_lib2_updateable has no entry here since updateable bcp can contain new packages - tracking via an allowlist is not necessary
 			},
 		},
 	}
 	for _, tc := range testcases {
 		t.Run(tc.name, func(t *testing.T) {
-			rules := createApexPermittedPackagesRules(tc.modulesPackages)
-			testApexPermittedPackagesRules(t, tc.expectedError, tc.bp, tc.bootJars, rules)
+			rules := createBcpPermittedPackagesRules(tc.bcpPermittedPackages)
+			testBootJarPermittedPackagesRules(t, tc.expectedError, tc.bp, tc.bootJars, rules)
 		})
 	}
 }
diff --git a/apex/builder.go b/apex/builder.go
index 50c8dd1..ea61e1a 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -617,10 +617,16 @@
 		}
 
 		// Create a NOTICE file, and embed it as an asset file in the APEX.
-		a.htmlGzNotice = android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
+		a.htmlGzNotice = android.PathForModuleOut(ctx, "NOTICE.html.gz")
 		android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, a.htmlGzNotice)
-		implicitInputs = append(implicitInputs, a.htmlGzNotice)
-		optFlags = append(optFlags, "--assets_dir "+filepath.Dir(a.htmlGzNotice.String()))
+		noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
+		builder := android.NewRuleBuilder(pctx, ctx)
+		builder.Command().Text("cp").
+			Input(a.htmlGzNotice).
+			Output(noticeAssetPath)
+		builder.Build("notice_dir", "Building notice dir")
+		implicitInputs = append(implicitInputs, noticeAssetPath)
+		optFlags = append(optFlags, "--assets_dir "+filepath.Dir(noticeAssetPath.String()))
 
 		if (moduleMinSdkVersion.GreaterThan(android.SdkVersion_Android10) && !a.shouldGenerateHashtree()) && !compressionEnabled {
 			// Apexes which are supposed to be installed in builtin dirs(/system, etc)
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
index 2f7211c..0b3191c 100644
--- a/bp2build/java_import_conversion_test.go
+++ b/bp2build/java_import_conversion_test.go
@@ -29,7 +29,7 @@
 func registerJavaImportModuleTypes(ctx android.RegistrationContext) {
 }
 
-func TestMinimalJavaImport(t *testing.T) {
+func TestJavaImportMinimal(t *testing.T) {
 	runJavaImportTestCase(t, bp2buildTestCase{
 		description:                "Java import - simple example",
 		moduleTypeUnderTest:        "java_import",
@@ -50,3 +50,36 @@
 			}),
 		}})
 }
+
+func TestJavaImportArchVariant(t *testing.T) {
+	runJavaImportTestCase(t, bp2buildTestCase{
+		description:                "Java import - simple example",
+		moduleTypeUnderTest:        "java_import",
+		moduleTypeUnderTestFactory: java.ImportFactory,
+		filesystem: map[string]string{
+			"import.jar": "",
+		},
+		blueprint: `
+java_import {
+        name: "example_import",
+		target: {
+			android: {
+				jars: ["android.jar"],
+			},
+			linux_glibc: {
+				jars: ["linux.jar"],
+			},
+		},
+        bazel_module: { bp2build_available: true },
+}
+`,
+		expectedBazelTargets: []string{
+			makeBazelTarget("java_import", "example_import", attrNameToString{
+				"jars": `select({
+        "//build/bazel/platforms/os:android": ["android.jar"],
+        "//build/bazel/platforms/os:linux": ["linux.jar"],
+        "//conditions:default": [],
+    })`,
+			}),
+		}})
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 8dda537..fad675a 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -214,7 +214,6 @@
 		// http://b/145211066
 		"-Wno-implicit-int-float-conversion",
 		// New warnings to be fixed after clang-r377782.
-		"-Wno-int-in-bool-context",          // http://b/148287349
 		"-Wno-sizeof-array-div",             // http://b/148815709
 		"-Wno-tautological-overlap-compare", // http://b/148815696
 		// New warnings to be fixed after clang-r383902.
@@ -287,8 +286,8 @@
 
 	// prebuilts/clang default settings.
 	ClangDefaultBase         = "prebuilts/clang/host"
-	ClangDefaultVersion      = "clang-r450784"
-	ClangDefaultShortVersion = "14.0.3"
+	ClangDefaultVersion      = "clang-r450784b"
+	ClangDefaultShortVersion = "14.0.4"
 
 	// Directories with warnings from Android.bp files.
 	WarningAllowedProjects = []string{
diff --git a/java/app.go b/java/app.go
index 5b1daa4..21ee34e 100755
--- a/java/app.go
+++ b/java/app.go
@@ -586,10 +586,16 @@
 	}
 	a.onDeviceDir = android.InstallPathToOnDevicePath(ctx, a.installDir)
 
-	noticeFile := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
-	android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, noticeFile)
 	if Bool(a.appProperties.Embed_notices) || ctx.Config().IsEnvTrue("ALWAYS_EMBED_NOTICES") {
-		a.aapt.noticeFile = android.OptionalPathForPath(noticeFile)
+		noticeFile := android.PathForModuleOut(ctx, "NOTICE.html.gz")
+		android.BuildNoticeHtmlOutputFromLicenseMetadata(ctx, noticeFile)
+		noticeAssetPath := android.PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
+		builder := android.NewRuleBuilder(pctx, ctx)
+		builder.Command().Text("cp").
+			Input(noticeFile).
+			Output(noticeAssetPath)
+		builder.Build("notice_dir", "Building notice dir")
+		a.aapt.noticeFile = android.OptionalPathForPath(noticeAssetPath)
 	}
 
 	a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
diff --git a/java/java.go b/java/java.go
index 1b6e559..ecbbc32 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2218,8 +2218,16 @@
 
 // java_import bp2Build converter.
 func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
-	//TODO(b/209577426): Support multiple arch variants
-	jars := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, i.properties.Jars, []string(nil)))
+	var jars bazel.LabelListAttribute
+	archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
+	for axis, configToProps := range archVariantProps {
+		for config, _props := range configToProps {
+			if archProps, ok := _props.(*ImportProperties); ok {
+				archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil))
+				jars.SetSelectValue(axis, config, archJars)
+			}
+		}
+	}
 
 	attrs := &bazelJavaImportAttributes{
 		Jars: jars,
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index c881751..950a1e5 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -77,7 +77,7 @@
 	"addprefix":                            &simpleCallParser{name: baseName + ".addprefix", returnType: starlarkTypeList},
 	"addsuffix":                            &simpleCallParser{name: baseName + ".addsuffix", returnType: starlarkTypeList},
 	"copy-files":                           &simpleCallParser{name: baseName + ".copy_files", returnType: starlarkTypeList},
-	"dir":                                  &simpleCallParser{name: baseName + ".dir", returnType: starlarkTypeList},
+	"dir":                                  &simpleCallParser{name: baseName + ".dir", returnType: starlarkTypeString},
 	"dist-for-goals":                       &simpleCallParser{name: baseName + ".mkdist_for_goals", returnType: starlarkTypeVoid, addGlobals: true},
 	"enforce-product-packages-exist":       &simpleCallParser{name: baseName + ".enforce_product_packages_exist", returnType: starlarkTypeVoid},
 	"error":                                &makeControlFuncParser{name: baseName + ".mkerror"},
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 31739fa..2b447e3 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -793,7 +793,7 @@
 PRODUCT_COPY_FILES := $(addsuffix .sff, a b c)
 PRODUCT_NAME := $(word 1, $(subst ., ,$(TARGET_BOARD_PLATFORM)))
 $(info $(patsubst %.pub,$(PRODUCT_NAME)%,$(PRODUCT_ADB_KEYS)))
-$(info $(dir foo/bar))
+$(info $$(dir foo/bar): $(dir foo/bar))
 $(info $(firstword $(PRODUCT_COPY_FILES)))
 $(info $(lastword $(PRODUCT_COPY_FILES)))
 $(info $(dir $(lastword $(MAKEFILE_LIST))))
@@ -816,7 +816,7 @@
   cfg["PRODUCT_COPY_FILES"] = rblf.addsuffix(".sff", "a b c")
   cfg["PRODUCT_NAME"] = ((g.get("TARGET_BOARD_PLATFORM", "")).replace(".", " ")).split()[0]
   rblf.mkinfo("product.mk", rblf.mkpatsubst("%.pub", "%s%%" % cfg["PRODUCT_NAME"], g.get("PRODUCT_ADB_KEYS", "")))
-  rblf.mkinfo("product.mk", rblf.dir("foo/bar"))
+  rblf.mkinfo("product.mk", "$(dir foo/bar): %s" % rblf.dir("foo/bar"))
   rblf.mkinfo("product.mk", cfg["PRODUCT_COPY_FILES"][0])
   rblf.mkinfo("product.mk", cfg["PRODUCT_COPY_FILES"][-1])
   rblf.mkinfo("product.mk", rblf.dir("product.mk"))