Merge "Rework class loader context implementation."
This commit is contained in:
commit
af335a4694
|
@ -16,7 +16,7 @@ package dexpreopt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
@ -49,39 +49,39 @@ var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)
|
||||||
|
|
||||||
const UnknownInstallLibraryPath = "error"
|
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.
|
// ClassLoaderContext is a tree of libraries used by the dexpreopted module with their dependencies.
|
||||||
type LibraryPath struct {
|
// The context is used by dex2oat to compile the module and recorded in the AOT-compiled files, so
|
||||||
Host android.Path
|
// 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
|
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.
|
// ClassLoaderContextMap is a map from SDK version to a class loader context.
|
||||||
type LibraryPaths map[string]*LibraryPath
|
// 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 {
|
// Add class loader context for the given library to the map entry for the given SDK version.
|
||||||
// Library names
|
func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
|
||||||
Names []string
|
hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) error {
|
||||||
|
|
||||||
// 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 {
|
|
||||||
|
|
||||||
// If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
|
// 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
|
// 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()
|
strict = strict && !ctx.Config().AllowMissingDependencies()
|
||||||
|
|
||||||
if hostPath == nil && strict {
|
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 installPath == nil {
|
||||||
if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
|
if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
|
||||||
// Assume that compatibility libraries are installed in /system/framework.
|
// Assume that compatibility libraries are installed in /system/framework.
|
||||||
installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
|
installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
|
||||||
} else if strict {
|
} else if strict {
|
||||||
return fmt.Errorf("unknown install path to <uses-library> '%s'", lib)
|
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))
|
|
||||||
} else {
|
} else {
|
||||||
// For some stub libraries the only known thing is the name of their implementation
|
// 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
|
// 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,
|
// such cases we still need to add the library to <uses-library> tags in the manifest,
|
||||||
// but we cannot use if for dexpreopt.
|
// but we cannot use it for dexpreopt.
|
||||||
devicePath = UnknownInstallLibraryPath
|
|
||||||
}
|
}
|
||||||
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper around addLibraryPath that does error reporting.
|
// Wrapper around addContext that reports errors.
|
||||||
func (libPaths LibraryPaths) addLibraryPathOrReportError(ctx android.ModuleInstallPathContext, lib string,
|
func (clcMap ClassLoaderContextMap) addContextOrReportError(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
|
||||||
hostPath, installPath android.Path, strict bool) {
|
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 {
|
if err != nil {
|
||||||
|
ctx.ModuleErrorf(err.Error())
|
||||||
android.ReportPathErrorf(ctx, err.Error())
|
android.ReportPathErrorf(ctx, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a new library path to the map. Enforce checks that the library paths exist.
|
// Add class loader context. Fail on unknown build/install paths.
|
||||||
func (libPaths LibraryPaths) AddLibraryPath(ctx android.ModuleInstallPathContext, lib string, hostPath, installPath android.Path) {
|
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
|
||||||
libPaths.addLibraryPathOrReportError(ctx, lib, hostPath, installPath, true)
|
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).
|
// Add class loader context if the library exists. Don't fail on unknown build/install paths.
|
||||||
// Don't enforce checks that the library paths exist. Some libraries may be missing from the build,
|
func (clcMap ClassLoaderContextMap) MaybeAddContext(ctx android.ModuleInstallPathContext, lib *string,
|
||||||
// but their names still need to be added to <uses-library> tags in the manifest.
|
hostPath, installPath android.Path) {
|
||||||
func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.ModuleInstallPathContext, lib *string, hostPath, installPath android.Path) {
|
|
||||||
if lib != nil {
|
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).
|
// Add class loader context for the given SDK version. Fail on unknown build/install paths.
|
||||||
func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
|
func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
|
||||||
for lib, path := range otherPaths {
|
lib string, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
|
||||||
if _, present := libPaths[lib]; !present {
|
|
||||||
libPaths[lib] = path
|
clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, true, nestedClcMap)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
|
// Merge the other class loader context map into this one, do not override existing entries.
|
||||||
if _, ok := m[sdkVer]; !ok {
|
func (clcMap ClassLoaderContextMap) AddContextMap(otherClcMap ClassLoaderContextMap) {
|
||||||
m[sdkVer] = &classLoaderContext{}
|
for sdkVer, otherClcs := range otherClcMap {
|
||||||
}
|
for _, otherClc := range otherClcs {
|
||||||
return m[sdkVer]
|
alreadyHave := false
|
||||||
}
|
for _, clc := range clcMap[sdkVer] {
|
||||||
|
if clc.Name == otherClc.Name {
|
||||||
func (clc *classLoaderContext) addLib(lib string, hostPath android.Path, targetPath string) {
|
alreadyHave = true
|
||||||
clc.Names = append(clc.Names, lib)
|
break
|
||||||
clc.Host = append(clc.Host, hostPath)
|
}
|
||||||
clc.Target = append(clc.Target, targetPath)
|
}
|
||||||
}
|
if !alreadyHave {
|
||||||
|
clcMap[sdkVer] = append(clcMap[sdkVer], otherClc)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
|
// List of libraries in the unconditional class loader context, excluding dependencies of shared libraries.
|
||||||
clc := m.getValue(sdkVer)
|
func (clcMap ClassLoaderContextMap) UsesLibs() (ulibs []string) {
|
||||||
for _, lib := range libs {
|
if clcMap != nil {
|
||||||
clc.addLib(lib, SystemServerDexJarHostPath(ctx, lib), filepath.Join("/system/framework", lib+".jar"))
|
// 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 {
|
func usesLibsRec(clcs []*ClassLoaderContext) (ulibs []string) {
|
||||||
if clc, ok := m[AnySdkVersion]; ok {
|
for _, clc := range clcs {
|
||||||
return clc.Names
|
ulibs = append(ulibs, clc.Name)
|
||||||
|
ulibs = append(ulibs, usesLibsRec(clc.Subcontexts)...)
|
||||||
}
|
}
|
||||||
return nil
|
return ulibs
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that the full unconditional context is known, reconstruct conditional context.
|
// Now that the full unconditional context is known, reconstruct conditional context.
|
||||||
// Apply filters for individual libraries, mirroring what the PackageManager does when it
|
// Apply filters for individual libraries, mirroring what the PackageManager does when it
|
||||||
// constructs class loader context on device.
|
// constructs class loader context on device.
|
||||||
//
|
//
|
||||||
// TODO(b/132357300):
|
// TODO(b/132357300): remove "android.hidl.manager" and "android.hidl.base" for non-system apps.
|
||||||
// - remove android.hidl.manager and android.hidl.base unless the app is a system app.
|
|
||||||
//
|
//
|
||||||
func fixConditionalClassLoaderContext(clcMap classLoaderContextMap) {
|
func fixClassLoaderContext(clcMap ClassLoaderContextMap) {
|
||||||
usesLibs := clcMap.usesLibs()
|
usesLibs := clcMap.UsesLibs()
|
||||||
|
|
||||||
for sdkVer, clc := range clcMap {
|
for sdkVer, clcs := range clcMap {
|
||||||
if sdkVer == AnySdkVersion {
|
if sdkVer == AnySdkVersion {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
clcMap[sdkVer] = &classLoaderContext{}
|
fixedClcs := []*ClassLoaderContext{}
|
||||||
for i, lib := range clc.Names {
|
for _, clc := range clcs {
|
||||||
if android.InList(lib, usesLibs) {
|
if android.InList(clc.Name, usesLibs) {
|
||||||
// skip compatibility libraries that are already included in unconditional context
|
// 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
|
// android.test.mock is only needed as a compatibility library (in conditional class
|
||||||
// loader context) if android.test.runner is used, otherwise skip it
|
// loader context) if android.test.runner is used, otherwise skip it
|
||||||
} else {
|
} 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.
|
// Return true if all build/install library paths are valid (including recursive subcontexts),
|
||||||
func computeClassLoaderContext(ctx android.PathContext, clcMap classLoaderContextMap) (clcStr string, paths android.Paths) {
|
// otherwise return false. A build path is valid if it's not nil. An install path is valid if it's
|
||||||
for _, ver := range android.SortedIntKeys(clcMap) {
|
// not equal to a special "error" value.
|
||||||
clc := clcMap.getValue(ver)
|
func validateClassLoaderContext(clcMap ClassLoaderContextMap) (bool, error) {
|
||||||
|
for sdkVer, clcs := range clcMap {
|
||||||
clcLen := len(clc.Names)
|
if valid, err := validateClassLoaderContextRec(sdkVer, clcs); !valid || err != nil {
|
||||||
if clcLen != len(clc.Host) || clcLen != len(clc.Target) {
|
return valid, err
|
||||||
android.ReportPathErrorf(ctx, "ill-formed class loader context")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
var hostClc, targetClc []string
|
func validateClassLoaderContextRec(sdkVer int, clcs []*ClassLoaderContext) (bool, error) {
|
||||||
var hostPaths android.Paths
|
for _, clc := range clcs {
|
||||||
|
if clc.Host == nil || clc.Device == UnknownInstallLibraryPath {
|
||||||
for i := 0; i < clcLen; i++ {
|
if sdkVer == AnySdkVersion {
|
||||||
hostStr := "PCL[" + clc.Host[i].String() + "]"
|
// Return error if dexpreopt doesn't know paths to one of the <uses-library>
|
||||||
targetStr := "PCL[" + clc.Target[i] + "]"
|
// 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)
|
||||||
hostClc = append(hostClc, hostStr)
|
} else {
|
||||||
targetClc = append(targetClc, targetStr)
|
// No error for compatibility libraries, as Soong doesn't know if they are needed
|
||||||
hostPaths = append(hostPaths, clc.Host[i])
|
// (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 {
|
if hostPaths != nil {
|
||||||
sdkVerStr := fmt.Sprintf("%d", ver)
|
clcStr += fmt.Sprintf(" --host-context-for-sdk %s %s", sdkVerStr, hostClc)
|
||||||
if ver == AnySdkVersion {
|
clcStr += fmt.Sprintf(" --target-context-for-sdk %s %s", sdkVerStr, targetClc)
|
||||||
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...)
|
|
||||||
}
|
}
|
||||||
|
paths = append(paths, hostPaths...)
|
||||||
}
|
}
|
||||||
|
return clcStr, android.FirstUniquePaths(paths)
|
||||||
return clcStr, 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 {
|
type jsonLibraryPath struct {
|
||||||
Host string
|
Host string
|
||||||
Device 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
|
// A map from SDK version (represented with a JSON string) to JSON class loader context.
|
||||||
func constructLibraryPaths(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
|
type jsonClassLoaderContextMap map[string]jsonClassLoaderContext
|
||||||
m := LibraryPaths{}
|
|
||||||
for lib, path := range paths {
|
// Convert JSON class loader context map to ClassLoaderContextMap.
|
||||||
m[lib] = &LibraryPath{
|
func fromJsonClassLoaderContext(ctx android.PathContext, jClcMap jsonClassLoaderContextMap) ClassLoaderContextMap {
|
||||||
constructPath(ctx, path.Host),
|
clcMap := make(ClassLoaderContextMap)
|
||||||
path.Device,
|
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
|
// ├── b
|
||||||
// ├── c
|
// ├── c
|
||||||
// ├── d
|
// ├── d
|
||||||
// ├── a2
|
// │ ├── a2
|
||||||
// ├── b2
|
// │ ├── b2
|
||||||
// ├── c2
|
// │ └── c2
|
||||||
// ├── a1
|
// │ ├── a1
|
||||||
// ├── b1
|
// │ └── b1
|
||||||
// ├── f
|
// ├── f
|
||||||
// ├── a3
|
// ├── a3
|
||||||
// └── b3
|
// └── b3
|
||||||
//
|
//
|
||||||
ctx := testContext()
|
ctx := testContext()
|
||||||
|
|
||||||
lp := make(LibraryPaths)
|
m := make(ClassLoaderContextMap)
|
||||||
|
|
||||||
lp.AddLibraryPath(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
|
m.AddContext(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
|
||||||
lp.AddLibraryPath(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
|
m.AddContext(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
|
||||||
|
|
||||||
// "Maybe" variant in the good case: add as usual.
|
// "Maybe" variant in the good case: add as usual.
|
||||||
c := "c"
|
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.
|
// "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.
|
// Add some libraries with nested subcontexts.
|
||||||
|
|
||||||
lp1 := make(LibraryPaths)
|
m1 := make(ClassLoaderContextMap)
|
||||||
lp1.AddLibraryPath(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
|
m1.AddContext(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
|
||||||
lp1.AddLibraryPath(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
|
m1.AddContext(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
|
||||||
|
|
||||||
lp2 := make(LibraryPaths)
|
m2 := make(ClassLoaderContextMap)
|
||||||
lp2.AddLibraryPath(ctx, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"))
|
m2.AddContext(ctx, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"))
|
||||||
lp2.AddLibraryPath(ctx, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"))
|
m2.AddContext(ctx, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"))
|
||||||
lp2.AddLibraryPath(ctx, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"))
|
m2.AddContextForSdk(ctx, AnySdkVersion, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
|
||||||
lp2.AddLibraryPaths(lp1)
|
|
||||||
|
|
||||||
lp.AddLibraryPath(ctx, "d", buildPath(ctx, "d"), installPath(ctx, "d"))
|
m3 := make(ClassLoaderContextMap)
|
||||||
lp.AddLibraryPaths(lp2)
|
m3.AddContext(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
|
||||||
|
m3.AddContext(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
|
||||||
|
|
||||||
lp3 := make(LibraryPaths)
|
m.AddContextForSdk(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), m2)
|
||||||
lp3.AddLibraryPath(ctx, "f", buildPath(ctx, "f"), installPath(ctx, "f"))
|
// When the same library is both in conditional and unconditional context, it should be removed
|
||||||
lp3.AddLibraryPath(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
|
// from conditional context.
|
||||||
lp3.AddLibraryPath(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
|
m.AddContextForSdk(ctx, 42, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
|
||||||
lp.AddLibraryPaths(lp3)
|
m.AddContextForSdk(ctx, AnySdkVersion, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
|
||||||
|
m.AddContextMap(m3)
|
||||||
|
|
||||||
// Compatibility libraries with unknown install paths get default paths.
|
// Compatibility libraries with unknown install paths get default paths.
|
||||||
lp.AddLibraryPath(ctx, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil)
|
m.AddContextForSdk(ctx, 29, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil, nil)
|
||||||
lp.AddLibraryPath(ctx, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil)
|
m.AddContextForSdk(ctx, 29, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil, 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
|
|
||||||
|
|
||||||
// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
|
// 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.
|
// needed as a compatibility library if "android.test.runner" is in CLC as well.
|
||||||
ok, err = m.addLibs(ctx, 30, module, AndroidTestMock)
|
m.AddContextForSdk(ctx, 30, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil, nil)
|
||||||
valid = valid && ok && err == nil
|
|
||||||
|
|
||||||
// When the same library is both in conditional and unconditional context, it should be removed
|
valid, validationError := validateClassLoaderContext(m)
|
||||||
// from conditional context.
|
|
||||||
ok, err = m.addLibs(ctx, 42, module, "f")
|
|
||||||
valid = valid && ok && err == nil
|
|
||||||
|
|
||||||
fixConditionalClassLoaderContext(m)
|
fixClassLoaderContext(m)
|
||||||
|
|
||||||
var haveStr string
|
var haveStr string
|
||||||
var havePaths android.Paths
|
var havePaths android.Paths
|
||||||
var haveUsesLibs []string
|
var haveUsesLibs []string
|
||||||
if valid {
|
if valid && validationError == nil {
|
||||||
haveStr, havePaths = computeClassLoaderContext(ctx, m)
|
haveStr, havePaths = ComputeClassLoaderContext(m)
|
||||||
haveUsesLibs = m.usesLibs()
|
haveUsesLibs = m.UsesLibs()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that validation is successful (all paths are known).
|
// Test that validation is successful (all paths are known).
|
||||||
t.Run("validate", func(t *testing.T) {
|
t.Run("validate", func(t *testing.T) {
|
||||||
if !valid {
|
if !(valid && validationError == nil) {
|
||||||
t.Errorf("invalid class loader context")
|
t.Errorf("invalid class loader context")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -135,14 +118,14 @@ func TestCLC(t *testing.T) {
|
||||||
"PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
|
"PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
|
||||||
"PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
|
"PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
|
||||||
" --host-context-for-sdk any " +
|
" --host-context-for-sdk any " +
|
||||||
"PCL[out/a.jar]#PCL[out/b.jar]#PCL[out/c.jar]#PCL[out/d.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/a2.jar]#PCL[out/b2.jar]#PCL[out/c2.jar]" +
|
||||||
"PCL[out/a1.jar]#PCL[out/b1.jar]#" +
|
"{PCL[out/a1.jar]#PCL[out/b1.jar]}}#" +
|
||||||
"PCL[out/f.jar]#PCL[out/a3.jar]#PCL[out/b3.jar]" +
|
"PCL[out/f.jar]#PCL[out/a3.jar]#PCL[out/b3.jar]" +
|
||||||
" --target-context-for-sdk any " +
|
" --target-context-for-sdk any " +
|
||||||
"PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.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/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]" +
|
||||||
"PCL[/system/a1.jar]#PCL[/system/b1.jar]#" +
|
"{PCL[/system/a1.jar]#PCL[/system/b1.jar]}}#" +
|
||||||
"PCL[/system/f.jar]#PCL[/system/a3.jar]#PCL[/system/b3.jar]"
|
"PCL[/system/f.jar]#PCL[/system/a3.jar]#PCL[/system/b3.jar]"
|
||||||
if wantStr != haveStr {
|
if wantStr != haveStr {
|
||||||
t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", 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.
|
// Test that an unexpected unknown build path causes immediate error.
|
||||||
func TestCLCUnknownBuildPath(t *testing.T) {
|
func TestCLCUnknownBuildPath(t *testing.T) {
|
||||||
ctx := testContext()
|
ctx := testContext()
|
||||||
lp := make(LibraryPaths)
|
m := make(ClassLoaderContextMap)
|
||||||
err := lp.addLibraryPath(ctx, "a", nil, nil, true)
|
err := m.addContext(ctx, AnySdkVersion, "a", nil, nil, true, nil)
|
||||||
checkError(t, err, "unknown build path to <uses-library> 'a'")
|
checkError(t, err, "unknown build path to <uses-library> \"a\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that an unexpected unknown install path causes immediate error.
|
// Test that an unexpected unknown install path causes immediate error.
|
||||||
func TestCLCUnknownInstallPath(t *testing.T) {
|
func TestCLCUnknownInstallPath(t *testing.T) {
|
||||||
ctx := testContext()
|
ctx := testContext()
|
||||||
lp := make(LibraryPaths)
|
m := make(ClassLoaderContextMap)
|
||||||
err := lp.addLibraryPath(ctx, "a", buildPath(ctx, "a"), nil, true)
|
err := m.addContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), nil, true, nil)
|
||||||
checkError(t, err, "unknown install path to <uses-library> 'a'")
|
checkError(t, err, "unknown install path to <uses-library> \"a\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCLCMaybeAdd(t *testing.T) {
|
func TestCLCMaybeAdd(t *testing.T) {
|
||||||
ctx := testContext()
|
ctx := testContext()
|
||||||
|
|
||||||
lp := make(LibraryPaths)
|
m := make(ClassLoaderContextMap)
|
||||||
a := "a"
|
a := "a"
|
||||||
lp.MaybeAddLibraryPath(ctx, &a, nil, nil)
|
m.MaybeAddContext(ctx, &a, nil, nil)
|
||||||
|
|
||||||
module := testSystemModuleConfig(ctx, "test")
|
// The library should be added to <uses-library> tags by the manifest_fixer.
|
||||||
module.LibraryPaths = lp
|
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)
|
// But class loader context in such cases should raise an error on validation.
|
||||||
_, err := m.addLibs(ctx, AnySdkVersion, module, "a")
|
t.Run("validate", func(t *testing.T) {
|
||||||
checkError(t, err, "dexpreopt cannot find path for <uses-library> 'a'")
|
_, err := validateClassLoaderContext(m)
|
||||||
|
checkError(t, err, "invalid path for <uses-library> \"a\"")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkError(t *testing.T, have error, want string) {
|
func checkError(t *testing.T, have error, want string) {
|
||||||
|
|
|
@ -114,10 +114,8 @@ type ModuleConfig struct {
|
||||||
ProfileIsTextListing bool
|
ProfileIsTextListing bool
|
||||||
ProfileBootListing android.OptionalPath
|
ProfileBootListing android.OptionalPath
|
||||||
|
|
||||||
EnforceUsesLibraries bool
|
EnforceUsesLibraries bool
|
||||||
OptionalUsesLibraries []string
|
ClassLoaderContexts ClassLoaderContextMap
|
||||||
UsesLibraries []string
|
|
||||||
LibraryPaths LibraryPaths
|
|
||||||
|
|
||||||
Archs []android.ArchType
|
Archs []android.ArchType
|
||||||
DexPreoptImages []android.Path
|
DexPreoptImages []android.Path
|
||||||
|
@ -265,7 +263,7 @@ func ParseModuleConfig(ctx android.PathContext, data []byte) (*ModuleConfig, err
|
||||||
DexPath string
|
DexPath string
|
||||||
ManifestPath string
|
ManifestPath string
|
||||||
ProfileClassListing string
|
ProfileClassListing string
|
||||||
LibraryPaths jsonLibraryPaths
|
ClassLoaderContexts jsonClassLoaderContextMap
|
||||||
DexPreoptImages []string
|
DexPreoptImages []string
|
||||||
DexPreoptImageLocations []string
|
DexPreoptImageLocations []string
|
||||||
PreoptBootClassPathDexFiles []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.DexPath = constructPath(ctx, config.DexPath)
|
||||||
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
|
config.ModuleConfig.ManifestPath = constructPath(ctx, config.ManifestPath)
|
||||||
config.ModuleConfig.ProfileClassListing = android.OptionalPathForPath(constructPath(ctx, config.ProfileClassListing))
|
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.DexPreoptImages = constructPaths(ctx, config.DexPreoptImages)
|
||||||
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
|
config.ModuleConfig.DexPreoptImageLocations = config.DexPreoptImageLocations
|
||||||
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
|
config.ModuleConfig.PreoptBootClassPathDexFiles = constructPaths(ctx, config.PreoptBootClassPathDexFiles)
|
||||||
|
|
|
@ -81,16 +81,18 @@ func GenerateDexpreoptRule(ctx android.PathContext, globalSoong *GlobalSoongConf
|
||||||
}
|
}
|
||||||
|
|
||||||
if !dexpreoptDisabled(ctx, global, module) {
|
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())
|
android.ReportPathErrorf(ctx, err.Error())
|
||||||
} else if clc != nil {
|
} else if valid {
|
||||||
|
fixClassLoaderContext(module.ClassLoaderContexts)
|
||||||
|
|
||||||
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
|
appImage := (generateProfile || module.ForceCreateAppImage || global.DefaultAppImages) &&
|
||||||
!module.NoCreateAppImage
|
!module.NoCreateAppImage
|
||||||
|
|
||||||
generateDM := shouldGenerateDM(module, global)
|
generateDM := shouldGenerateDM(module, global)
|
||||||
|
|
||||||
for archIdx, _ := range module.Archs {
|
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,
|
func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, global *GlobalConfig,
|
||||||
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, classLoaderContexts classLoaderContextMap,
|
module *ModuleConfig, rule *android.RuleBuilder, archIdx int, profile android.WritablePath,
|
||||||
profile android.WritablePath, appImage bool, generateDM bool) {
|
appImage bool, generateDM bool) {
|
||||||
|
|
||||||
arch := module.Archs[archIdx]
|
arch := module.Archs[archIdx]
|
||||||
|
|
||||||
|
@ -235,6 +237,16 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
|
||||||
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
rule.Command().FlagWithOutput("rm -f ", odexPath)
|
||||||
|
|
||||||
if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
|
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.
|
// Copy the system server jar to a predefined location where dex2oat will find it.
|
||||||
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
|
dexPathHost := SystemServerDexJarHostPath(ctx, module.Name)
|
||||||
rule.Command().Text("mkdir -p").Flag(filepath.Dir(dexPathHost.String()))
|
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)
|
checkSystemServerOrder(ctx, jarIndex)
|
||||||
|
|
||||||
clc := classLoaderContexts[AnySdkVersion]
|
|
||||||
rule.Command().
|
rule.Command().
|
||||||
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clc.Host.Strings(), ":") + "]").
|
Text("class_loader_context_arg=--class-loader-context=PCL[" + strings.Join(clcHost.Strings(), ":") + "]").
|
||||||
Implicits(clc.Host).
|
Implicits(clcHost).
|
||||||
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clc.Target, ":") + "]")
|
Text("stored_class_loader_context_arg=--stored-class-loader-context=PCL[" + strings.Join(clcTarget, ":") + "]")
|
||||||
|
|
||||||
} else if module.EnforceUsesLibraries {
|
} else if module.EnforceUsesLibraries {
|
||||||
// Generate command that saves target SDK version in a shell variable.
|
// Generate command that saves target SDK version in a shell variable.
|
||||||
if module.ManifestPath != nil {
|
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.
|
// 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().
|
cmd := rule.Command().
|
||||||
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
|
Text(`eval "$(`).Tool(globalSoong.ConstructContext).
|
||||||
Text(` --target-sdk-version ${target_sdk_version}`).
|
Text(` --target-sdk-version ${target_sdk_version}`).
|
||||||
Text(clc).Implicits(paths)
|
Text(clc).Implicits(paths)
|
||||||
cmd.Text(`)"`)
|
cmd.Text(`)"`)
|
||||||
|
|
||||||
} else {
|
} 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.
|
// Pass special class loader context to skip the classpath and collision check.
|
||||||
// This will get removed once LOCAL_USES_LIBRARIES is enforced.
|
// 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
|
// 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{},
|
ProfileClassListing: android.OptionalPath{},
|
||||||
ProfileIsTextListing: false,
|
ProfileIsTextListing: false,
|
||||||
EnforceUsesLibraries: false,
|
EnforceUsesLibraries: false,
|
||||||
OptionalUsesLibraries: nil,
|
ClassLoaderContexts: nil,
|
||||||
UsesLibraries: nil,
|
|
||||||
LibraryPaths: nil,
|
|
||||||
Archs: []android.ArchType{android.Arm},
|
Archs: []android.ArchType{android.Arm},
|
||||||
DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
|
DexPreoptImages: android.Paths{android.PathForTesting("system/framework/arm/boot.art")},
|
||||||
DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}},
|
DexPreoptImagesDeps: []android.OutputPaths{android.OutputPaths{}},
|
||||||
|
|
14
java/aar.go
14
java/aar.go
|
@ -109,7 +109,7 @@ type aapt struct {
|
||||||
useEmbeddedNativeLibs bool
|
useEmbeddedNativeLibs bool
|
||||||
useEmbeddedDex bool
|
useEmbeddedDex bool
|
||||||
usesNonSdkApis bool
|
usesNonSdkApis bool
|
||||||
sdkLibraries dexpreopt.LibraryPaths
|
sdkLibraries dexpreopt.ClassLoaderContextMap
|
||||||
hasNoCode bool
|
hasNoCode bool
|
||||||
LoggingParent string
|
LoggingParent string
|
||||||
resourceFiles android.Paths
|
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
|
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
|
||||||
func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStaticLibs, transitiveStaticLibManifests android.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
|
var sharedLibs android.Paths
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
||||||
sharedLibs = append(sharedLibs, sdkDep.jars...)
|
sharedLibs = append(sharedLibs, sdkDep.jars...)
|
||||||
}
|
}
|
||||||
|
|
||||||
sdkLibraries = make(dexpreopt.LibraryPaths)
|
sdkLibraries = make(dexpreopt.ClassLoaderContextMap)
|
||||||
|
|
||||||
ctx.VisitDirectDeps(func(module android.Module) {
|
ctx.VisitDirectDeps(func(module android.Module) {
|
||||||
var exportPackage android.Path
|
var exportPackage android.Path
|
||||||
|
@ -411,7 +411,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
||||||
}
|
}
|
||||||
|
|
||||||
if dep, ok := module.(Dependency); ok {
|
if dep, ok := module.(Dependency); ok {
|
||||||
sdkLibraries.AddLibraryPaths(dep.ExportedSdkLibs())
|
sdkLibraries.AddContextMap(dep.ExportedSdkLibs())
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ctx.OtherModuleDependencyTag(module) {
|
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
|
// (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.
|
// names to the list of sdk libraries to be added to the manifest.
|
||||||
if component, ok := module.(SdkLibraryComponentDependency); ok {
|
if component, ok := module.(SdkLibraryComponentDependency); ok {
|
||||||
sdkLibraries.MaybeAddLibraryPath(ctx, component.OptionalImplicitSdkLibrary(),
|
sdkLibraries.MaybeAddContext(ctx, component.OptionalImplicitSdkLibrary(),
|
||||||
component.DexJarBuildPath(), component.DexJarInstallPath())
|
component.DexJarBuildPath(), component.DexJarInstallPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +439,7 @@ func aaptLibs(ctx android.ModuleContext, sdkContext sdkContext) (transitiveStati
|
||||||
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
|
transitiveStaticLibs = append(transitiveStaticLibs, aarDep.ExportedStaticPackages()...)
|
||||||
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
|
transitiveStaticLibs = append(transitiveStaticLibs, exportPackage)
|
||||||
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
|
transitiveStaticLibManifests = append(transitiveStaticLibManifests, aarDep.ExportedManifests()...)
|
||||||
sdkLibraries.AddLibraryPaths(aarDep.ExportedSdkLibs())
|
sdkLibraries.AddContextMap(aarDep.ExportedSdkLibs())
|
||||||
if aarDep.ExportedAssets().Valid() {
|
if aarDep.ExportedAssets().Valid() {
|
||||||
assets = append(assets, aarDep.ExportedAssets().Path())
|
assets = append(assets, aarDep.ExportedAssets().Path())
|
||||||
}
|
}
|
||||||
|
@ -827,7 +827,7 @@ func (a *AARImport) AidlIncludeDirs() android.Paths {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AARImport) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
func (a *AARImport) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,9 @@ var manifestMergerRule = pctx.AndroidStaticRule("manifestMerger",
|
||||||
"args", "libs")
|
"args", "libs")
|
||||||
|
|
||||||
// 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,
|
||||||
isLibrary, useEmbeddedNativeLibs, usesNonSdkApis, useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
|
sdkLibraries dexpreopt.ClassLoaderContextMap, isLibrary, useEmbeddedNativeLibs, usesNonSdkApis,
|
||||||
|
useEmbeddedDex, hasNoCode bool, loggingParent string) android.Path {
|
||||||
|
|
||||||
var args []string
|
var args []string
|
||||||
if isLibrary {
|
if isLibrary {
|
||||||
|
@ -70,7 +71,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
|
||||||
args = append(args, "--use-embedded-dex")
|
args = append(args, "--use-embedded-dex")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, usesLib := range android.SortedStringKeys(sdkLibraries) {
|
for _, usesLib := range sdkLibraries.UsesLibs() {
|
||||||
if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
|
if inList(usesLib, dexpreopt.OptionalCompatUsesLibs) {
|
||||||
args = append(args, "--optional-uses-library", usesLib)
|
args = append(args, "--optional-uses-library", usesLib)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -115,7 +115,7 @@ func (library *Library) AndroidMkEntries() []android.AndroidMkEntries {
|
||||||
entries.SetPath("LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR", library.jacocoReportClassesFile)
|
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 {
|
if len(library.additionalCheckedModules) != 0 {
|
||||||
entries.AddStrings("LOCAL_ADDITIONAL_CHECKED_MODULE", library.additionalCheckedModules.Strings()...)
|
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")
|
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)
|
a.dexpreopter.installPath = a.installPath(ctx)
|
||||||
if a.dexProperties.Uncompress_dex == nil {
|
if a.dexProperties.Uncompress_dex == nil {
|
||||||
// If the value was not force-set by the user, use reasonable default based on the module.
|
// 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.uncompressedDex = *a.dexProperties.Uncompress_dex
|
||||||
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||||
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
|
||||||
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
a.dexpreopter.classLoaderContexts.AddContextMap(sdkLibs)
|
||||||
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
|
||||||
a.dexpreopter.libraryPaths.AddLibraryPaths(sdkLibs)
|
|
||||||
a.dexpreopter.manifestFile = a.mergedManifestFile
|
a.dexpreopter.manifestFile = a.mergedManifestFile
|
||||||
a.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
a.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||||
|
|
||||||
if ctx.ModuleName() != "framework-res" {
|
if ctx.ModuleName() != "framework-res" {
|
||||||
a.Module.compile(ctx, a.aaptSrcJar)
|
a.Module.compile(ctx, a.aaptSrcJar)
|
||||||
|
@ -791,7 +789,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
a.usesLibrary.freezeEnforceUsesLibraries()
|
a.usesLibrary.freezeEnforceUsesLibraries()
|
||||||
|
|
||||||
// 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 a.aapt.sdkLibraries.UsesLibs() {
|
||||||
a.usesLibrary.addLib(usesLib, inList(usesLib, dexpreopt.OptionalCompatUsesLibs))
|
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.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||||
|
|
||||||
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||||
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
|
||||||
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
|
||||||
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
|
||||||
|
|
||||||
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
|
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
|
||||||
if a.dexpreopter.uncompressedDex {
|
if a.dexpreopter.uncompressedDex {
|
||||||
|
@ -1976,17 +1972,18 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s
|
||||||
return optionalUsesLibs
|
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.
|
// to their dex jars on host and on device.
|
||||||
func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) dexpreopt.LibraryPaths {
|
func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
|
||||||
usesLibPaths := make(dexpreopt.LibraryPaths)
|
clcMap := make(dexpreopt.ClassLoaderContextMap)
|
||||||
|
|
||||||
if !ctx.Config().UnbundledBuild() {
|
if !ctx.Config().UnbundledBuild() {
|
||||||
ctx.VisitDirectDeps(func(m android.Module) {
|
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)
|
dep := ctx.OtherModuleName(m)
|
||||||
if lib, ok := m.(Dependency); ok {
|
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() {
|
} else if ctx.Config().AllowMissingDependencies() {
|
||||||
ctx.AddMissingDependencies([]string{dep})
|
ctx.AddMissingDependencies([]string{dep})
|
||||||
} else {
|
} 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
|
// 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
|
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
|
||||||
cmd = app.Rule("dexpreopt").RuleParams.Command
|
cmd = app.Rule("dexpreopt").RuleParams.Command
|
||||||
w := `--target-context-for-sdk any ` +
|
w := `--target-context-for-sdk any ` +
|
||||||
`PCL[/system/framework/foo.jar]#` +
|
|
||||||
`PCL[/system/framework/quuz.jar]#` +
|
|
||||||
`PCL[/system/framework/qux.jar]#` +
|
`PCL[/system/framework/qux.jar]#` +
|
||||||
`PCL[/system/framework/runtime-library.jar]#` +
|
`PCL[/system/framework/quuz.jar]#` +
|
||||||
`PCL[/system/framework/bar.jar]`
|
`PCL[/system/framework/foo.jar]#` +
|
||||||
|
`PCL[/system/framework/bar.jar]#` +
|
||||||
|
`PCL[/system/framework/runtime-library.jar]`
|
||||||
if !strings.Contains(cmd, w) {
|
if !strings.Contains(cmd, w) {
|
||||||
t.Errorf("wanted %q in %q", w, cmd)
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,7 +163,7 @@ func (d *DeviceHostConverter) AidlIncludeDirs() android.Paths {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
func (d *DeviceHostConverter) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,9 @@ type dexpreopter struct {
|
||||||
isTest bool
|
isTest bool
|
||||||
isPresignedPrebuilt bool
|
isPresignedPrebuilt bool
|
||||||
|
|
||||||
manifestFile android.Path
|
manifestFile android.Path
|
||||||
usesLibs []string
|
enforceUsesLibs bool
|
||||||
optionalUsesLibs []string
|
classLoaderContexts dexpreopt.ClassLoaderContextMap
|
||||||
enforceUsesLibs bool
|
|
||||||
libraryPaths dexpreopt.LibraryPaths
|
|
||||||
|
|
||||||
builtInstalled string
|
builtInstalled string
|
||||||
}
|
}
|
||||||
|
@ -193,10 +191,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
||||||
ProfileIsTextListing: profileIsTextListing,
|
ProfileIsTextListing: profileIsTextListing,
|
||||||
ProfileBootListing: profileBootListing,
|
ProfileBootListing: profileBootListing,
|
||||||
|
|
||||||
EnforceUsesLibraries: d.enforceUsesLibs,
|
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||||
OptionalUsesLibraries: d.optionalUsesLibs,
|
ClassLoaderContexts: d.classLoaderContexts,
|
||||||
UsesLibraries: d.usesLibs,
|
|
||||||
LibraryPaths: d.libraryPaths,
|
|
||||||
|
|
||||||
Archs: archs,
|
Archs: archs,
|
||||||
DexPreoptImages: images,
|
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
|
// manifest file to use instead of properties.Manifest
|
||||||
overrideManifest android.OptionalPath
|
overrideManifest android.OptionalPath
|
||||||
|
|
||||||
// map of SDK libs exported by this java module to their build and install paths
|
// map of SDK version to class loader context
|
||||||
exportedSdkLibs dexpreopt.LibraryPaths
|
exportedSdkLibs dexpreopt.ClassLoaderContextMap
|
||||||
|
|
||||||
// list of plugins that this java module is exporting
|
// list of plugins that this java module is exporting
|
||||||
exportedPluginJars android.Paths
|
exportedPluginJars android.Paths
|
||||||
|
@ -509,7 +509,7 @@ type Dependency interface {
|
||||||
ImplementationJars() android.Paths
|
ImplementationJars() android.Paths
|
||||||
ResourceJars() android.Paths
|
ResourceJars() android.Paths
|
||||||
AidlIncludeDirs() android.Paths
|
AidlIncludeDirs() android.Paths
|
||||||
ExportedSdkLibs() dexpreopt.LibraryPaths
|
ExportedSdkLibs() dexpreopt.ClassLoaderContextMap
|
||||||
ExportedPlugins() (android.Paths, []string)
|
ExportedPlugins() (android.Paths, []string)
|
||||||
SrcJarArgs() ([]string, android.Paths)
|
SrcJarArgs() ([]string, android.Paths)
|
||||||
BaseModuleName() string
|
BaseModuleName() string
|
||||||
|
@ -1027,7 +1027,8 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
||||||
case libTag:
|
case libTag:
|
||||||
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
|
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
|
||||||
// names of sdk libs that are directly depended are exported
|
// 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:
|
case staticLibTag:
|
||||||
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
|
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:
|
case libTag, instrumentationForTag:
|
||||||
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
deps.classpath = append(deps.classpath, dep.HeaderJars()...)
|
||||||
// sdk lib names from dependencies are re-exported
|
// 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()...)
|
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||||
pluginJars, pluginClasses := dep.ExportedPlugins()
|
pluginJars, pluginClasses := dep.ExportedPlugins()
|
||||||
addPlugins(&deps, pluginJars, pluginClasses...)
|
addPlugins(&deps, pluginJars, pluginClasses...)
|
||||||
|
@ -1050,7 +1051,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
|
||||||
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
|
deps.staticHeaderJars = append(deps.staticHeaderJars, dep.HeaderJars()...)
|
||||||
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
|
deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
|
||||||
// sdk lib names from dependencies are re-exported
|
// 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()...)
|
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
|
||||||
pluginJars, pluginClasses := dep.ExportedPlugins()
|
pluginJars, pluginClasses := dep.ExportedPlugins()
|
||||||
addPlugins(&deps, pluginJars, pluginClasses...)
|
addPlugins(&deps, pluginJars, pluginClasses...)
|
||||||
|
@ -1902,7 +1903,7 @@ func (j *Module) AidlIncludeDirs() android.Paths {
|
||||||
return j.exportAidlIncludeDirs
|
return j.exportAidlIncludeDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Module) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
func (j *Module) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||||
return j.exportedSdkLibs
|
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.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
|
||||||
}
|
}
|
||||||
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
|
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
|
||||||
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
j.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||||
j.compile(ctx, nil)
|
j.compile(ctx, nil)
|
||||||
|
|
||||||
// Collect the module directory for IDE info in java/jdeps.go.
|
// 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
|
// 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
|
// that, if necessary, a <uses-library> element for that java_sdk_library is
|
||||||
// added to the Android manifest.
|
// 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).
|
// 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 != "" {
|
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)
|
j.distFiles = j.GenerateTaggedDistFiles(ctx)
|
||||||
|
@ -2644,7 +2646,7 @@ type Import struct {
|
||||||
dexJarFile android.Path
|
dexJarFile android.Path
|
||||||
|
|
||||||
combinedClasspathFile android.Path
|
combinedClasspathFile android.Path
|
||||||
exportedSdkLibs dexpreopt.LibraryPaths
|
exportedSdkLibs dexpreopt.ClassLoaderContextMap
|
||||||
exportAidlIncludeDirs android.Paths
|
exportAidlIncludeDirs android.Paths
|
||||||
|
|
||||||
hideApexVariantFromMake bool
|
hideApexVariantFromMake bool
|
||||||
|
@ -2719,7 +2721,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
TransformJetifier(ctx, outputFile, inputFile)
|
TransformJetifier(ctx, outputFile, inputFile)
|
||||||
}
|
}
|
||||||
j.combinedClasspathFile = outputFile
|
j.combinedClasspathFile = outputFile
|
||||||
j.exportedSdkLibs = make(dexpreopt.LibraryPaths)
|
j.exportedSdkLibs = make(dexpreopt.ClassLoaderContextMap)
|
||||||
|
|
||||||
var flags javaBuilderFlags
|
var flags javaBuilderFlags
|
||||||
|
|
||||||
|
@ -2733,7 +2735,7 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
case libTag, staticLibTag:
|
case libTag, staticLibTag:
|
||||||
flags.classpath = append(flags.classpath, dep.HeaderJars()...)
|
flags.classpath = append(flags.classpath, dep.HeaderJars()...)
|
||||||
// sdk lib names from dependencies are re-exported
|
// sdk lib names from dependencies are re-exported
|
||||||
j.exportedSdkLibs.AddLibraryPaths(dep.ExportedSdkLibs())
|
j.exportedSdkLibs.AddContextMap(dep.ExportedSdkLibs())
|
||||||
case bootClasspathTag:
|
case bootClasspathTag:
|
||||||
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
|
flags.bootClasspath = append(flags.bootClasspath, dep.HeaderJars()...)
|
||||||
}
|
}
|
||||||
|
@ -2742,7 +2744,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
case libTag:
|
case libTag:
|
||||||
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
|
flags.classpath = append(flags.classpath, dep.SdkHeaderJars(ctx, j.sdkVersion())...)
|
||||||
// names of sdk libs that are directly depended are exported
|
// 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
|
// 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
|
// that, if necessary, a <uses-library> element for that java_sdk_library is
|
||||||
// added to the Android manifest.
|
// 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)
|
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
|
||||||
|
|
||||||
|
@ -2839,7 +2843,7 @@ func (j *Import) AidlIncludeDirs() android.Paths {
|
||||||
return j.exportAidlIncludeDirs
|
return j.exportAidlIncludeDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Import) ExportedSdkLibs() dexpreopt.LibraryPaths {
|
func (j *Import) ExportedSdkLibs() dexpreopt.ClassLoaderContextMap {
|
||||||
return j.exportedSdkLibs
|
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
|
// test if baz has exported SDK lib names foo and bar to qux
|
||||||
qux := ctx.ModuleForTests("qux", "android_common")
|
qux := ctx.ModuleForTests("qux", "android_common")
|
||||||
if quxLib, ok := qux.Module().(*Library); ok {
|
if quxLib, ok := qux.Module().(*Library); ok {
|
||||||
sdkLibs := android.SortedStringKeys(quxLib.ExportedSdkLibs())
|
sdkLibs := quxLib.ExportedSdkLibs().UsesLibs()
|
||||||
if w := []string{"bar", "foo", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
|
if w := []string{"foo", "bar", "fred", "quuz"}; !reflect.DeepEqual(w, sdkLibs) {
|
||||||
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
|
t.Errorf("qux should export %q but exports %q", w, sdkLibs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue