Merge "Add system/logging/liblog."
diff --git a/android/config.go b/android/config.go
index 35403b8..23423b7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1665,8 +1665,9 @@
 	return ConfiguredJarList{apexes, jars}
 }
 
-// Filter keeps the entries if a jar appears in the given list of jars to keep; returns a new list.
-func (l *ConfiguredJarList) Filter(jarsToKeep []string) ConfiguredJarList {
+// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
+// and any remaining jars that are not on this list.
+func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
 	var apexes []string
 	var jars []string
 
@@ -1677,7 +1678,7 @@
 		}
 	}
 
-	return ConfiguredJarList{apexes, jars}
+	return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
 }
 
 // CopyOfJars returns a copy of the list of strings containing jar module name
diff --git a/android/module.go b/android/module.go
index b571f15..cc03418 100644
--- a/android/module.go
+++ b/android/module.go
@@ -986,10 +986,13 @@
 	// Device is built by default. Host and HostCross are not supported.
 	DeviceSupported = deviceSupported | deviceDefault
 
-	// Device is built by default. Host and HostCross are supported.
+	// By default, _only_ device variant is built. Device variant can be disabled with `device_supported: false`
+    // Host and HostCross are disabled by default and can be enabled with `host_supported: true`
 	HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
 
 	// Host, HostCross, and Device are built by default.
+    // Building Device can be disabled with `device_supported: false`
+    // Building Host and HostCross can be disabled with `host_supported: false`
 	HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
 		deviceSupported | deviceDefault
 
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index e2d8465..60f18bd 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -159,11 +159,6 @@
 			],
 		}
 
-		bootclasspath_fragment {
-			name: "non-apex-fragment",
-			contents: ["othersdklibrary"],
-		}
-
 		apex {
 			name: "otherapex",
 			key: "otherapex.key",
@@ -213,7 +208,6 @@
 	myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
 	myBar := result.Module("bar", "android_common_apex10000")
 
-	nonApexFragment := result.Module("non-apex-fragment", "android_common")
 	other := result.Module("othersdklibrary", "android_common_apex10000")
 
 	otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
@@ -253,15 +247,6 @@
 		assertElementsEquals(t, "elements", expectedElements, elements)
 	})
 
-	// Verify that CreateClasspathElements detects when a fragment does not have an associated apex.
-	t.Run("non apex fragment", func(t *testing.T) {
-		ctx := newCtx()
-		elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{nonApexFragment})
-		android.FailIfNoMatchingErrors(t, "fragment non-apex-fragment{.*} is not part of an apex", ctx.errs)
-		expectedElements := java.ClasspathElements{}
-		assertElementsEquals(t, "elements", expectedElements, elements)
-	})
-
 	// Verify that CreateClasspathElements detects when an apex has multiple fragments.
 	t.Run("multiple fragments for same apex", func(t *testing.T) {
 		ctx := newCtx()
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index e0421f6..513ddc0 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -543,3 +543,140 @@
 		"out/soong/target/product/test_device/system/etc/classpaths",
 	)
 }
+
+func TestBootJarNotInApex(t *testing.T) {
+	android.GroupFixturePreparers(
+		prepareForTestWithPlatformBootclasspath,
+		PrepareForTestWithApexBuildComponents,
+		prepareForTestWithMyapex,
+		java.FixtureConfigureApexBootJars("myapex:foo"),
+	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+		`dependency "foo" of "myplatform-bootclasspath" missing variant`)).
+		RunTestWithBp(t, `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				updatable: false,
+			}
+
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+
+			java_library {
+				name: "foo",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: [
+					"myapex",
+				],
+			}
+
+			bootclasspath_fragment {
+				name: "not-in-apex-fragment",
+				contents: [
+					"foo",
+				],
+			}
+
+			platform_bootclasspath {
+				name: "myplatform-bootclasspath",
+			}
+		`)
+}
+
+func TestBootFragmentNotInApex(t *testing.T) {
+	android.GroupFixturePreparers(
+		prepareForTestWithPlatformBootclasspath,
+		PrepareForTestWithApexBuildComponents,
+		prepareForTestWithMyapex,
+		java.FixtureConfigureApexBootJars("myapex:foo"),
+	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+		`library foo.*have no corresponding fragment.*`)).RunTestWithBp(t, `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				java_libs: ["foo"],
+				updatable: false,
+			}
+
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+
+			java_library {
+				name: "foo",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: ["myapex"],
+				permitted_packages: ["foo"],
+			}
+
+			bootclasspath_fragment {
+				name: "not-in-apex-fragment",
+				contents: ["foo"],
+			}
+
+			platform_bootclasspath {
+				name: "myplatform-bootclasspath",
+			}
+		`)
+}
+
+func TestNonBootJarInFragment(t *testing.T) {
+	android.GroupFixturePreparers(
+		prepareForTestWithPlatformBootclasspath,
+		PrepareForTestWithApexBuildComponents,
+		prepareForTestWithMyapex,
+		java.FixtureConfigureApexBootJars("myapex:foo"),
+	).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+		`in contents must also be declared in PRODUCT_APEX_BOOT_JARS`)).
+		RunTestWithBp(t, `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				bootclasspath_fragments: ["apex-fragment"],
+				updatable: false,
+			}
+
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+
+			java_library {
+				name: "foo",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: ["myapex"],
+				permitted_packages: ["foo"],
+			}
+
+			java_library {
+				name: "bar",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: ["myapex"],
+				permitted_packages: ["bar"],
+			}
+
+			bootclasspath_fragment {
+				name: "apex-fragment",
+				contents: ["foo", "bar"],
+				apex_available:[ "myapex" ],
+			}
+
+			platform_bootclasspath {
+				name: "myplatform-bootclasspath",
+				fragments: [{
+						apex: "myapex",
+						module:"apex-fragment",
+				}],
+			}
+		`)
+}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index a64c6f4..a8d5931 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -130,3 +130,54 @@
 		`mysystemserverclasspathfragment`,
 	})
 }
+
+func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) {
+	android.GroupFixturePreparers(
+		prepareForTestWithSystemserverclasspathFragment,
+		prepareForTestWithMyapex,
+		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+	).
+		ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+			`in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS`)).
+		RunTestWithBp(t, `
+			apex {
+				name: "myapex",
+				key: "myapex.key",
+				systemserverclasspath_fragments: [
+					"mysystemserverclasspathfragment",
+				],
+				updatable: false,
+			}
+
+			apex_key {
+				name: "myapex.key",
+				public_key: "testkey.avbpubkey",
+				private_key: "testkey.pem",
+			}
+
+			java_library {
+				name: "foo",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: ["myapex"],
+			}
+
+			java_library {
+				name: "bar",
+				srcs: ["b.java"],
+				installable: true,
+				apex_available: ["myapex"],
+			}
+
+			systemserverclasspath_fragment {
+				name: "mysystemserverclasspathfragment",
+				contents: [
+					"foo",
+					"bar",
+				],
+				apex_available: [
+					"myapex",
+				],
+			}
+		`)
+}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a64d474..f652a35 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -14,14 +14,20 @@
 
 package bp2build
 
