Rework class loader context implementation.
The old representation consisted of a list of libraries (UsesLibraries), a list of optional libraries (OptionalUsesLibraries) and a mapping from library name to its build/install paths (LibraryPaths). The separation into lists and map was necessary because of special handling of compatibility libraries, which is now unified with normal libraries. The new representation is a mapping from target SDK version to a tree structure ClassLoaderContext. Each node of the tree represents a library and contains library name, build/install paths and a slice of subcontexts for dependencies. The same library may occur in the tree multiple times in case it is a dependency of multiple libraries. The order in which libraries are added matters (the resulting tree shape may be different). Test results have to be updated, as the resulting <uses-library> list is reodered (previously it was a sorted list of map keys, and now it is formed by a depth-first preorder traversal of the class loader tree). Test: lunch aosp_cf_x86_phone-userdebug && m Bug: 132357300 Bug: 168686456 Change-Id: I11be8cd2967f004fd58753d7c5fb99fed179cd63
This commit is contained in:
parent
366c7d3a74
commit
8cbc5d269b
14 changed files with 351 additions and 361 deletions
|
@ -16,7 +16,7 @@ package dexpreopt
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"android/soong/android"
|
||||
|
@ -49,39 +49,39 @@ var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)
|
|||
|
||||
const UnknownInstallLibraryPath = "error"
|
||||
|
||||
const AnySdkVersion int = 9999 // should go last in class loader context
|
||||
// AnySdkVersion means that the class loader context is needed regardless of the targetSdkVersion
|
||||
// of the app. The numeric value affects the key order in the map and, as a result, the order of
|
||||
// arguments passed to construct_context.py (high value means that the unconditional context goes
|
||||
// last). We use the converntional "current" SDK level (10000), but any big number would do as well.
|
||||
const AnySdkVersion int = android.FutureApiLevelInt
|
||||
|
||||
// LibraryPath contains paths to the library DEX jar on host and on device.
|
||||
type LibraryPath struct {
|
||||
Host android.Path
|
||||
// ClassLoaderContext is a tree of libraries used by the dexpreopted module with their dependencies.
|
||||
// The context is used by dex2oat to compile the module and recorded in the AOT-compiled files, so
|
||||
// that it can be checked agains the run-time class loader context on device. If there is a mismatch
|
||||
// at runtime, AOT-compiled code is rejected.
|
||||
type ClassLoaderContext struct {
|
||||
// The name of the library (same as the name of the module that contains it).
|
||||
Name string
|
||||
|
||||
// On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
|
||||
Host android.Path
|
||||
|
||||
// On-device install path (used in dex2oat argument --stored-class-loader-context).
|
||||
Device string
|
||||
|
||||
// Nested class loader subcontexts for dependencies.
|
||||
Subcontexts []*ClassLoaderContext
|
||||
}
|
||||
|
||||
// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
|
||||
type LibraryPaths map[string]*LibraryPath
|
||||
// ClassLoaderContextMap is a map from SDK version to a class loader context.
|
||||
// There is a special entry with key AnySdkVersion that stores unconditional class loader context.
|
||||
// Other entries store conditional contexts that should be added for some apps that have
|
||||
// targetSdkVersion in the manifest lower than the key SDK version.
|
||||
type ClassLoaderContextMap map[int][]*ClassLoaderContext
|
||||
|
||||
type classLoaderContext struct {
|
||||
// Library names
|
||||
Names []string
|
||||
|
||||
// The class loader context using paths in the build.
|
||||
Host android.Paths
|
||||
|
||||
// The class loader context using paths as they will be on the device.
|
||||
Target []string
|
||||
}
|
||||
|
||||
// A map of class loader contexts for each SDK version.
|
||||
// A map entry for "any" version contains libraries that are unconditionally added to class loader
|
||||
// context. Map entries for existing versions contains libraries that were in the default classpath
|
||||
// until that API version, and should be added to class loader context if and only if the
|
||||
// targetSdkVersion in the manifest or APK is less than that API version.
|
||||
type classLoaderContextMap map[int]*classLoaderContext
|
||||
|
||||
// Add a new library path to the map, unless a path for this library already exists.
|
||||
// If necessary, check that the build and install paths exist.
|
||||
func (libPaths LibraryPaths) addLibraryPath(ctx android.ModuleInstallPathContext, lib string,
|
||||
hostPath, installPath android.Path, strict bool) error {
|
||||
// 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 {
|
||||
|
||||
// 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
|
||||
|
@ -89,263 +89,254 @@ func (libPaths LibraryPaths) addLibraryPath(ctx android.ModuleInstallPathContext
|
|||
strict = strict && !ctx.Config().AllowMissingDependencies()
|
||||
|
||||
if hostPath == nil && strict {
|
||||
return fmt.Errorf("unknown build path to <uses-library> '%s'", lib)
|
||||
return fmt.Errorf("unknown build path to <uses-library> \"%s\"", lib)
|
||||
}
|
||||
|
||||
devicePath := UnknownInstallLibraryPath
|
||||
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 {
|
||||
return fmt.Errorf("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 {
|
||||
var devicePath string
|
||||
if installPath != nil {
|
||||
devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
|
||||
return fmt.Errorf("unknown install path to <uses-library> \"%s\"", lib)
|
||||
} else {
|
||||
// For some stub libraries the only known thing is the name of their implementation
|
||||
// library, but the library itself is unavailable (missing or part of a prebuilt). In
|
||||
// such cases we still need to add the library to <uses-library> tags in the manifest,
|
||||
// but we cannot use if for dexpreopt.
|
||||
devicePath = UnknownInstallLibraryPath
|
||||
// but we cannot use it for dexpreopt.
|
||||
}
|
||||
libPaths[lib] = &LibraryPath{hostPath, devicePath}
|
||||
}
|
||||
if installPath != nil {
|
||||
devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
|
||||
}
|
||||
|
||||
subcontexts := nestedClcMap[AnySdkVersion]
|
||||
|
||||
// If the library with this name is already present as one of the unconditional top-level
|
||||
// components, do not re-add it.
|
||||
for _, clc := range clcMap[sdkVer] {
|
||||
if clc.Name == lib {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
|
||||
Name: lib,
|
||||
Host: hostPath,
|
||||
Device: devicePath,
|
||||
Subcontexts: subcontexts,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Wrapper around addLibraryPath that does error reporting.
|
||||
func (libPaths LibraryPaths) addLibraryPathOrReportError(ctx android.ModuleInstallPathContext, lib string,
|
||||
hostPath, installPath android.Path, strict bool) {
|
||||
// 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) {
|
||||
|
||||
err := libPaths.addLibraryPath(ctx, lib, hostPath, installPath, strict)
|
||||
err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, strict, nestedClcMap)
|
||||
if err != nil {
|
||||
ctx.ModuleErrorf(err.Error())
|
||||
android.ReportPathErrorf(ctx, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new library path to the map. Enforce checks that the library paths exist.
|
||||
func (libPaths LibraryPaths) AddLibraryPath(ctx android.ModuleInstallPathContext, lib string, hostPath, installPath android.Path) {
|
||||
libPaths.addLibraryPathOrReportError(ctx, lib, hostPath, installPath, true)
|
||||
// Add class loader context. Fail on unknown build/install paths.
|
||||
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
|
||||
hostPath, installPath android.Path) {
|
||||
|
||||
clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, hostPath, installPath, true, nil)
|
||||
}
|
||||
|
||||
// Add a new library path to the map, if the library exists (name is not nil).
|
||||
// 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.ModuleInstallPathContext, lib *string, hostPath, installPath android.Path) {
|
||||
// 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) {
|
||||
|
||||
if lib != nil {
|
||||
libPaths.addLibraryPathOrReportError(ctx, *lib, hostPath, installPath, false)
|
||||
clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, hostPath, installPath, false, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Add library paths from the second map to the first map (do not override existing entries).
|
||||
func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
|
||||
for lib, path := range otherPaths {
|
||||
if _, present := libPaths[lib]; !present {
|
||||
libPaths[lib] = path
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
|
||||
clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, true, nestedClcMap)
|
||||
}
|
||||
|
||||
func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
|
||||
if _, ok := m[sdkVer]; !ok {
|
||||
m[sdkVer] = &classLoaderContext{}
|
||||
}
|
||||
return m[sdkVer]
|
||||
}
|
||||
|
||||
func (clc *classLoaderContext) addLib(lib string, hostPath android.Path, targetPath string) {
|
||||
clc.Names = append(clc.Names, lib)
|
||||
clc.Host = append(clc.Host, hostPath)
|
||||
clc.Target = append(clc.Target, targetPath)
|
||||
}
|
||||
|
||||
func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig,
|
||||
libs ...string) (bool, error) {
|
||||
|
||||
clc := m.getValue(sdkVer)
|
||||
for _, lib := range libs {
|
||||
if p, ok := module.LibraryPaths[lib]; ok && p.Host != nil && p.Device != UnknownInstallLibraryPath {
|
||||
clc.addLib(lib, p.Host, p.Device)
|
||||
} else {
|
||||
if sdkVer == AnySdkVersion {
|
||||
// Fail the build if dexpreopt doesn't know paths to one of the <uses-library>
|
||||
// dependencies. In the future we may need to relax this and just disable dexpreopt.
|
||||
return false, fmt.Errorf("dexpreopt cannot find path for <uses-library> '%s'", lib)
|
||||
} else {
|
||||
// No error for compatibility libraries, as Soong doesn't know if they are needed
|
||||
// (this depends on the targetSdkVersion in the manifest).
|
||||
return false, nil
|
||||
// Merge the other class loader context map into this one, do not override existing entries.
|
||||
func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContextMap) {
|
||||
for sdkVer, otherClcs := range otherClcMap {
|
||||
for _, otherClc := range otherClcs {
|
||||
alreadyHave := false
|
||||
for _, clc := range clcMap[sdkVer] {
|
||||
if clc.Name == otherClc.Name {
|
||||
alreadyHave = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !alreadyHave {
|
||||
clcMap[sdkVer] = append(clcMap[sdkVer], otherClc)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
|
||||
clc := m.getValue(sdkVer)
|
||||
for _, lib := range libs {
|
||||
clc.addLib(lib, SystemServerDexJarHostPath(ctx, lib), filepath.Join("/system/framework", lib+".jar"))
|
||||
// List of libraries in the unconditional class loader context, excluding dependencies of shared libraries.
|
||||
func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
|
||||
if clcMap != nil {
|
||||
// compatibility libraries (those in conditional context) are not added to <uses-library> tags
|
||||
ulibs = usesLibsRec(clcMap[AnySdkVersion])
|
||||
ulibs = android.FirstUniqueStrings(ulibs)
|
||||
}
|
||||
return ulibs
|
||||
}
|
||||
|
||||
func (m classLoaderContextMap) usesLibs() []string {
|
||||
if clc, ok := m[AnySdkVersion]; ok {
|
||||
return clc.Names
|
||||
func usesLibsRec(clcs []*ClassLoaderContext) (ulibs []string) {
|
||||
for _, clc := range clcs {
|
||||
ulibs = append(ulibs, clc.Name)
|
||||
ulibs = append(ulibs, usesLibsRec(clc.Subcontexts)...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// genClassLoaderContext generates host and target class loader context to be passed to the dex2oat
|
||||
// command for the dexpreopted module. There are three possible cases:
|
||||
//
|
||||
// 1. System server jars. They have a special class loader context that includes other system
|
||||
// server jars.
|
||||
//
|
||||
// 2. Library jars or APKs which have precise list of their <uses-library> libs. Their class loader
|
||||
// context includes build and on-device paths to these libs. In some cases it may happen that
|
||||
// the path to a <uses-library> is unknown (e.g. the dexpreopted module may depend on stubs
|
||||
// library, whose implementation library is missing from the build altogether). In such case
|
||||
// dexpreopting with the <uses-library> is impossible, and dexpreopting without it is pointless,
|
||||
// as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
|
||||
// such cases the function returns nil, which disables dexpreopt.
|
||||
//
|
||||
// 3. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
|
||||
// the unsafe &-classpath workaround that means empty class loader context and absence of runtime
|
||||
// check that the class loader context provided by the PackageManager agrees with the stored
|
||||
// class loader context recorded in the .odex file.
|
||||
//
|
||||
func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) (*classLoaderContextMap, error) {
|
||||
classLoaderContexts := make(classLoaderContextMap)
|
||||
systemServerJars := NonUpdatableSystemServerJars(ctx, global)
|
||||
|
||||
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
||||
// System server jars should be dexpreopted together: class loader context of each jar
|
||||
// should include all preceding jars on the system server classpath.
|
||||
classLoaderContexts.addSystemServerLibs(AnySdkVersion, ctx, module, systemServerJars[:jarIndex]...)
|
||||
|
||||
} else if module.EnforceUsesLibraries {
|
||||
// Unconditional class loader context.
|
||||
usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
|
||||
if ok, err := classLoaderContexts.addLibs(ctx, AnySdkVersion, module, usesLibs...); !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Conditional class loader context for API version < 28.
|
||||
const httpLegacy = "org.apache.http.legacy"
|
||||
if ok, err := classLoaderContexts.addLibs(ctx, 28, module, httpLegacy); !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Conditional class loader context for API version < 29.
|
||||
usesLibs29 := []string{
|
||||
"android.hidl.base-V1.0-java",
|
||||
"android.hidl.manager-V1.0-java",
|
||||
}
|
||||
if ok, err := classLoaderContexts.addLibs(ctx, 29, module, usesLibs29...); !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Conditional class loader context for API version < 30.
|
||||
if ok, err := classLoaderContexts.addLibs(ctx, 30, module, OptionalCompatUsesLibs30...); !ok {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
} else {
|
||||
// Pass special class loader context to skip the classpath and collision check.
|
||||
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
|
||||
// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
|
||||
// to the &.
|
||||
}
|
||||
|
||||
fixConditionalClassLoaderContext(classLoaderContexts)
|
||||
|
||||
return &classLoaderContexts, nil
|
||||
return ulibs
|
||||
}
|
||||
|
||||
// Now that the full unconditional context is known, reconstruct conditional context.
|
||||
// Apply filters for individual libraries, mirroring what the PackageManager does when it
|
||||
// constructs class loader context on device.
|
||||
//
|
||||
// TODO(b/132357300):
|
||||
// - remove android.hidl.manager and android.hidl.base unless the app is a system app.
|
||||
// TODO(b/132357300): remove "android.hidl.manager" and "android.hidl.base" for non-system apps.
|
||||
//
|
||||
func fixConditionalClassLoaderContext(clcMap classLoaderContextMap) {
|
||||
usesLibs := clcMap.usesLibs()
|
||||
func fixClassLoaderContext(clcMap ClassLoaderContextMap) {
|
||||
usesLibs := clcMap.UsesLibs()
|
||||
|
||||
for sdkVer, clc := range clcMap {
|
||||
for sdkVer, clcs := range clcMap {
|
||||
if sdkVer == AnySdkVersion {
|
||||
continue
|
||||
}
|
||||
clcMap[sdkVer] = &classLoaderContext{}
|
||||
for i, lib := range clc.Names {
|
||||
if android.InList(lib, usesLibs) {
|
||||
fixedClcs := []*ClassLoaderContext{}
|
||||
for _, clc := range clcs {
|
||||
if android.InList(clc.Name, usesLibs) {
|
||||
// skip compatibility libraries that are already included in unconditional context
|
||||
} else if lib == AndroidTestMock && !android.InList("android.test.runner", usesLibs) {
|
||||
} else if clc.Name == AndroidTestMock && !android.InList("android.test.runner", usesLibs) {
|
||||
// android.test.mock is only needed as a compatibility library (in conditional class
|
||||
// loader context) if android.test.runner is used, otherwise skip it
|
||||
} else {
|
||||
clcMap[sdkVer].addLib(lib, clc.Host[i], clc.Target[i])
|
||||
fixedClcs = append(fixedClcs, clc)
|
||||
}
|
||||
clcMap[sdkVer] = fixedClcs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return the class loader context as a string and a slice of build paths for all dependencies.
|
||||
func computeClassLoaderContext(ctx android.PathContext, clcMap classLoaderContextMap) (clcStr string, paths android.Paths) {
|
||||
for _, ver := range android.SortedIntKeys(clcMap) {
|
||||
clc := clcMap.getValue(ver)
|
||||
|
||||
clcLen := len(clc.Names)
|
||||
if clcLen != len(clc.Host) || clcLen != len(clc.Target) {
|
||||
android.ReportPathErrorf(ctx, "ill-formed class loader context")
|
||||
// Return true if all build/install library paths are valid (including recursive subcontexts),
|
||||
// otherwise return false. A build path is valid if it's not nil. An install path is valid if it's
|
||||
// not equal to a special "error" value.
|
||||
func validateClassLoaderContext(clcMap ClassLoaderContextMap) (bool, error) {
|
||||
for sdkVer, clcs := range clcMap {
|
||||
if valid, err := validateClassLoaderContextRec(sdkVer, clcs); !valid || err != nil {
|
||||
return valid, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var hostClc, targetClc []string
|
||||
var hostPaths android.Paths
|
||||
|
||||
for i := 0; i < clcLen; i++ {
|
||||
hostStr := "PCL[" + clc.Host[i].String() + "]"
|
||||
targetStr := "PCL[" + clc.Target[i] + "]"
|
||||
|
||||
hostClc = append(hostClc, hostStr)
|
||||
targetClc = append(targetClc, targetStr)
|
||||
hostPaths = append(hostPaths, clc.Host[i])
|
||||
func validateClassLoaderContextRec(sdkVer int, clcs []*ClassLoaderContext) (bool, error) {
|
||||
for _, clc := range clcs {
|
||||
if clc.Host == nil || clc.Device == UnknownInstallLibraryPath {
|
||||
if sdkVer == AnySdkVersion {
|
||||
// Return error if dexpreopt doesn't know paths to one of the <uses-library>
|
||||
// dependencies. In the future we may need to relax this and just disable dexpreopt.
|
||||
return false, fmt.Errorf("invalid path for <uses-library> \"%s\"", clc.Name)
|
||||
} else {
|
||||
// No error for compatibility libraries, as Soong doesn't know if they are needed
|
||||
// (this depends on the targetSdkVersion in the manifest), but the CLC is invalid.
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
if valid, err := validateClassLoaderContextRec(sdkVer, clc.Subcontexts); !valid || err != nil {
|
||||
return valid, err
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Return the class loader context as a string, and a slice of build paths for all dependencies.
|
||||
// Perform a depth-first preorder traversal of the class loader context tree for each SDK version.
|
||||
// Return the resulting string and a slice of on-host build paths to all library dependencies.
|
||||
func ComputeClassLoaderContext(clcMap ClassLoaderContextMap) (clcStr string, paths android.Paths) {
|
||||
for _, sdkVer := range android.SortedIntKeys(clcMap) { // determinisitc traversal order
|
||||
sdkVerStr := fmt.Sprintf("%d", sdkVer)
|
||||
if sdkVer == AnySdkVersion {
|
||||
sdkVerStr = "any" // a special keyword that means any SDK version
|
||||
}
|
||||
hostClc, targetClc, hostPaths := computeClassLoaderContextRec(clcMap[sdkVer])
|
||||
if hostPaths != nil {
|
||||
sdkVerStr := fmt.Sprintf("%d", ver)
|
||||
if ver == AnySdkVersion {
|
||||
sdkVerStr = "any" // a special keyword that means any SDK version
|
||||
}
|
||||
clcStr += fmt.Sprintf(" --host-context-for-sdk %s %s", sdkVerStr, strings.Join(hostClc, "#"))
|
||||
clcStr += fmt.Sprintf(" --target-context-for-sdk %s %s", sdkVerStr, strings.Join(targetClc, "#"))
|
||||
paths = append(paths, hostPaths...)
|
||||
clcStr += fmt.Sprintf(" --host-context-for-sdk %s %s", sdkVerStr, hostClc)
|
||||
clcStr += fmt.Sprintf(" --target-context-for-sdk %s %s", sdkVerStr, targetClc)
|
||||
}
|
||||
paths = append(paths, hostPaths...)
|
||||
}
|
||||
|
||||
return clcStr, paths
|
||||
return clcStr, android.FirstUniquePaths(paths)
|
||||
}
|
||||
|
||||
func computeClassLoaderContextRec(clcs []*ClassLoaderContext) (string, string, android.Paths) {
|
||||
var paths android.Paths
|
||||
var clcsHost, clcsTarget []string
|
||||
|
||||
for _, clc := range clcs {
|
||||
subClcHost, subClcTarget, subPaths := computeClassLoaderContextRec(clc.Subcontexts)
|
||||
if subPaths != nil {
|
||||
subClcHost = "{" + subClcHost + "}"
|
||||
subClcTarget = "{" + subClcTarget + "}"
|
||||
}
|
||||
|
||||
clcsHost = append(clcsHost, "PCL["+clc.Host.String()+"]"+subClcHost)
|
||||
clcsTarget = append(clcsTarget, "PCL["+clc.Device+"]"+subClcTarget)
|
||||
|
||||
paths = append(paths, clc.Host)
|
||||
paths = append(paths, subPaths...)
|
||||
}
|
||||
|
||||
clcHost := strings.Join(clcsHost, "#")
|
||||
clcTarget := strings.Join(clcsTarget, "#")
|
||||
|
||||
return clcHost, clcTarget, paths
|
||||
}
|
||||
|
||||
// Paths to a <uses-library> on host and on device.
|
||||
type jsonLibraryPath struct {
|
||||
Host string
|
||||
Device string
|
||||
}
|
||||
|
||||
type jsonLibraryPaths map[string]jsonLibraryPath
|
||||
// Class loader contexts that come from Make (via JSON dexpreopt.config) files have simpler
|
||||
// structure than Soong class loader contexts: they are flat maps from a <uses-library> name to its
|
||||
// on-host and on-device paths. There are no nested subcontexts. It is a limitation of the current
|
||||
// Make implementation.
|
||||
type jsonClassLoaderContext map[string]jsonLibraryPath
|
||||
|
||||
// convert JSON map of library paths to LibraryPaths
|
||||
func constructLibraryPaths(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
|
||||
m := LibraryPaths{}
|
||||
for lib, path := range paths {
|
||||
m[lib] = &LibraryPath{
|
||||
constructPath(ctx, path.Host),
|
||||
path.Device,
|
||||
// A map from SDK version (represented with a JSON string) to JSON class loader context.
|
||||
type jsonClassLoaderContextMap map[string]jsonClassLoaderContext
|
||||
|
||||
// Convert JSON class loader context map to ClassLoaderContextMap.
|
||||
func fromJsonClassLoaderContext(ctx android.PathContext, jClcMap jsonClassLoaderContextMap) ClassLoaderContextMap {
|
||||
clcMap := make(ClassLoaderContextMap)
|
||||
for sdkVerStr, clc := range jClcMap {
|
||||
sdkVer, ok := strconv.Atoi(sdkVerStr)
|
||||
if ok != nil {
|
||||
if sdkVerStr == "any" {
|
||||
sdkVer = AnySdkVersion
|
||||
} else {
|
||||
android.ReportPathErrorf(ctx, "failed to parse SDK version in dexpreopt.config: '%s'", sdkVerStr)
|
||||
}
|
||||
}
|
||||
for lib, path := range clc {
|
||||
clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
|
||||
Name: lib,
|
||||
Host: constructPath(ctx, path.Host),
|
||||
Device: path.Device,
|
||||
Subcontexts: nil,
|
||||
})
|
||||
}
|
||||
}
|
||||
return m
|
||||
return clcMap
|
||||
}
|
||||
|
|
|
@ -37,91 +37,74 @@ func TestCLC(t *testing.T) {
|
|||
// ├── b
|
||||
// ├── c
|
||||
// ├── d
|
||||
// ├── a2
|
||||
// ├── b2
|
||||
// ├── c2
|
||||
// ├── a1
|
||||
// ├── b1
|
||||
// │ ├── a2
|
||||
// │ ├── b2
|
||||
// │ └── c2
|
||||
// │ ├── a1
|
||||
// │ └── b1
|
||||
// ├── f
|
||||
// ├── a3
|
||||
// └── b3
|
||||
//
|
||||
ctx := testContext()
|
||||
|
||||
lp := make(LibraryPaths)
|
||||
m := make(ClassLoaderContextMap)
|
||||
|
||||
lp.AddLibraryPath(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
|
||||
lp.AddLibraryPath(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
|
||||
m.AddContext(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
|
||||
m.AddContext(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
|
||||
|
||||
// "Maybe" variant in the good case: add as usual.
|
||||
c := "c"
|
||||
lp.MaybeAddLibraryPath(ctx, &c, buildPath(ctx, "c"), installPath(ctx, "c"))
|
||||
m.MaybeAddContext(ctx, &c, buildPath(ctx, "c"), installPath(ctx, "c"))
|
||||
|
||||
// "Maybe" variant in the bad case: don't add library with unknown name, keep going.
|
||||
lp.MaybeAddLibraryPath(ctx, nil, nil, nil)
|
||||
m.MaybeAddContext(ctx, nil, nil, nil)
|
||||
|
||||
// Add some libraries with nested subcontexts.
|
||||
|
||||
lp1 := make(LibraryPaths)
|
||||
lp1.AddLibraryPath(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
|
||||
lp1.AddLibraryPath(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
|
||||
m1 := make(ClassLoaderContextMap)
|
||||
m1.AddContext(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
|
||||
m1.AddContext(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
|
||||
|
||||
lp2 := make(LibraryPaths)
|
||||
lp2.AddLibraryPath(ctx, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"))
|
||||
lp2.AddLibraryPath(ctx, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"))
|
||||
lp2.AddLibraryPath(ctx, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"))
|
||||
lp2.AddLibraryPaths(lp1)
|
||||
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)
|
||||
|
||||
lp.AddLibraryPath(ctx, "d", buildPath(ctx, "d"), installPath(ctx, "d"))
|
||||
lp.AddLibraryPaths(lp2)
|
||||
m3 := make(ClassLoaderContextMap)
|
||||
m3.AddContext(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
|
||||
m3.AddContext(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
|
||||
|
||||
lp3 := make(LibraryPaths)
|
||||
lp3.AddLibraryPath(ctx, "f", buildPath(ctx, "f"), installPath(ctx, "f"))
|
||||
lp3.AddLibraryPath(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
|
||||
lp3.AddLibraryPath(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
|
||||
lp.AddLibraryPaths(lp3)
|
||||
m.AddContextForSdk(ctx, AnySdkVersion, "d", 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.AddContextMap(m3)
|
||||
|
||||
// Compatibility libraries with unknown install paths get default paths.
|
||||
lp.AddLibraryPath(ctx, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil)
|
||||
lp.AddLibraryPath(ctx, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil)
|
||||
lp.AddLibraryPath(ctx, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil)
|
||||
|
||||
module := testSystemModuleConfig(ctx, "test")
|
||||
module.LibraryPaths = lp
|
||||
|
||||
m := make(classLoaderContextMap)
|
||||
valid := true
|
||||
|
||||
ok, err := m.addLibs(ctx, AnySdkVersion, module, "a", "b", "c", "d", "a2", "b2", "c2", "a1", "b1", "f", "a3", "b3")
|
||||
valid = valid && ok && err == nil
|
||||
|
||||
// Add compatibility libraries to conditional CLC for SDK level 29.
|
||||
ok, err = m.addLibs(ctx, 29, module, AndroidHidlManager, AndroidHidlBase)
|
||||
valid = valid && ok && err == nil
|
||||
m.AddContextForSdk(ctx, 29, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil, nil)
|
||||
m.AddContextForSdk(ctx, 29, AndroidHidlBase, 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.
|
||||
ok, err = m.addLibs(ctx, 30, module, AndroidTestMock)
|
||||
valid = valid && ok && err == nil
|
||||
m.AddContextForSdk(ctx, 30, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil, nil)
|
||||
|
||||
// When the same library is both in conditional and unconditional context, it should be removed
|
||||
// from conditional context.
|
||||
ok, err = m.addLibs(ctx, 42, module, "f")
|
||||
valid = valid && ok && err == nil
|
||||
valid, validationError := validateClassLoaderContext(m)
|
||||
|
||||
fixConditionalClassLoaderContext(m)
|
||||
fixClassLoaderContext(m)
|
||||
|
||||
var haveStr string
|
||||
var havePaths android.Paths
|
||||
var haveUsesLibs []string
|
||||
if valid {
|
||||
haveStr, havePaths = computeClassLoaderContext(ctx, m)
|
||||
haveUsesLibs = m.usesLibs()
|
||||
if valid && validationError == nil {
|
||||
haveStr, havePaths = ComputeClassLoaderContext(m)
|
||||
haveUsesLibs = m.UsesLibs()
|
||||
}
|
||||
|
||||
// Test that validation is successful (all paths are known).
|
||||
t.Run("validate", func(t *testing.T) {
|
||||
if !valid {
|
||||
if !(valid && validationError == nil) {
|
||||
t.Errorf("invalid class loader context")
|
||||
}
|
||||
})
|
||||
|
@ -135,14 +118,14 @@ func TestCLC(t *testing.T) {
|
|||
"PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
|
||||
"PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
|
||||
" --host-context-for-sdk any " +
|
||||
"PCL[out/a.jar]#PCL[out/b.jar]#PCL[out/c.jar]#PCL[out/d.jar]#" +
|
||||
"PCL[out/a2.jar]#PCL[out/b2.jar]#PCL[out/c2.jar]#" +
|
||||
"PCL[out/a1.jar]#PCL[out/b1.jar]#" +
|
||||
"PCL[out/a.jar]#PCL[out/b.jar]#PCL[out/c.jar]#PCL[out/d.jar]" +
|
||||
"{PCL[out/a2.jar]#PCL[out/b2.jar]#PCL[out/c2.jar]" +
|
||||
"{PCL[out/a1.jar]#PCL[out/b1.jar]}}#" +
|
||||
"PCL[out/f.jar]#PCL[out/a3.jar]#PCL[out/b3.jar]" +
|
||||
" --target-context-for-sdk any " +
|
||||
"PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.jar]#" +
|
||||
"PCL[/system/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]#" +
|
||||
"PCL[/system/a1.jar]#PCL[/system/b1.jar]#" +
|
||||
"PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.jar]" +
|
||||
"{PCL[/system/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]" +
|
||||
"{PCL[/system/a1.jar]#PCL[/system/b1.jar]}}#" +
|
||||
"PCL[/system/f.jar]#PCL[/system/a3.jar]#PCL[/system/b3.jar]"
|
||||
if wantStr != haveStr {
|
||||
t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
|
||||
|
@ -175,32 +158,40 @@ func TestCLC(t *testing.T) {
|
|||
// Test that an unexpected unknown build path causes immediate error.
|
||||
func TestCLCUnknownBuildPath(t *testing.T) {
|
||||
ctx := testContext()
|
||||
lp := make(LibraryPaths)
|
||||
err := lp.addLibraryPath(ctx, "a", nil, nil, true)
|
||||
checkError(t, err, "unknown build path to <uses-library> 'a'")
|
||||
m := make(ClassLoaderContextMap)
|
||||
err := m.addContext(ctx, AnySdkVersion, "a", nil, nil, true, nil)
|
||||
checkError(t, err, "unknown build path to <uses-library> \"a\"")
|
||||
}
|
||||
|
||||
// Test that an unexpected unknown install path causes immediate error.
|
||||
func TestCLCUnknownInstallPath(t *testing.T) {
|
||||
ctx := testContext()
|
||||
lp := make(LibraryPaths)
|
||||
err := lp.addLibraryPath(ctx, "a", buildPath(ctx, "a"), nil, true)
|
||||
checkError(t, err, "unknown install path to <uses-library> 'a'")
|
||||
m := make(ClassLoaderContextMap)
|
||||
err := m.addContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), nil, true, nil)
|
||||
checkError(t, err, "unknown install path to <uses-library> \"a\"")
|
||||
}
|
||||
|
||||
func TestCLCMaybeAdd(t *testing.T) {
|
||||
ctx := testContext()
|
||||
|
||||
lp := make(LibraryPaths)
|
||||
m := make(ClassLoaderContextMap)
|
||||
a := "a"
|
||||
lp.MaybeAddLibraryPath(ctx, &a, nil, nil)
|
||||
m.MaybeAddContext(ctx, &a, nil, nil)
|
||||
|
||||
module := testSystemModuleConfig(ctx, "test")
|
||||
module.LibraryPaths = lp
|
||||
// The library should be added to <uses-library> tags by the manifest_fixer.
|
||||
t.Run("maybe add", func(t *testing.T) {
|
||||
haveUsesLibs := m.UsesLibs()
|
||||
wantUsesLibs := []string{"a"}
|
||||
if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
|
||||
t.Errorf("\nwant uses libs: %s\nhave uses libs: %s", wantUsesLibs, haveUsesLibs)
|
||||
}
|
||||
})
|
||||
|
||||
m := make(classLoaderContextMap)
|
||||
_, err := m.addLibs(ctx, AnySdkVersion, module, "a")
|
||||
checkError(t, err, "dexpreopt cannot find path for <uses-library> 'a'")
|
||||
// But class loader context in such cases should raise an error on validation.
|
||||
t.Run("validate", func(t *testing.T) {
|
||||
_, err := validateClassLoaderContext(m)
|
||||
checkError(t, err, "invalid path for <uses-library> \"a\"")
|
||||
})
|
||||
}
|
||||
|
||||
func checkError(t *testing.T, have error, want string) {
|
||||
|
|
|
@ -114,10 +114,8 @@ type ModuleConfig struct {
|
|||
ProfileIsTextListing bool
|
||||
ProfileBootListing android.OptionalPath
|
||||
|
||||
EnforceUsesLibraries bool
|
||||
OptionalUsesLibraries []string
|
||||
UsesLibraries []string
|
||||
LibraryPaths LibraryPaths
|
||||
EnforceUsesLibraries bool
|
||||
ClassLoaderContexts ClassLoaderContextMap
|
||||
|
||||
Archs []android.ArchType
|
||||
DexPreoptImages []android.Path
|
||||
|
@ -265,7 +263,7 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
|
|||
DexPath string
|
||||
ManifestPath string
|
||||
ProfileClassListing string
|
||||
LibraryPaths jsonLibraryPaths
|
||||
ClassLoaderContexts jsonClassLoaderContextMap
|
||||
DexPreoptImages []string
|
||||
DexPreoptImageLocations []string
|
||||
PreoptBootClassPathDexFiles []string
|
||||
|
@ -283,7 +281,7 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
|
|||
config.ModuleConfig.DexPath = constructPath(ctx, config.DexPath)
|
||||
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
|
||||
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
|
||||
config.ModuleConfig.LibraryPaths = constructLibraryPaths(ctx, config.LibraryPaths)
|
||||
config.ModuleConfig.ClassLoaderContexts = fromJsonClassLoaderContext(ctx, config.ClassLoaderContexts)
|
||||
config.ModuleConfig.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
|
||||
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
|
||||
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
|
||||
|
|
|
@ -81,16 +81,18 @@ func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConf
|
|||
}
|
||||
|
||||
if !dexpreoptDisabled(ctx, global, module) {
|
||||
if clc, err := genClassLoaderContext(ctx, global, module); err != nil {
|
||||
if valid, err := validateClassLoaderContext(module.ClassLoaderContexts); err != nil {
|
||||
android.ReportPathErrorf(ctx, err.Error())
|
||||
} else if clc != nil {
|
||||
} else if valid {
|
||||
fixClassLoaderContext(module.ClassLoaderContexts)
|
||||
|
||||
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
|
||||
!module.NoCreateAppImage
|
||||
|
||||
generateDM := shouldGenerateDM(module, global)
|
||||
|
||||
for archIdx, _ := range module.Archs {
|
||||
dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, *clc, profile, appImage, generateDM)
|
||||
dexpreoptCommand(ctx, globalSoong, global, module, rule, archIdx, profile, appImage, generateDM)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -197,8 +199,8 @@ func bootProfileCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig,
|
|||
}
|
||||
|
||||
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
|
||||
profile android.WritablePath, appImage bool, generateDM bool) {
|
||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
|
||||
appImage bool, generateDM bool) {
|
||||
|
||||
arch := module.Archs[archIdx]
|
||||
|
||||
|
@ -235,6 +237,16 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
||||
|
||||
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
||||
// System server jars should be dexpreopted together: class loader context of each jar
|
||||
// should include all preceding jars on the system server classpath.
|
||||
|
||||
var clcHost android.Paths
|
||||
var clcTarget []string
|
||||
for _, lib := range systemServerJars[:jarIndex] {
|
||||
clcHost = append(clcHost, SystemServerDexJarHostPath(ctx, lib))
|
||||
clcTarget = append(clcTarget, filepath.Join("/system/framework", lib+".jar"))
|
||||
}
|
||||
|
||||
// Copy the system server jar to a predefined location where dex2oat will find it.
|
||||
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
|
||||
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
|
||||
|
@ -242,11 +254,11 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||
|
||||
checkSystemServerOrder(ctx, jarIndex)
|
||||
|
||||
clc := classLoaderContexts[AnySdkVersion]
|
||||
rule.Command().
|
||||
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
|
||||
Implicits(clc.Host).
|
||||
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
|
||||
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clcHost.Strings(), ":") + "]").
|
||||
Implicits(clcHost).
|
||||
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
|
||||
|
||||
} else if module.EnforceUsesLibraries {
|
||||
// Generate command that saves target SDK version in a shell variable.
|
||||
if module.ManifestPath != nil {
|
||||
|
@ -266,13 +278,15 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
|||
}
|
||||
|
||||
// Generate command that saves host and target class loader context in shell variables.
|
||||
clc, paths := computeClassLoaderContext(ctx, classLoaderContexts)
|
||||
clc, paths := ComputeClassLoaderContext(module.ClassLoaderContexts)
|
||||
cmd := rule.Command().
|
||||
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
|
||||
Text(` --target-sdk-version ${target_sdk_version}`).
|
||||
Text(clc).Implicits(paths)
|
||||
cmd.Text(`)"`)
|
||||
|
||||
} else {
|
||||
// Other libraries or APKs for which the exact <uses-library> list is unknown.
|
||||
// Pass special class loader context to skip the classpath and collision check.
|
||||
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
|
||||
// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
|
||||
|
|
|
@ -44,9 +44,7 @@ func testModuleConfig(ctx android.PathContext, name, partition string) *ModuleCo
|
|||
ProfileClassListing: android.OptionalPath{},
|
||||
ProfileIsTextListing: false,
|
||||
EnforceUsesLibraries: false,
|
||||
OptionalUsesLibraries: nil,
|
||||
UsesLibraries: nil,
|
||||
LibraryPaths: nil,
|
||||
ClassLoaderContexts: nil,
|
||||
Archs: []android.ArchType{android.Arm},
|
||||
DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
|
||||
DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}},
|
||||
|
|
14
java/aar.go
14
java/aar.go
|
@ -109,7 +109,7 @@ type aapt struct {
|
|||
useEmbeddedNativeLibs bool
|
||||
useEmbeddedDex bool
|
||||
usesNonSdkApis bool
|
||||
sdkLibraries dexpreopt.LibraryPaths
|
||||
sdkLibraries dexpreopt.ClassLoaderContextMap
|
||||
hasNoCode bool
|
||||
LoggingParent string
|
||||
resourceFiles android.Paths
|
||||
|
@ -392,7 +392,7 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex
|
|||
|
||||
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
|
||||
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.Paths,
|
||||
staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries dexpreopt.LibraryPaths) {
|
||||
staticRRODirs []rroDir, assets, deps android.Paths, flags []string, sdkLibraries dexpreopt.ClassLoaderContextMap) {
|
||||
|
||||
var sharedLibs android.Paths
|
||||
|
||||
|
@ -401,7 +401,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
|||
sharedLibs = append(sharedLibs, sdkDep.jars...)
|
||||
}
|
||||
|
||||
sdkLibraries = make(dexpreopt.LibraryPaths)
|
||||
sdkLibraries = make(dexpreopt.ClassLoaderContextMap)
|
||||
|
||||
ctx.VisitDirectDeps(func(module android.Module) {
|
||||
var exportPackage android.Path
|
||||
|
@ -411,7 +411,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
|||
}
|
||||
|
||||
if dep, ok := module.(Dependency); ok {
|
||||
sdkLibraries.AddLibraryPaths(dep.ExportedSdkLibs())
|
||||
sdkLibraries.AddContextMap(dep.ExportedSdkLibs())
|
||||
}
|
||||
|
||||
switch ctx.OtherModuleDependencyTag(module) {
|
||||
|
@ -426,7 +426,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
|||
// (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.MaybeAddLibraryPath(ctx, component.OptionalImplicitSdkLibrary(),
|
||||
sdkLibraries.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(),
|
||||
component.DexJarBuildPath(), component.DexJarInstallPath())
|
||||
}
|
||||
|
||||
|
@ -439,7 +439,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
|||
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
|
||||
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
|
||||
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
|
||||
sdkLibraries.AddLibraryPaths(aarDep.ExportedSdkLibs())
|
||||
sdkLibraries.AddContextMap(aarDep.ExportedSdkLibs())
|
||||
if aarDep.ExportedAssets().Valid() {
|
||||
assets = append(assets, aarDep.ExportedAssets().Path())
|
||||
}
|
||||
|
@ -827,7 +827,7 @@ func (a *AARImport) AidlIncludeDirs() android.Paths {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (a *AARImport) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
||||
func (a *AARImport) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,9 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
|
|||
"args", "libs")
|
||||
|
||||
// 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,
|
||||
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
|
||||
func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
|
||||
sdkLibraries dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
|
||||
useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
|
||||
|
||||
var args []string
|
||||
if isLibrary {
|
||||
|
@ -70,7 +71,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
|
|||
args = append(args, "--use-embedded-dex")
|
||||
}
|
||||
|
||||
for _, usesLib := range android.SortedStringKeys(sdkLibraries) {
|
||||
for _, usesLib := range sdkLibraries.UsesLibs() {
|
||||
if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
|
||||
args = append(args, "--optional-uses-library", usesLib)
|
||||
} else {
|
||||
|
|
|
@ -115,7 +115,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
|||
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
|
||||
}
|
||||
|
||||
entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", android.SortedStringKeys(library.exportedSdkLibs)...)
|
||||
entries.AddStrings("LOCAL_EXPORT_SDK_LIBRARIES", library.exportedSdkLibs.UsesLibs()...)
|
||||
|
||||
if len(library.additionalCheckedModules) != 0 {
|
||||
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
|
||||
|
|
29
java/app.go
29
java/app.go
|
@ -601,7 +601,7 @@ func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath
|
|||
return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
|
||||
}
|
||||
|
||||
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext, sdkLibs dexpreopt.LibraryPaths) android.Path {
|
||||
func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext, sdkLibs dexpreopt.ClassLoaderContextMap) android.Path {
|
||||
a.dexpreopter.installPath = a.installPath(ctx)
|
||||
if a.dexProperties.Uncompress_dex == nil {
|
||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
||||
|
@ -609,12 +609,10 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext, sdkLibs dexpreop
|
|||
}
|
||||
a.dexpreopter.uncompressedDex = *a.dexProperties.Uncompress_dex
|
||||
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
||||
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
||||
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
||||
a.dexpreopter.libraryPaths.AddLibraryPaths(sdkLibs)
|
||||
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
|
||||
a.dexpreopter.classLoaderContexts.AddContextMap(sdkLibs)
|
||||
a.dexpreopter.manifestFile = a.mergedManifestFile
|
||||
a.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
||||
a.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||
|
||||
if ctx.ModuleName() != "framework-res" {
|
||||
a.Module.compile(ctx, a.aaptSrcJar)
|
||||
|
@ -791,7 +789,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
a.usesLibrary.freezeEnforceUsesLibraries()
|
||||
|
||||
// Add implicit SDK libraries to <uses-library> list.
|
||||
for _, usesLib := range android.SortedStringKeys(a.aapt.sdkLibraries) {
|
||||
for _, usesLib := range a.aapt.sdkLibraries.UsesLibs() {
|
||||
a.usesLibrary.addLib(usesLib, inList(usesLib, dexpreopt.OptionalCompatUsesLibs))
|
||||
}
|
||||
|
||||
|
@ -1540,9 +1538,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
|
|||
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||
|
||||
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
||||
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
||||
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
||||
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
|
||||
|
||||
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
|
||||
if a.dexpreopter.uncompressedDex {
|
||||
|
@ -1976,17 +1972,18 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s
|
|||
return optionalUsesLibs
|
||||
}
|
||||
|
||||
// usesLibraryPaths returns a map of module names of shared library dependencies to the paths
|
||||
// Returns a map of module names of shared library dependencies to the paths
|
||||
// to their dex jars on host and on device.
|
||||
func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths {
|
||||
usesLibPaths := make(dexpreopt.LibraryPaths)
|
||||
func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
|
||||
clcMap := make(dexpreopt.ClassLoaderContextMap)
|
||||
|
||||
if !ctx.Config().UnbundledBuild() {
|
||||
ctx.VisitDirectDeps(func(m android.Module) {
|
||||
if _, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
|
||||
if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
|
||||
dep := ctx.OtherModuleName(m)
|
||||
if lib, ok := m.(Dependency); ok {
|
||||
usesLibPaths.AddLibraryPath(ctx, dep, lib.DexJarBuildPath(), lib.DexJarInstallPath())
|
||||
clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep,
|
||||
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ExportedSdkLibs())
|
||||
} else if ctx.Config().AllowMissingDependencies() {
|
||||
ctx.AddMissingDependencies([]string{dep})
|
||||
} else {
|
||||
|
@ -1996,7 +1993,7 @@ func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.Libr
|
|||
})
|
||||
}
|
||||
|
||||
return usesLibPaths
|
||||
return clcMap
|
||||
}
|
||||
|
||||
// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
|
||||
|
|
|
@ -2815,11 +2815,11 @@ func TestUsesLibraries(t *testing.T) {
|
|||
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
|
||||
cmd = app.Rule("dexpreopt").RuleParams.Command
|
||||
w := `--target-context-for-sdk any ` +
|
||||
`PCL[/system/framework/foo.jar]#` +
|
||||
`PCL[/system/framework/quuz.jar]#` +
|
||||
`PCL[/system/framework/qux.jar]#` +
|
||||
`PCL[/system/framework/runtime-library.jar]#` +
|
||||
`PCL[/system/framework/bar.jar]`
|
||||
`PCL[/system/framework/quuz.jar]#` +
|
||||
`PCL[/system/framework/foo.jar]#` +
|
||||
`PCL[/system/framework/bar.jar]#` +
|
||||
`PCL[/system/framework/runtime-library.jar]`
|
||||
if !strings.Contains(cmd, w) {
|
||||
t.Errorf("wanted %q in %q", w, cmd)
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
||||
func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -33,11 +33,9 @@ type dexpreopter struct {
|
|||
isTest bool
|
||||
isPresignedPrebuilt bool
|
||||
|
||||
manifestFile android.Path
|
||||
usesLibs []string
|
||||
optionalUsesLibs []string
|
||||
enforceUsesLibs bool
|
||||
libraryPaths dexpreopt.LibraryPaths
|
||||
manifestFile android.Path
|
||||
enforceUsesLibs bool
|
||||
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
||||
|
||||
builtInstalled string
|
||||
}
|
||||
|
@ -193,10 +191,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
|||
ProfileIsTextListing: profileIsTextListing,
|
||||
ProfileBootListing: profileBootListing,
|
||||
|
||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||
OptionalUsesLibraries: d.optionalUsesLibs,
|
||||
UsesLibraries: d.usesLibs,
|
||||
LibraryPaths: d.libraryPaths,
|
||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||
ClassLoaderContexts: d.classLoaderContexts,
|
||||
|
||||
Archs: archs,
|
||||
DexPreoptImages: images,
|
||||
|
|
36
java/java.go
36
java/java.go
|
@ -416,8 +416,8 @@ type Module struct {
|
|||
// manifest file to use instead of properties.Manifest
|
||||
overrideManifest android.OptionalPath
|
||||
|
||||
// map of SDK libs exported by this java module to their build and install paths
|
||||
exportedSdkLibs dexpreopt.LibraryPaths
|
||||
// map of SDK version to class loader context
|
||||
exportedSdkLibs dexpreopt.ClassLoaderContextMap
|
||||
|
||||
// list of plugins that this java module is exporting
|
||||
exportedPluginJars android.Paths
|
||||
|
@ -509,7 +509,7 @@ type Dependency interface {
|
|||
ImplementationJars() android.Paths
|
||||
ResourceJars() android.Paths
|
||||
AidlIncludeDirs() android.Paths
|
||||
ExportedSdkLibs() dexpreopt.LibraryPaths
|
||||
ExportedSdkLibs() dexpreopt.ClassLoaderContextMap
|
||||
ExportedPlugins() (android.Paths, []string)
|
||||
SrcJarArgs() ([]string, android.Paths)
|
||||
BaseModuleName() string
|
||||
|
@ -1027,7 +1027,8 @@ 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.MaybeAddLibraryPath(ctx, dep.OptionalImplicitSdkLibrary(), dep.DexJarBuildPath(), dep.DexJarInstallPath())
|
||||
j.exportedSdkLibs.MaybeAddContext(ctx, dep.OptionalImplicitSdkLibrary(),
|
||||
dep.DexJarBuildPath(), dep.DexJarInstallPath())
|
||||
case staticLibTag:
|
||||
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
|
||||
}
|
||||
|
@ -1038,7 +1039,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||
case libTag, instrumentationForTag:
|
||||
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
||||
// sdk lib names from dependencies are re-exported
|
||||
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
|
||||
j.exportedSdkLibs.AddContextMap(dep.ExportedSdkLibs())
|
||||
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||
pluginJars, pluginClasses := dep.ExportedPlugins()
|
||||
addPlugins(&deps, pluginJars, pluginClasses...)
|
||||
|
@ -1050,7 +1051,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
|||
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
|
||||
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
|
||||
// sdk lib names from dependencies are re-exported
|
||||
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
|
||||
j.exportedSdkLibs.AddContextMap(dep.ExportedSdkLibs())
|
||||
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||
pluginJars, pluginClasses := dep.ExportedPlugins()
|
||||
addPlugins(&deps, pluginJars, pluginClasses...)
|
||||
|
@ -1902,7 +1903,7 @@ func (j *Module) AidlIncludeDirs() android.Paths {
|
|||
return j.exportAidlIncludeDirs
|
||||
}
|
||||
|
||||
func (j *Module) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
||||
func (j *Module) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||
return j.exportedSdkLibs
|
||||
}
|
||||
|
||||
|
@ -2041,7 +2042,7 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
|
||||
}
|
||||
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
|
||||
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
||||
j.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||
j.compile(ctx, nil)
|
||||
|
||||
// Collect the module directory for IDE info in java/jdeps.go.
|
||||
|
@ -2061,11 +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.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), j.DexJarBuildPath(), j.DexJarInstallPath())
|
||||
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
|
||||
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.AddLibraryPath(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
|
||||
j.exportedSdkLibs.AddContext(ctx, lib, j.DexJarBuildPath(), j.DexJarInstallPath())
|
||||
}
|
||||
|
||||
j.distFiles = j.GenerateTaggedDistFiles(ctx)
|
||||
|
@ -2644,7 +2646,7 @@ type Import struct {
|
|||
dexJarFile android.Path
|
||||
|
||||
combinedClasspathFile android.Path
|
||||
exportedSdkLibs dexpreopt.LibraryPaths
|
||||
exportedSdkLibs dexpreopt.ClassLoaderContextMap
|
||||
exportAidlIncludeDirs android.Paths
|
||||
|
||||
hideApexVariantFromMake bool
|
||||
|
@ -2719,7 +2721,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
TransformJetifier(ctx, outputFile, inputFile)
|
||||
}
|
||||
j.combinedClasspathFile = outputFile
|
||||
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
||||
j.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||
|
||||
var flags javaBuilderFlags
|
||||
|
||||
|
@ -2733,7 +2735,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||
case libTag, staticLibTag:
|
||||
flags.classpath = append(flags.classpath, dep.HeaderJars()...)
|
||||
// sdk lib names from dependencies are re-exported
|
||||
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
|
||||
j.exportedSdkLibs.AddContextMap(dep.ExportedSdkLibs())
|
||||
case bootClasspathTag:
|
||||
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
|
||||
}
|
||||
|
@ -2742,7 +2744,8 @@ 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.AddLibraryPath(ctx, otherName, dep.DexJarBuildPath(), dep.DexJarInstallPath())
|
||||
j.exportedSdkLibs.AddContext(ctx, otherName,
|
||||
dep.DexJarBuildPath(), dep.DexJarInstallPath())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -2757,7 +2760,8 @@ 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.MaybeAddLibraryPath(ctx, j.OptionalImplicitSdkLibrary(), outputFile, installFile)
|
||||
j.exportedSdkLibs.MaybeAddContext(ctx, j.OptionalImplicitSdkLibrary(),
|
||||
outputFile, installFile)
|
||||
|
||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
|
||||
|
||||
|
@ -2839,7 +2843,7 @@ func (j *Import) AidlIncludeDirs() android.Paths {
|
|||
return j.exportAidlIncludeDirs
|
||||
}
|
||||
|
||||
func (j *Import) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
||||
func (j *Import) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||
return j.exportedSdkLibs
|
||||
}
|
||||
|
||||
|
|
|
@ -1593,8 +1593,8 @@ func TestJavaSdkLibrary(t *testing.T) {
|
|||
// test if baz has exported SDK lib names foo and bar to qux
|
||||
qux := ctx.ModuleForTests("qux", "android_common")
|
||||
if quxLib, ok := qux.Module().(*Library); ok {
|
||||
sdkLibs := android.SortedStringKeys(quxLib.ExportedSdkLibs())
|
||||
if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
|
||||
sdkLibs := quxLib.ExportedSdkLibs().UsesLibs()
|
||||
if w := []string{"foo", "bar", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
|
||||
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue