Consistently use default install path for compatibility <uses-library>.

Previously default install path was provided only for comatibility
libraries that are added explicitly via `uses_libs`/`optional_uses_libs`
properties. This didn't take into account compatibility libraries that
are added by Soong when it computes transitive closure of SDK library
dependencies. As a result, install path in such cases remained unknown,
and the corresponding compatibility library was omitted from class
loader context, which caused 'ClassLoaderContext shared library size
mismatch' errors at first boot on device.

Test: lunch aosp_cf_x86_phone-userdebug && m
Bug: 132357300
Change-Id: If661272f46803299c8640f7f5ef161c8217d07e4
This commit is contained in:
Ulya Trafimovich 2020-09-10 12:48:53 +01:00
parent c2c2d4e716
commit 663dc53c94
4 changed files with 58 additions and 61 deletions

View file

@ -100,6 +100,22 @@ type GlobalSoongConfig struct {
ConstructContext android.Path ConstructContext android.Path
} }
// These two libs are added as optional dependencies (<uses-library> with
// android:required set to false). This is because they haven't existed in pre-P
// devices, but classes in them were in bootclasspath jars, etc. So making them
// hard dependencies (android:required=true) would prevent apps from being
// installed to such legacy devices.
var OptionalCompatUsesLibs = []string{
"android.test.base",
"android.test.mock",
}
var CompatUsesLibs = []string{
"org.apache.http.legacy",
"android.hidl.base-V1.0-java",
"android.hidl.manager-V1.0-java",
}
const UnknownInstallLibraryPath = "error" const UnknownInstallLibraryPath = "error"
// LibraryPath contains paths to the library DEX jar on host and on device. // LibraryPath contains paths to the library DEX jar on host and on device.
@ -112,7 +128,29 @@ type LibraryPath struct {
type LibraryPaths map[string]*LibraryPath type LibraryPaths map[string]*LibraryPath
// Add a new library path to the map, unless a path for this library already exists. // Add a new library path to the map, unless a path for this library already exists.
func (libPaths LibraryPaths) addLibraryPath(ctx android.PathContext, lib string, hostPath, installPath android.Path) { // If necessary, check that the build and install paths exist.
func (libPaths LibraryPaths) addLibraryPath(ctx android.ModuleContext, lib string,
hostPath, installPath android.Path, strict bool) {
// If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
// not found. However, this is likely to result is disabling dexpreopt, as it won't be
// possible to construct class loader context without on-host and on-device library paths.
strict = strict && !ctx.Config().AllowMissingDependencies()
if hostPath == nil && strict {
android.ReportPathErrorf(ctx, "unknown build path to <uses-library> '%s'", lib)
}
if installPath == nil {
if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
// Assume that compatibility libraries are installed in /system/framework.
installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
} else if strict {
android.ReportPathErrorf(ctx, "unknown install path to <uses-library> '%s'", lib)
}
}
// Add a library only if the build and install path to it is known.
if _, present := libPaths[lib]; !present { if _, present := libPaths[lib]; !present {
var devicePath string var devicePath string
if installPath != nil { if installPath != nil {
@ -128,31 +166,17 @@ func (libPaths LibraryPaths) addLibraryPath(ctx android.PathContext, lib string,
} }
} }
// Add a new library path to the map. Ensure that the build path to the library exists. // Add a new library path to the map. Enforce checks that the library paths exist.
func (libPaths LibraryPaths) AddLibraryPath(ctx android.PathContext, lib string, hostPath, installPath android.Path) { func (libPaths LibraryPaths) AddLibraryPath(ctx android.ModuleContext, lib string, hostPath, installPath android.Path) {
if hostPath != nil && installPath != nil { libPaths.addLibraryPath(ctx, lib, hostPath, installPath, true)
// Add a library only if the build and install path to it is known.
libPaths.addLibraryPath(ctx, lib, hostPath, installPath)
} else if ctx.Config().AllowMissingDependencies() {
// If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
// not found. However, this is likely to result is disabling dexpreopt, as it won't be
// possible to construct class loader context without on-host and on-device library paths.
} else {
// Error on libraries with unknown paths.
if hostPath == nil {
android.ReportPathErrorf(ctx, "unknown build path to <uses-library> '%s'", lib)
} else {
android.ReportPathErrorf(ctx, "unknown install path to <uses-library> '%s'", lib)
}
}
} }
// Add a new library path to the map, if the library exists (name is not nil). // Add a new library path to the map, if the library exists (name is not nil).
func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.PathContext, lib *string, hostPath, installPath android.Path) { // Don't enforce checks that the library paths exist. Some libraries may be missing from the build,
// but their names still need to be added to <uses-library> tags in the manifest.
func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.ModuleContext, lib *string, hostPath, installPath android.Path) {
if lib != nil { if lib != nil {
// Don't check the build paths, add in any case. Some libraries may be missing from the libPaths.addLibraryPath(ctx, *lib, hostPath, installPath, false)
// build, but their names still need to be added to <uses-library> tags in the manifest.
libPaths.addLibraryPath(ctx, *lib, hostPath, installPath)
} }
} }

View file

@ -42,16 +42,6 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
}, },
"args", "libs") "args", "libs")
// These two libs are added as optional dependencies (<uses-library> with
// android:required set to false). This is because they haven't existed in pre-P
// devices, but classes in them were in bootclasspath jars, etc. So making them
// hard dependencies (android:required=true) would prevent apps from being
// installed to such legacy devices.
var optionalUsesLibs = []string{
"android.test.base",
"android.test.mock",
}
// Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml // Uses manifest_fixer.py to inject minSdkVersion, etc. into an AndroidManifest.xml
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries dexpreopt.LibraryPaths, func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext, sdkLibraries dexpreopt.LibraryPaths,
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path { isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
@ -81,7 +71,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
} }
for _, usesLib := range android.SortedStringKeys(sdkLibraries) { for _, usesLib := range android.SortedStringKeys(sdkLibraries) {
if inList(usesLib, optionalUsesLibs) { if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
args = append(args, "--optional-uses-library", usesLib) args = append(args, "--optional-uses-library", usesLib)
} else { } else {
args = append(args, "--uses-library", usesLib) args = append(args, "--uses-library", usesLib)

View file

@ -787,7 +787,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
// Add implicit SDK libraries to <uses-library> list. // Add implicit SDK libraries to <uses-library> list.
for _, usesLib := range android.SortedStringKeys(a.aapt.sdkLibraries) { for _, usesLib := range android.SortedStringKeys(a.aapt.sdkLibraries) {
a.usesLibrary.addLib(usesLib, inList(usesLib, optionalUsesLibs)) a.usesLibrary.addLib(usesLib, inList(usesLib, dexpreopt.OptionalCompatUsesLibs))
} }
// Check that the <uses-library> list is coherent with the manifest. // Check that the <uses-library> list is coherent with the manifest.
@ -1947,11 +1947,8 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs
if hasFrameworkLibs { if hasFrameworkLibs {
// Dexpreopt needs paths to the dex jars of these libraries in order to construct // 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. // class loader context for dex2oat. Add them as a dependency with a special tag.
ctx.AddVariationDependencies(nil, usesLibCompatTag, ctx.AddVariationDependencies(nil, usesLibTag, dexpreopt.CompatUsesLibs...)
"org.apache.http.legacy", ctx.AddVariationDependencies(nil, usesLibTag, dexpreopt.OptionalCompatUsesLibs...)
"android.hidl.base-V1.0-java",
"android.hidl.manager-V1.0-java")
ctx.AddVariationDependencies(nil, usesLibCompatTag, optionalUsesLibs...)
} }
} }
} }
@ -1969,27 +1966,14 @@ func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.Libr
usesLibPaths := make(dexpreopt.LibraryPaths) usesLibPaths := make(dexpreopt.LibraryPaths)
if !ctx.Config().UnbundledBuild() { if !ctx.Config().UnbundledBuild() {
ctx.VisitDirectDeps(func(m android.Module) { ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
tag := ctx.OtherModuleDependencyTag(m)
if tag == usesLibTag || tag == usesLibCompatTag {
dep := ctx.OtherModuleName(m) dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok { if lib, ok := m.(Dependency); ok {
buildPath := lib.DexJarBuildPath() usesLibPaths.AddLibraryPath(ctx, dep, lib.DexJarBuildPath(), lib.DexJarInstallPath())
installPath := lib.DexJarInstallPath()
if installPath == nil && tag == usesLibCompatTag {
// assume that compatibility libraries are in /system/framework
installPath = android.PathForModuleInstall(ctx, "framework", dep+".jar")
}
usesLibPaths.AddLibraryPath(ctx, dep, buildPath, installPath)
} else if ctx.Config().AllowMissingDependencies() { } else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep}) ctx.AddMissingDependencies([]string{dep})
} else { } else {
ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be "+ ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library", dep)
"a java library", dep)
}
} }
}) })
} }

View file

@ -570,7 +570,6 @@ var (
certificateTag = dependencyTag{name: "certificate"} certificateTag = dependencyTag{name: "certificate"}
instrumentationForTag = dependencyTag{name: "instrumentation_for"} instrumentationForTag = dependencyTag{name: "instrumentation_for"}
usesLibTag = dependencyTag{name: "uses-library"} usesLibTag = dependencyTag{name: "uses-library"}
usesLibCompatTag = dependencyTag{name: "uses-library-compat"}
extraLintCheckTag = dependencyTag{name: "extra-lint-check"} extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
) )