+/*
+For shareable/common functionality for conversion from soong-module to build files
+for queryview/bp2build
+*/
+
 import (
-	"android/soong/android"
-	"android/soong/bazel"
 	"fmt"
 	"reflect"
 	"sort"
 	"strings"
 
+	"android/soong/android"
+	"android/soong/bazel"
+
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index bff192f..c840016 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -15,10 +15,10 @@
 package bp2build
 
 import (
+	"testing"
+
 	"android/soong/android"
 	"android/soong/cc"
-	"strings"
-	"testing"
 )
 
 const (
@@ -54,59 +54,6 @@
 	ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
 }
 
-func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
-	t.Helper()
-	dir := "."
-	filesystem := make(map[string][]byte)
-	toParse := []string{
-		"Android.bp",
-	}
-	for f, content := range tc.filesystem {
-		if strings.HasSuffix(f, "Android.bp") {
-			toParse = append(toParse, f)
-		}
-		filesystem[f] = []byte(content)
-	}
-	config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
-	ctx := android.NewTestContext(config)
-
-	registerModuleTypes(ctx)
-	ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
-	ctx.RegisterBp2BuildConfig(bp2buildConfig)
-	ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
-	ctx.RegisterForBazelConversion()
-
-	_, errs := ctx.ParseFileList(dir, toParse)
-	if errored(t, tc.description, errs) {
-		return
-	}
-	_, errs = ctx.ResolveDependencies(config)
-	if errored(t, tc.description, errs) {
-		return
-	}
-
-	checkDir := dir
-	if tc.dir != "" {
-		checkDir = tc.dir
-	}
-	codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
-	bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
-	if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
-		t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
-	} else {
-		for i, target := range bazelTargets {
-			if w, g := tc.expectedBazelTargets[i], target.content; w != g {
-				t.Errorf(
-					"%s: Expected generated Bazel target to be '%s', got '%s'",
-					tc.description,
-					w,
-					g,
-				)
-			}
-		}
-	}
-}
-
 func TestCcLibrarySimple(t *testing.T) {
 	runCcLibraryTestCase(t, bp2buildTestCase{
 		description:                        "cc_library - simple example",
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 712d0bd..ea2c10a 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -40,17 +40,6 @@
 }`
 )
 
-type bp2buildTestCase struct {
-	description                        string
-	moduleTypeUnderTest                string
-	moduleTypeUnderTestFactory         android.ModuleFactory
-	moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
-	blueprint                          string
-	expectedBazelTargets               []string
-	filesystem                         map[string]string
-	dir                                string
-}
-
 func TestCcLibraryHeadersLoadStatement(t *testing.T) {
 	testCases := []struct {
 		bazelTargets           BazelTargets
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 7bedf71..cf46322 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -3,17 +3,11 @@
 import (
 	"testing"
 
-	"android/soong/android"
 	"android/soong/python"
 )
 
-func runPythonTestCase(t *testing.T, tc bp2buildTestCase) {
-	t.Helper()
-	runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
 func TestPythonBinaryHostSimple(t *testing.T) {
-	runPythonTestCase(t, bp2buildTestCase{
+	runBp2BuildTestCaseSimple(t, bp2buildTestCase{
 		description:                        "simple python_binary_host converts to a native py_binary",
 		moduleTypeUnderTest:                "python_binary_host",
 		moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
@@ -49,7 +43,7 @@
 }
 
 func TestPythonBinaryHostPy2(t *testing.T) {
-	runPythonTestCase(t, bp2buildTestCase{
+	runBp2BuildTestCaseSimple(t, bp2buildTestCase{
 		description:                        "py2 python_binary_host",
 		moduleTypeUnderTest:                "python_binary_host",
 		moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
@@ -79,7 +73,7 @@
 }
 
 func TestPythonBinaryHostPy3(t *testing.T) {
-	runPythonTestCase(t, bp2buildTestCase{
+	runBp2BuildTestCaseSimple(t, bp2buildTestCase{
 		description:                        "py3 python_binary_host",
 		moduleTypeUnderTest:                "python_binary_host",
 		moduleTypeUnderTestFactory:         python.PythonBinaryHostFactory,
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 266b817..3a77d0e 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -1,6 +1,26 @@
+// Copyright 2021 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
 
+/*
+For shareable/common bp2build testing functionality and dumping ground for
+specific-but-shared functionality among tests in package
+*/
+
 import (
+	"strings"
 	"testing"
 
 	"android/soong/android"
@@ -16,6 +36,86 @@
 	buildDir string
 )
 
+func errored(t *testing.T, desc string, errs []error) bool {
+	t.Helper()
+	if len(errs) > 0 {
+		for _, err := range errs {
+			t.Errorf("%s: %s", desc, err)
+		}
+		return true
+	}
+	return false
+}
+
+func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
+	t.Helper()
+	runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+type bp2buildTestCase struct {
+	description                        string
+	moduleTypeUnderTest                string
+	moduleTypeUnderTestFactory         android.ModuleFactory
+	moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+	blueprint                          string
+	expectedBazelTargets               []string
+	filesystem                         map[string]string
+	dir                                string
+}
+
+func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
+	t.Helper()
+	dir := "."
+	filesystem := make(map[string][]byte)
+	toParse := []string{
+		"Android.bp",
+	}
+	for f, content := range tc.filesystem {
+		if strings.HasSuffix(f, "Android.bp") {
+			toParse = append(toParse, f)
+		}
+		filesystem[f] = []byte(content)
+	}
+	config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
+	ctx := android.NewTestContext(config)
+
+	registerModuleTypes(ctx)
+	ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
+	ctx.RegisterBp2BuildConfig(bp2buildConfig)
+	ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
+	ctx.RegisterForBazelConversion()
+
+	_, errs := ctx.ParseFileList(dir, toParse)
+	if errored(t, tc.description, errs) {
+		return
+	}
+	_, errs = ctx.ResolveDependencies(config)
+	if errored(t, tc.description, errs) {
+		return
+	}
+
+	checkDir := dir
+	if tc.dir != "" {
+		checkDir = tc.dir
+	}
+	codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+	bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
+	if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
+		t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
+	} else {
+		for i, target := range bazelTargets {
+			if w, g := tc.expectedBazelTargets[i], target.content; w != g {
+				t.Errorf(
+					"%s: Expected generated Bazel target to be '%s', got '%s'",
+					tc.description,
+					w,
+					g,
+				)
+			}
+		}
+	}
+}
+
 type nestedProps struct {
 	Nested_prop string
 }
@@ -44,17 +144,6 @@
 	props customProps
 }
 
-func errored(t *testing.T, desc string, errs []error) bool {
-	t.Helper()
-	if len(errs) > 0 {
-		for _, err := range errs {
-			t.Errorf("%s: %s", desc, err)
-		}
-		return true
-	}
-	return false
-}
-
 // OutputFiles is needed because some instances of this module use dist with a
 // tag property which requires the module implements OutputFileProducer.
 func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
diff --git a/cc/ndk_api_coverage_parser/__init__.py b/cc/ndk_api_coverage_parser/__init__.py
index 7817c78..8b9cd66 100755
--- a/cc/ndk_api_coverage_parser/__init__.py
+++ b/cc/ndk_api_coverage_parser/__init__.py
@@ -21,7 +21,12 @@
 import sys
 
 from xml.etree.ElementTree import Element, SubElement, tostring
-from symbolfile import ALL_ARCHITECTURES, FUTURE_API_LEVEL, MultiplyDefinedSymbolError, SymbolFileParser
+from symbolfile import (
+    ALL_ARCHITECTURES,
+    FUTURE_API_LEVEL,
+    MultiplyDefinedSymbolError,
+    SymbolFileParser,
+)
 
 
 ROOT_ELEMENT_TAG = 'ndk-library'
@@ -63,6 +68,7 @@
 
 class XmlGenerator(object):
     """Output generator that writes parsed symbol file to a xml file."""
+
     def __init__(self, output_file):
         self.output_file = output_file
 
@@ -74,10 +80,14 @@
                 continue
             version_attributes = parse_tags(version.tags)
             _, _, postfix = version.name.partition('_')
-            is_platform = postfix == 'PRIVATE' or postfix == 'PLATFORM'
+            is_platform = postfix in ('PRIVATE' , 'PLATFORM')
             is_deprecated = postfix == 'DEPRECATED'
-            version_attributes.update({PLATFORM_ATTRIBUTE_KEY: str(is_platform)})
-            version_attributes.update({DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)})
+            version_attributes.update(
+                {PLATFORM_ATTRIBUTE_KEY: str(is_platform)}
+            )
+            version_attributes.update(
+                {DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)}
+            )
             for symbol in version.symbols:
                 if VARIABLE_TAG in symbol.tags:
                     continue
@@ -103,13 +113,20 @@
     """Parses and returns command line arguments."""
     parser = argparse.ArgumentParser()
 
-    parser.add_argument('symbol_file', type=os.path.realpath, help='Path to symbol file.')
     parser.add_argument(
-        'output_file', type=os.path.realpath,
-        help='The output parsed api coverage file.')
+        'symbol_file', type=os.path.realpath, help='Path to symbol file.'
+    )
     parser.add_argument(
-        '--api-map', type=os.path.realpath, required=True,
-        help='Path to the API level map JSON file.')
+        'output_file',
+        type=os.path.realpath,
+        help='The output parsed api coverage file.',
+    )
+    parser.add_argument(
+        '--api-map',
+        type=os.path.realpath,
+        required=True,
+        help='Path to the API level map JSON file.',
+    )
     return parser.parse_args()
 
 
@@ -122,13 +139,15 @@
 
     with open(args.symbol_file) as symbol_file:
         try:
-            versions = SymbolFileParser(symbol_file, api_map, "", FUTURE_API_LEVEL,
-                                        True, True).parse()
+            versions = SymbolFileParser(
+                symbol_file, api_map, "", FUTURE_API_LEVEL, True, True
+            ).parse()
         except MultiplyDefinedSymbolError as ex:
             sys.exit('{}: error: {}'.format(args.symbol_file, ex))
 
     generator = XmlGenerator(args.output_file)
     generator.write(versions)
 
+
 if __name__ == '__main__':
     main()
diff --git a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
index 3ec14c1..141059c 100644
--- a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
+++ b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
@@ -50,10 +50,12 @@
         return False
     return all(etree_equal(c1, c2) for c1, c2 in zip(elem1, elem2))
 
-
+# pylint: disable=line-too-long
 class ApiCoverageSymbolFileParserTest(unittest.TestCase):
     def test_parse(self):
-        input_file = io.StringIO(textwrap.dedent(u"""\
+        input_file = io.StringIO(
+            textwrap.dedent(
+                u"""\
             LIBLOG { # introduced-arm64=24 introduced-x86=24 introduced-x86_64=24
               global:
                 android_name_to_log_id; # apex llndk introduced=23
@@ -64,22 +66,28 @@
               local:
                 *;
             };
-            
+
             LIBLOG_PLATFORM {
                 android_fdtrack; # llndk
                 android_net; # introduced=23
             };
-            
+
             LIBLOG_FOO { # var
                 android_var;
             };
-        """))
-        parser = SymbolFileParser(input_file, {}, "", FUTURE_API_LEVEL, True, True)
+        """
+            )
+        )
+        parser = SymbolFileParser(
+            input_file, {}, "", FUTURE_API_LEVEL, True, True
+        )
         generator = nparser.XmlGenerator(io.StringIO())
         result = generator.convertToXml(parser.parse())
-        expected = fromstring('<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>')
+        expected = fromstring(
+            '<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>'
+        )
         self.assertTrue(etree_equal(expected, result))
-
+# pylint: enable=line-too-long
 
 def main():
     suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index ebb8959..1bdd040 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -196,6 +196,10 @@
 	// If the library is optional or required.
 	Optional bool
 
+	// If the library is implicitly infered by Soong (as opposed to explicitly added via `uses_libs`
+	// or `optional_uses_libs`.
+	Implicit bool
+
 	// On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
 	Host android.Path
 
@@ -258,8 +262,9 @@
 const AnySdkVersion int = android.FutureApiLevelInt
 
 // Add class loader context for the given library to the map entry for the given SDK version.
-func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
-	optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
+func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int,
+	lib string, optional, implicit bool, hostPath, installPath android.Path,
+	nestedClcMap ClassLoaderContextMap) error {
 
 	// For prebuilts, library should have the same name as the source module.
 	lib = android.RemoveOptionalPrebuiltPrefix(lib)
@@ -308,6 +313,7 @@
 	clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
 		Name:        lib,
 		Optional:    optional,
+		Implicit:    implicit,
 		Host:        hostPath,
 		Device:      devicePath,
 		Subcontexts: subcontexts,
@@ -320,9 +326,10 @@
 // about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
 // are validated later before CLC is used (in validateClassLoaderContext).
 func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, sdkVer int,
-	lib string, optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
+	lib string, optional, implicit bool, hostPath, installPath android.Path,
+	nestedClcMap ClassLoaderContextMap) {
 
-	err := clcMap.addContext(ctx, sdkVer, lib, optional, hostPath, installPath, nestedClcMap)
+	err := clcMap.addContext(ctx, sdkVer, lib, optional, implicit, hostPath, installPath, nestedClcMap)
 	if err != nil {
 		ctx.ModuleErrorf(err.Error())
 	}
@@ -366,13 +373,15 @@
 // included). This is the list of libraries that should be in the <uses-library> tags in the
 // manifest. Some of them may be present in the source manifest, others are added by manifest_fixer.
 // Required and optional libraries are in separate lists.
-func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []string) {
+func (clcMap ClassLoaderContextMap) usesLibs(implicit bool) (required []string, optional []string) {
 	if clcMap != nil {
 		clcs := clcMap[AnySdkVersion]
 		required = make([]string, 0, len(clcs))
 		optional = make([]string, 0, len(clcs))
 		for _, clc := range clcs {
-			if clc.Optional {
+			if implicit && !clc.Implicit {
+				// Skip, this is an explicit library and we need only the implicit ones.
+			} else if clc.Optional {
 				optional = append(optional, clc.Name)
 			} else {
 				required = append(required, clc.Name)
@@ -382,6 +391,14 @@
 	return required, optional
 }
 
+func (clcMap ClassLoaderContextMap) UsesLibs() ([]string, []string) {
+	return clcMap.usesLibs(false)
+}
+
+func (clcMap ClassLoaderContextMap) ImplicitUsesLibs() ([]string, []string) {
+	return clcMap.usesLibs(true)
+}
+
 func (clcMap ClassLoaderContextMap) Dump() string {
 	jsonCLC := toJsonClassLoaderContext(clcMap)
 	bytes, err := json.MarshalIndent(jsonCLC, "", "  ")
@@ -524,6 +541,8 @@
 // the same as Soong representation except that SDK versions and paths are represented with strings.
 type jsonClassLoaderContext struct {
 	Name        string
+	Optional    bool
+	Implicit    bool
 	Host        string
 	Device      string
 	Subcontexts []*jsonClassLoaderContext
@@ -555,6 +574,8 @@
 	for _, clc := range jClcs {
 		clcs = append(clcs, &ClassLoaderContext{
 			Name:        clc.Name,
+			Optional:    clc.Optional,
+			Implicit:    clc.Implicit,
 			Host:        constructPath(ctx, clc.Host),
 			Device:      clc.Device,
 			Subcontexts: fromJsonClassLoaderContextRec(ctx, clc.Subcontexts),
@@ -579,6 +600,8 @@
 	for i, clc := range clcs {
 		jClcs[i] = &jsonClassLoaderContext{
 			Name:        clc.Name,
+			Optional:    clc.Optional,
+			Implicit:    clc.Implicit,
 			Host:        clc.Host.String(),
 			Device:      clc.Device,
 			Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index 0b7b546..d81ac2c 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -50,33 +50,34 @@
 	ctx := testContext()
 
 	optional := false
+	implicit := true
 
 	m := make(ClassLoaderContextMap)
 
-	m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
-	m.AddContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
-	m.AddContext(ctx, AnySdkVersion, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+	m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+	m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+	m.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
 
 	// Add some libraries with nested subcontexts.
 
 	m1 := make(ClassLoaderContextMap)
-	m1.AddContext(ctx, AnySdkVersion, "a1", optional, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
-	m1.AddContext(ctx, AnySdkVersion, "b1", optional, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
+	m1.AddContext(ctx, AnySdkVersion, "a1", optional, implicit, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
+	m1.AddContext(ctx, AnySdkVersion, "b1", optional, implicit, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
 
 	m2 := make(ClassLoaderContextMap)
-	m2.AddContext(ctx, AnySdkVersion, "a2", optional, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
-	m2.AddContext(ctx, AnySdkVersion, "b2", optional, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
-	m2.AddContext(ctx, AnySdkVersion, "c2", optional, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
+	m2.AddContext(ctx, AnySdkVersion, "a2", optional, implicit, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
+	m2.AddContext(ctx, AnySdkVersion, "b2", optional, implicit, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
+	m2.AddContext(ctx, AnySdkVersion, "c2", optional, implicit, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
 
 	m3 := make(ClassLoaderContextMap)
-	m3.AddContext(ctx, AnySdkVersion, "a3", optional, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
-	m3.AddContext(ctx, AnySdkVersion, "b3", optional, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
+	m3.AddContext(ctx, AnySdkVersion, "a3", optional, implicit, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
+	m3.AddContext(ctx, AnySdkVersion, "b3", optional, implicit, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
 
-	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
+	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
 	// When the same library is both in conditional and unconditional context, it should be removed
 	// from conditional context.
-	m.AddContext(ctx, 42, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
-	m.AddContext(ctx, AnySdkVersion, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+	m.AddContext(ctx, 42, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+	m.AddContext(ctx, AnySdkVersion, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
 
 	// Merge map with implicit root library that is among toplevel contexts => does nothing.
 	m.AddContextMap(m1, "c")
@@ -85,12 +86,12 @@
 	m.AddContextMap(m3, "m_g")
 
 	// Compatibility libraries with unknown install paths get default paths.
-	m.AddContext(ctx, 29, AndroidHidlManager, optional, buildPath(ctx, AndroidHidlManager), nil, nil)
-	m.AddContext(ctx, 29, AndroidHidlBase, optional, buildPath(ctx, AndroidHidlBase), nil, nil)
+	m.AddContext(ctx, 29, AndroidHidlManager, optional, implicit, buildPath(ctx, AndroidHidlManager), nil, nil)
+	m.AddContext(ctx, 29, AndroidHidlBase, optional, implicit, buildPath(ctx, AndroidHidlBase), nil, nil)
 
 	// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
 	// needed as a compatibility library if "android.test.runner" is in CLC as well.
-	m.AddContext(ctx, 30, AndroidTestMock, optional, buildPath(ctx, AndroidTestMock), nil, nil)
+	m.AddContext(ctx, 30, AndroidTestMock, optional, implicit, buildPath(ctx, AndroidTestMock), nil, nil)
 
 	valid, validationError := validateClassLoaderContext(m)
 
@@ -164,11 +165,12 @@
 func TestCLCJson(t *testing.T) {
 	ctx := testContext()
 	optional := false
+	implicit := true
 	m := make(ClassLoaderContextMap)
-	m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
-	m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
-	m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
-	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+	m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+	m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+	m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
 	jsonCLC := toJsonClassLoaderContext(m)
 	restored := fromJsonClassLoaderContext(ctx, jsonCLC)
 	android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
@@ -189,12 +191,13 @@
 func testCLCUnknownPath(t *testing.T, whichPath string) {
 	ctx := testContext()
 	optional := false
+	implicit := true
 
 	m := make(ClassLoaderContextMap)
 	if whichPath == "build" {
-		m.AddContext(ctx, AnySdkVersion, "a", optional, nil, nil, nil)
+		m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, nil, nil, nil)
 	} else {
-		m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), nil, nil)
+		m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), nil, nil)
 	}
 
 	// The library should be added to <uses-library> tags by the manifest_fixer.
@@ -229,10 +232,11 @@
 func TestCLCNestedConditional(t *testing.T) {
 	ctx := testContext()
 	optional := false
+	implicit := true
 	m1 := make(ClassLoaderContextMap)
-	m1.AddContext(ctx, 42, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+	m1.AddContext(ctx, 42, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
 	m := make(ClassLoaderContextMap)
-	err := m.addContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
+	err := m.addContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
 	checkError(t, err, "nested class loader context shouldn't have conditional part")
 }
 
@@ -241,11 +245,12 @@
 func TestCLCSdkVersionOrder(t *testing.T) {
 	ctx := testContext()
 	optional := false
+	implicit := true
 	m := make(ClassLoaderContextMap)
-	m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
-	m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
-	m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
-	m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+	m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+	m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+	m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+	m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
 
 	valid, validationError := validateClassLoaderContext(m)
 
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 1f7234d..38065f1 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -71,7 +71,9 @@
 		args = append(args, "--use-embedded-dex")
 	}
 
-	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
+	// manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
+	// explicitly via `uses_libs`/`optional_uses_libs`.
+	requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
 	for _, usesLib := range requiredUsesLibs {
 		args = append(args, "--uses-library", usesLib)
 	}
diff --git a/java/app.go b/java/app.go
index e7661df..5104f07 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1224,17 +1224,28 @@
 
 func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
 	if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
-		ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
-		ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
+		reqTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false, false)
+		ctx.AddVariationDependencies(nil, reqTag, u.usesLibraryProperties.Uses_libs...)
+
+		optTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true, false)
+		ctx.AddVariationDependencies(nil, optTag, u.presentOptionalUsesLibs(ctx)...)
+
 		// Only add these extra dependencies if the module depends on framework libs. This avoids
 		// creating a cyclic dependency:
 		//     e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
 		if hasFrameworkLibs {
-			// Dexpreopt needs paths to the dex jars of these libraries in order to construct
-			// class loader context for dex2oat. Add them as a dependency with a special tag.
-			ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
-			ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
-			ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
+			// Add implicit <uses-library> dependencies on compatibility libraries. Some of them are
+			// optional, and some required --- this depends on the most common usage of the library
+			// and may be wrong for some apps (they need explicit `uses_libs`/`optional_uses_libs`).
+
+			compat28OptTag := makeUsesLibraryDependencyTag(28, true, true)
+			ctx.AddVariationDependencies(nil, compat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
+
+			compat29ReqTag := makeUsesLibraryDependencyTag(29, false, true)
+			ctx.AddVariationDependencies(nil, compat29ReqTag, dexpreopt.CompatUsesLibs29...)
+
+			compat30OptTag := makeUsesLibraryDependencyTag(30, true, true)
+			ctx.AddVariationDependencies(nil, compat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
 		}
 	}
 }
@@ -1293,7 +1304,7 @@
 				replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
 				replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
 			}
-			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
+			clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, tag.implicit,
 				lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
 		} else if ctx.Config().AllowMissingDependencies() {
 			ctx.AddMissingDependencies([]string{dep})
diff --git a/java/app_test.go b/java/app_test.go
index c14c65d..56ad28d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2398,14 +2398,7 @@
 	expectManifestFixerArgs := `--extract-native-libs=true ` +
 		`--uses-library qux ` +
 		`--uses-library quuz ` +
-		`--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
-		`--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
-		`--uses-library runtime-library ` +
-		`--uses-library runtime-required-x ` + // TODO(b/132357300): "runtime-required-x" should not be passed to manifest_fixer
-		`--uses-library runtime-required-y ` + // TODO(b/132357300): "runtime-required-y" should not be passed to manifest_fixer
-		`--optional-uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
-		`--optional-uses-library runtime-optional-x ` + // TODO(b/132357300): "runtime-optional-x" should not be passed to manifest_fixer
-		`--optional-uses-library runtime-optional-y` // TODO(b/132357300): "runtime-optional-y" should not be passed to manifest_fixer
+		`--uses-library runtime-library`
 	android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
 
 	// Test that all libraries are verified (library order matters).
diff --git a/java/base.go b/java/base.go
index ea5b137..8e6d1cd 100644
--- a/java/base.go
+++ b/java/base.go
@@ -606,10 +606,8 @@
 			if component, ok := dep.(SdkLibraryComponentDependency); ok {
 				if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
 					// Add library as optional if it's one of the optional compatibility libs.
-					tag := usesLibReqTag
-					if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
-						tag = usesLibOptTag
-					}
+					optional := android.InList(*lib, dexpreopt.OptionalCompatUsesLibs)
+					tag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, optional, true)
 					ctx.AddVariationDependencies(nil, tag, *lib)
 				}
 			}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index bb542c4..7577316 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -538,7 +538,7 @@
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
-	jars := global.ApexBootJars.Filter(possibleUpdatableModules)
+	jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
 
 	// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
 	// config. However, any test specific jars would not be present in ApexBootJars. Instead,
