Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af335a46 authored by Ulyana Trafimovich's avatar Ulyana Trafimovich Committed by Gerrit Code Review
Browse files

Merge "Rework class loader context implementation."

parents 74f576de 8cbc5d26
Loading
Loading
Loading
Loading
+199 −208
Original line number Diff line number Diff line
@@ -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

// LibraryPath contains paths to the library DEX jar on host and on device.
type LibraryPath struct {
// 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

// 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
	Device string
}

// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
type LibraryPaths map[string]*LibraryPath

type classLoaderContext struct {
	// Library names
	Names []string

	// The class loader context using paths in the build.
	Host android.Paths
	// On-device install path (used in dex2oat argument --stored-class-loader-context).
	Device string

	// The class loader context using paths as they will be on the device.
	Target []string
	// Nested class loader subcontexts for dependencies.
	Subcontexts []*ClassLoaderContext
}

// 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
// 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

// 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}
	}
	return nil
	if installPath != nil {
		devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
	}

// Wrapper around addLibraryPath that does error reporting.
func (libPaths LibraryPaths) addLibraryPathOrReportError(ctx android.ModuleInstallPathContext, lib string,
	hostPath, installPath android.Path, strict bool) {
	subcontexts := nestedClcMap[AnySdkVersion]

	err := libPaths.addLibraryPath(ctx, lib, hostPath, installPath, strict)
	if err != nil {
		android.ReportPathErrorf(ctx, err.Error())
	// 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
		}
	}

// 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)
	clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
		Name:        lib,
		Host:        hostPath,
		Device:      devicePath,
		Subcontexts: subcontexts,
	})
	return 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) {
	if lib != nil {
		libPaths.addLibraryPathOrReportError(ctx, *lib, hostPath, installPath, false)
	}
}
// 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) {

// 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
		}
	err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, strict, nestedClcMap)
	if err != nil {
		ctx.ModuleErrorf(err.Error())
		android.ReportPathErrorf(ctx, err.Error())
	}
}

func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
	if _, ok := m[sdkVer]; !ok {
		m[sdkVer] = &classLoaderContext{}
	}
	return m[sdkVer]
}
// Add class loader context. Fail on unknown build/install paths.
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
	hostPath, installPath android.Path) {

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)
	clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, hostPath, installPath, true, nil)
}

func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig,
	libs ...string) (bool, error) {
// 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) {

	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
			}
	if lib != nil {
		clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, hostPath, installPath, false, nil)
	}
}
	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"))
	}
// 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) usesLibs() []string {
	if clc, ok := m[AnySdkVersion]; ok {
		return clc.Names
// 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
				}
	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
			if !alreadyHave {
				clcMap[sdkVer] = append(clcMap[sdkVer], otherClc)
			}

		// 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
// 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)
	}

	} 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 &.
	return ulibs
}

	fixConditionalClassLoaderContext(classLoaderContexts)

	return &classLoaderContexts, nil
func usesLibsRec(clcs []*ClassLoaderContext) (ulibs []string) {
	for _, clc := range clcs {
		ulibs = append(ulibs, clc.Name)
		ulibs = append(ulibs, usesLibsRec(clc.Subcontexts)...)
	}
	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
}

		if hostPaths != nil {
			sdkVerStr := fmt.Sprintf("%d", ver)
			if ver == AnySdkVersion {
// 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
		}
			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, "#"))
		hostClc, targetClc, hostPaths := computeClassLoaderContextRec(clcMap[sdkVer])
		if hostPaths != nil {
			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, 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...)
	}

	return clcStr, paths
	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

// A map from SDK version (represented with a JSON string) to JSON class loader context.
type jsonClassLoaderContextMap map[string]jsonClassLoaderContext

// 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,
// 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
}
+62 −71

File changed.

Preview size limit exceeded, changes collapsed.

+4 −6
Original line number Diff line number Diff line
@@ -115,9 +115,7 @@ type ModuleConfig struct {
	ProfileBootListing   android.OptionalPath

	EnforceUsesLibraries bool
	OptionalUsesLibraries []string
	UsesLibraries         []string
	LibraryPaths          LibraryPaths
	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)
+24 −10

File changed.

Preview size limit exceeded, changes collapsed.

+1 −3
Original line number Diff line number Diff line
@@ -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{}},
Loading