Do not add dependencies of shared SDK libraries to manifest_fixer.

Test: lunch aosp_cf_x86_phone-userdebug && m
Bug: 132357300
Bug: 168686456
Change-Id: Ibd9742684fa6a8f1353ca0e513f7fa814a6ec9fc
This commit is contained in:
Ulya Trafimovich 2020-10-06 17:24:19 +01:00
parent 18554243de
commit a8c28e27bc
6 changed files with 75 additions and 46 deletions

View File

@ -71,6 +71,10 @@ type ClassLoaderContext struct {
// Nested class loader subcontexts for dependencies.
Subcontexts []*ClassLoaderContext
// If the library is a shared library. This affects which elements of class loader context are
// added as <uses-library> tags by the manifest_fixer (dependencies of shared libraries aren't).
IsSharedLibrary bool
}
// ClassLoaderContextMap is a map from SDK version to a class loader context.
@ -81,7 +85,7 @@ type ClassLoaderContextMap map[int][]*ClassLoaderContext
// 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,
hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) error {
shared bool, hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) error {
// 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
@ -132,42 +136,42 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont
Host: hostPath,
Device: devicePath,
Subcontexts: subcontexts,
IsSharedLibrary: shared,
})
return nil
}
// Wrapper around addContext that reports errors.
func (clcMap ClassLoaderContextMap) addContextOrReportError(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) {
shared bool, hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) {
err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, strict, nestedClcMap)
err := clcMap.addContext(ctx, sdkVer, lib, shared, hostPath, installPath, strict, nestedClcMap)
if err != nil {
ctx.ModuleErrorf(err.Error())
android.ReportPathErrorf(ctx, err.Error())
}
}
// Add class loader context. Fail on unknown build/install paths.
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
hostPath, installPath android.Path) {
shared bool, hostPath, installPath android.Path) {
clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, hostPath, installPath, true, nil)
clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, shared, hostPath, installPath, true, nil)
}
// Add class loader context if the library exists. Don't fail on unknown build/install paths.
func (clcMap ClassLoaderContextMap) MaybeAddContext(ctx android.ModuleInstallPathContext, lib *string,
hostPath, installPath android.Path) {
shared bool, hostPath, installPath android.Path) {
if lib != nil {
clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, hostPath, installPath, false, nil)
clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, shared, hostPath, installPath, false, nil)
}
}
// Add class loader context for the given SDK version. Fail on unknown build/install paths.
func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
lib string, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
lib string, shared bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, true, nestedClcMap)
clcMap.addContextOrReportError(ctx, sdkVer, lib, shared, hostPath, installPath, true, nestedClcMap)
}
// Merge the other class loader context map into this one, do not override existing entries.
@ -204,7 +208,9 @@ func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContext
}
}
// List of libraries in the unconditional class loader context, excluding dependencies of shared libraries.
// List of libraries in the unconditional class loader context, excluding dependencies of shared
// libraries. These libraries should be in the <uses-library> tags in the manifest. Some of them may
// be present in the original manifest, others are added by the manifest_fixer.
func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
if clcMap != nil {
// compatibility libraries (those in conditional context) are not added to <uses-library> tags
@ -217,8 +223,13 @@ func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
func usesLibsRec(clcs []*ClassLoaderContext) (ulibs []string) {
for _, clc := range clcs {
ulibs = append(ulibs, clc.Name)
// <uses-library> tags in the manifest should not include dependencies of shared libraries,
// because PackageManager already tracks all such dependencies and automatically adds their
// class loader contexts as subcontext of the shared library.
if !clc.IsSharedLibrary {
ulibs = append(ulibs, usesLibsRec(clc.Subcontexts)...)
}
}
return ulibs
}

View File

@ -25,6 +25,11 @@ import (
"android/soong/android"
)
const (
shared = true // dependencies are not added to uses libs
nonshared = false // dependencies are added to uses libs
)
func TestCLC(t *testing.T) {
// Construct class loader context with the following structure:
// .
@ -50,36 +55,36 @@ func TestCLC(t *testing.T) {
m := make(ClassLoaderContextMap)
m.AddContext(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
m.AddContext(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
m.AddContext(ctx, "a", nonshared, buildPath(ctx, "a"), installPath(ctx, "a"))
m.AddContext(ctx, "b", shared, buildPath(ctx, "b"), installPath(ctx, "b"))
// "Maybe" variant in the good case: add as usual.
c := "c"
m.MaybeAddContext(ctx, &c, buildPath(ctx, "c"), installPath(ctx, "c"))
m.MaybeAddContext(ctx, &c, nonshared, buildPath(ctx, "c"), installPath(ctx, "c"))
// "Maybe" variant in the bad case: don't add library with unknown name, keep going.
m.MaybeAddContext(ctx, nil, nil, nil)
m.MaybeAddContext(ctx, nil, nonshared, nil, nil)
// Add some libraries with nested subcontexts.
m1 := make(ClassLoaderContextMap)
m1.AddContext(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
m1.AddContext(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
m1.AddContext(ctx, "a1", nonshared, buildPath(ctx, "a1"), installPath(ctx, "a1"))
m1.AddContext(ctx, "b1", shared, buildPath(ctx, "b1"), installPath(ctx, "b1"))
m2 := make(ClassLoaderContextMap)
m2.AddContext(ctx, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"))
m2.AddContext(ctx, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"))
m2.AddContextForSdk(ctx, AnySdkVersion, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
m2.AddContext(ctx, "a2", nonshared, buildPath(ctx, "a2"), installPath(ctx, "a2"))
m2.AddContext(ctx, "b2", shared, buildPath(ctx, "b2"), installPath(ctx, "b2"))
m2.AddContextForSdk(ctx, AnySdkVersion, "c2", shared, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
m3 := make(ClassLoaderContextMap)
m3.AddContext(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
m3.AddContext(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
m3.AddContext(ctx, "a3", nonshared, buildPath(ctx, "a3"), installPath(ctx, "a3"))
m3.AddContext(ctx, "b3", shared, buildPath(ctx, "b3"), installPath(ctx, "b3"))
m.AddContextForSdk(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), m2)
m.AddContextForSdk(ctx, AnySdkVersion, "d", nonshared, 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.AddContextForSdk(ctx, 42, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
m.AddContextForSdk(ctx, AnySdkVersion, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
m.AddContextForSdk(ctx, 42, "f", nonshared, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
m.AddContextForSdk(ctx, AnySdkVersion, "f", nonshared, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
// Merge map with implicit root library that is among toplevel contexts => does nothing.
m.AddContextMap(m1, "c")
@ -88,12 +93,12 @@ func TestCLC(t *testing.T) {
m.AddContextMap(m3, "m_g")
// Compatibility libraries with unknown install paths get default paths.
m.AddContextForSdk(ctx, 29, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil, nil)
m.AddContextForSdk(ctx, 29, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil, nil)
m.AddContextForSdk(ctx, 29, AndroidHidlManager, nonshared, buildPath(ctx, AndroidHidlManager), nil, nil)
m.AddContextForSdk(ctx, 29, AndroidHidlBase, nonshared, 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.AddContextForSdk(ctx, 30, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil, nil)
m.AddContextForSdk(ctx, 30, AndroidTestMock, nonshared, buildPath(ctx, AndroidTestMock), nil, nil)
valid, validationError := validateClassLoaderContext(m)
@ -153,7 +158,7 @@ func TestCLC(t *testing.T) {
// Test for libraries that are added by the manifest_fixer.
t.Run("uses libs", func(t *testing.T) {
wantUsesLibs := []string{"a", "b", "c", "d", "a2", "b2", "c2", "a1", "b1", "f", "a3", "b3"}
wantUsesLibs := []string{"a", "b", "c", "d", "a2", "b2", "c2", "f", "a3", "b3"}
if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
}
@ -164,7 +169,7 @@ func TestCLC(t *testing.T) {
func TestCLCUnknownBuildPath(t *testing.T) {
ctx := testContext()
m := make(ClassLoaderContextMap)
err := m.addContext(ctx, AnySdkVersion, "a", nil, nil, true, nil)
err := m.addContext(ctx, AnySdkVersion, "a", nonshared, nil, nil, true, nil)
checkError(t, err, "unknown build path to <uses-library> \"a\"")
}
@ -172,7 +177,7 @@ func TestCLCUnknownBuildPath(t *testing.T) {
func TestCLCUnknownInstallPath(t *testing.T) {
ctx := testContext()
m := make(ClassLoaderContextMap)
err := m.addContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), nil, true, nil)
err := m.addContext(ctx, AnySdkVersion, "a", nonshared, buildPath(ctx, "a"), nil, true, nil)
checkError(t, err, "unknown install path to <uses-library> \"a\"")
}
@ -181,7 +186,7 @@ func TestCLCMaybeAdd(t *testing.T) {
m := make(ClassLoaderContextMap)
a := "a"
m.MaybeAddContext(ctx, &a, nil, nil)
m.MaybeAddContext(ctx, &a, nonshared, nil, nil)
// The library should be added to <uses-library> tags by the manifest_fixer.
t.Run("maybe add", func(t *testing.T) {
@ -203,9 +208,9 @@ func TestCLCMaybeAdd(t *testing.T) {
func TestCLCNestedConditional(t *testing.T) {
ctx := testContext()
m1 := make(ClassLoaderContextMap)
m1.AddContextForSdk(ctx, 42, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
m1.AddContextForSdk(ctx, 42, "a", nonshared, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
m := make(ClassLoaderContextMap)
err := m.addContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), true, m1)
err := m.addContext(ctx, AnySdkVersion, "b", nonshared, buildPath(ctx, "b"), installPath(ctx, "b"), true, m1)
checkError(t, err, "nested class loader context shouldn't have conditional part")
}

View File

@ -426,7 +426,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext, sdkLibraries dex
// (including the java_sdk_library) itself then append any implicit sdk library
// names to the list of sdk libraries to be added to the manifest.
if component, ok := module.(SdkLibraryComponentDependency); ok {
sdkLibraries.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(),
sdkLibraries.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(), true,
component.DexJarBuildPath(), component.DexJarInstallPath())
}

View File

@ -1981,7 +1981,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
dep := ctx.OtherModuleName(m)
if lib, ok := m.(Dependency); ok {
clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep,
clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep, isSharedSdkLibrary(m),
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ExportedSdkLibs())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
@ -1995,6 +1995,11 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
return clcMap
}
func isSharedSdkLibrary(m android.Module) bool {
lib, ok := m.(SdkLibraryDependency)
return ok && lib.IsSharedLibrary()
}
// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
// unconditionally in the future.

View File

@ -1027,7 +1027,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
case libTag:
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.exportedSdkLibs.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
j.exportedSdkLibs.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(), true,
dep.DexJarBuildPath(), dep.DexJarInstallPath())
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
@ -2062,12 +2062,12 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(), true,
j.DexJarBuildPath(), j.DexJarInstallPath())
// A non-SDK library may provide a <uses-library> (the name may be different from the module name).
if lib := proptools.String(j.usesLibraryProperties.Provides_uses_lib); lib != "" {
j.exportedSdkLibs.AddContext(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
j.exportedSdkLibs.AddContext(ctx, lib, true, j.DexJarBuildPath(), j.DexJarInstallPath())
}
j.distFiles = j.GenerateTaggedDistFiles(ctx)
@ -2744,7 +2744,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
case libTag:
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
// names of sdk libs that are directly depended are exported
j.exportedSdkLibs.AddContext(ctx, otherName,
j.exportedSdkLibs.AddContext(ctx, otherName, dep.IsSharedLibrary(),
dep.DexJarBuildPath(), dep.DexJarInstallPath())
}
}
@ -2760,7 +2760,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// add the name of that java_sdk_library to the exported sdk libs to make sure
// that, if necessary, a <uses-library> element for that java_sdk_library is
// added to the Android manifest.
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(), true,
outputFile, installFile)
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)

View File

@ -673,6 +673,11 @@ func (c *commonToSdkLibraryAndImport) apiModuleName(apiScope *apiScope) string {
return c.namingScheme.apiModuleName(apiScope, c.moduleBase.BaseModuleName())
}
// If the SDK library is a shared library.
func (c *commonToSdkLibraryAndImport) IsSharedLibrary() bool {
return c.sharedLibrary()
}
// The component names for different outputs of the java_sdk_library.
//
// They are similar to the names used for the child modules it creates
@ -918,6 +923,9 @@ type SdkLibraryDependency interface {
// jars for the stubs. The latter should only be needed when generating JavaDoc as otherwise
// they are identical to the corresponding header jars.
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths
// If the SDK library is a shared library.
IsSharedLibrary() bool
}
type SdkLibrary struct {