@@ -546,6 +546,12 @@
 	// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
 	if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
 		jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
+	} else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+		unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents)
+		_, unknown = android.RemoveFromList("core-icu4j", unknown)
+		if len(unknown) > 0 {
+			ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+		}
 	}
 	return jars
 }
diff --git a/java/java.go b/java/java.go
index b46324f..4c2ca9b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -248,15 +248,24 @@
 
 type usesLibraryDependencyTag struct {
 	dependencyTag
-	sdkVersion int  // SDK version in which the library appared as a standalone library.
-	optional   bool // If the dependency is optional or required.
+
+	// SDK version in which the library appared as a standalone library.
+	sdkVersion int
+
+	// If the dependency is optional or required.
+	optional bool
+
+	// Whether this is an implicit dependency inferred by Soong, or an explicit one added via
+	// `uses_libs`/`optional_uses_libs` properties.
+	implicit bool
 }
 
-func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag {
+func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag {
 	return usesLibraryDependencyTag{
 		dependencyTag: dependencyTag{name: fmt.Sprintf("uses-library-%d", sdkVersion)},
 		sdkVersion:    sdkVersion,
 		optional:      optional,
+		implicit:      implicit,
 	}
 }
 
@@ -285,11 +294,6 @@
 	syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
 	jniInstallTag           = installDependencyTag{name: "jni install"}
 	binaryInstallTag        = installDependencyTag{name: "binary install"}
-	usesLibReqTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
-	usesLibOptTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
-	usesLibCompat28OptTag   = makeUsesLibraryDependencyTag(28, true)
-	usesLibCompat29ReqTag   = makeUsesLibraryDependencyTag(29, false)
-	usesLibCompat30OptTag   = makeUsesLibraryDependencyTag(30, true)
 )
 
 func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -1813,8 +1817,10 @@
 	depTag := ctx.OtherModuleDependencyTag(depModule)
 	if depTag == libTag {
 		// Ok, propagate <uses-library> through non-static library dependencies.
-	} else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
-		// Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
+	} else if tag, ok := depTag.(usesLibraryDependencyTag); ok &&
+		tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit {
+		// Ok, propagate <uses-library> through non-compatibility implicit <uses-library>
+		// dependencies.
 	} else if depTag == staticLibTag {
 		// Propagate <uses-library> through static library dependencies, unless it is a component
 		// library (such as stubs). Component libraries have a dependency on their SDK library,
@@ -1832,7 +1838,7 @@
 	// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
 	// from its CLC should be added to the current CLC.
 	if sdkLib != nil {
-		clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
+		clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true,
 			dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
 	} else {
 		clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 6c2a5b5..5311f62 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -107,7 +107,16 @@
 	global := dexpreopt.GetGlobalConfig(ctx)
 
 	possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
-	return global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+	jars, unknown := global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+	// TODO(satayev): remove geotz ssc_fragment, since geotz is not part of SSCP anymore.
+	_, unknown = android.RemoveFromList("geotz", unknown)
+
+	// For non test apexes, make sure that all contents are actually declared in make.
+	if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 {
+		ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS", unknown)
+	}
+
+	return jars
 }
 
 type systemServerClasspathFragmentContentDependencyTag struct {