Merge changes from topic "cherrypicker-L27000030003160683:N90900030051335582" into main

* changes:
  Propagate transitive missing optional_uses_libs.
  Refactor the contruction of the manifest check inputs.
This commit is contained in:
Treehugger Robot 2024-04-16 13:35:54 +00:00 committed by Gerrit Code Review
commit 9a8255f48e
9 changed files with 146 additions and 77 deletions

View file

@ -323,6 +323,7 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont
} else if clc.Host == hostPath && clc.Device == devicePath {
// Ok, the same library with the same paths. Don't re-add it, but don't raise an error
// either, as the same library may be reachable via different transitional dependencies.
clc.Optional = clc.Optional && optional
return nil
} else {
// Fail, as someone is trying to add the same library with different paths. This likely

View file

@ -356,12 +356,13 @@ type aaptBuildActionOptions struct {
forceNonFinalResourceIDs bool
extraLinkFlags []string
aconfigTextFiles android.Paths
usesLibrary *usesLibrary
}
func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptions) {
staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedExportPackages, libFlags :=
aaptLibs(ctx, opts.sdkContext, opts.classLoaderContexts)
aaptLibs(ctx, opts.sdkContext, opts.classLoaderContexts, opts.usesLibrary)
// Exclude any libraries from the supplied list.
opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)
@ -703,7 +704,8 @@ func (t transitiveAarDeps) assets() android.Paths {
}
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext,
classLoaderContexts dexpreopt.ClassLoaderContextMap, usesLibrary *usesLibrary) (
staticResourcesNodes, sharedResourcesNodes *android.DepSet[*resourcesNode], staticRRODirs *android.DepSet[rroDir],
staticManifests *android.DepSet[android.Path], sharedLibs android.Paths, flags []string) {
@ -753,6 +755,9 @@ func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoa
}
addCLCFromDep(ctx, module, classLoaderContexts)
if usesLibrary != nil {
addMissingOptionalUsesLibsFromDep(ctx, module, usesLibrary)
}
})
// AAPT2 overlays are in lowest to highest priority order, the topological order will be reversed later.
@ -805,12 +810,12 @@ func (a *AndroidLibrary) OutputFiles(tag string) (android.Paths, error) {
var _ AndroidLibraryDependency = (*AndroidLibrary)(nil)
func (a *AndroidLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
a.usesLibrary.deps(ctx, false)
a.Module.deps(ctx)
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
a.usesLibrary.deps(ctx, false)
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
@ -829,6 +834,7 @@ func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
classLoaderContexts: a.classLoaderContexts,
enforceDefaultTargetSdkVersion: false,
aconfigTextFiles: getAconfigFilePaths(ctx),
usesLibrary: &a.usesLibrary,
},
)
@ -1215,7 +1221,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
linkDeps = append(linkDeps, a.manifest)
staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags :=
aaptLibs(ctx, android.SdkContext(a), nil)
aaptLibs(ctx, android.SdkContext(a), nil, nil)
_ = sharedResourcesNodesDepSet
_ = staticRRODirsDepSet
@ -1287,6 +1293,7 @@ func (a *AARImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
}
addCLCFromDep(ctx, module, a.classLoaderContexts)
addMissingOptionalUsesLibsFromDep(ctx, module, &a.usesLibrary)
})
var implementationJarFile android.OutputPath
@ -1405,6 +1412,12 @@ func (a *AARImport) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
var _ android.PrebuiltInterface = (*AARImport)(nil)
func (a *AARImport) UsesLibrary() *usesLibrary {
return &a.usesLibrary
}
var _ ModuleWithUsesLibrary = (*AARImport)(nil)
// android_library_import imports an `.aar` file into the build graph as if it was built with android_library.
//
// This module is not suitable for installing on a device, but can be used as a `static_libs` dependency of

View file

@ -249,13 +249,13 @@ func (c Certificate) AndroidMkString() string {
}
func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
a.Module.deps(ctx)
if String(a.appProperties.Stl) == "c++_shared" && !a.SdkVersion(ctx).Specified() {
ctx.PropertyErrorf("stl", "sdk_version must be set in order to use c++_shared")
}
sdkDep := decodeSdkDep(ctx, android.SdkContext(a))
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
a.Module.deps(ctx)
if sdkDep.hasFrameworkLibs() {
a.aapt.deps(ctx, sdkDep)
}
@ -285,9 +285,6 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
}
ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)
}
a.usesLibrary.deps(ctx, sdkDep.hasFrameworkLibs())
for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
}
@ -534,6 +531,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
forceNonFinalResourceIDs: nonFinalIds,
extraLinkFlags: aaptLinkFlags,
aconfigTextFiles: getAconfigFilePaths(ctx),
usesLibrary: &a.usesLibrary,
},
)
@ -815,18 +813,10 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
a.usesLibrary.freezeEnforceUsesLibraries()
// Add implicit SDK libraries to <uses-library> list.
requiredUsesLibs, optionalUsesLibs := a.classLoaderContexts.UsesLibs()
for _, usesLib := range requiredUsesLibs {
a.usesLibrary.addLib(usesLib, false)
}
for _, usesLib := range optionalUsesLibs {
a.usesLibrary.addLib(usesLib, true)
}
// Check that the <uses-library> list is coherent with the manifest.
if a.usesLibrary.enforceUsesLibraries() {
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(
ctx, a.mergedManifestFile, &a.classLoaderContexts)
apkDeps = append(apkDeps, manifestCheckFile)
}
@ -1596,6 +1586,9 @@ type UsesLibraryProperties struct {
// provide the android.test.base statically and use jarjar to rename them so they do not collide
// with the classes provided by the android.test.base library.
Exclude_uses_libs []string
// The module names of optional uses-library libraries that are missing from the source tree.
Missing_optional_uses_libs []string `blueprint:"mutated"`
}
// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
@ -1612,20 +1605,11 @@ type usesLibrary struct {
shouldDisableDexpreopt bool
}
func (u *usesLibrary) addLib(lib string, optional bool) {
if !android.InList(lib, u.usesLibraryProperties.Uses_libs) && !android.InList(lib, u.usesLibraryProperties.Optional_uses_libs) {
if optional {
u.usesLibraryProperties.Optional_uses_libs = append(u.usesLibraryProperties.Optional_uses_libs, lib)
} else {
u.usesLibraryProperties.Uses_libs = append(u.usesLibraryProperties.Uses_libs, lib)
}
}
}
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps bool) {
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
presentOptionalUsesLibs := u.presentOptionalUsesLibs(ctx)
ctx.AddVariationDependencies(nil, usesLibOptTag, presentOptionalUsesLibs...)
// Only add these extra dependencies if the module is an app that depends on framework
// libs. This avoids creating a cyclic dependency:
// e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
@ -1636,6 +1620,8 @@ func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, addCompatDeps boo
ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
_, diff, _ := android.ListSetDifference(u.usesLibraryProperties.Optional_uses_libs, presentOptionalUsesLibs)
u.usesLibraryProperties.Missing_optional_uses_libs = diff
} else {
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.usesLibraryProperties.Uses_libs...)
ctx.AddVariationDependencies(nil, r8LibraryJarTag, u.presentOptionalUsesLibs(ctx)...)
@ -1654,15 +1640,6 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s
return optionalUsesLibs
}
// Helper function to replace string in a list.
func replaceInList(list []string, oldstr, newstr string) {
for i, str := range list {
if str == oldstr {
list[i] = newstr
}
}
}
// Returns a map of module names of shared library dependencies to the paths to their dex jars on
// host and on device.
func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
@ -1704,11 +1681,6 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
libName := dep
if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
libName = *ulib.ProvidesUsesLib()
// Replace module name with library name in `uses_libs`/`optional_uses_libs` in
// order to pass verify_uses_libraries check (which compares these properties
// against library names written in the manifest).
replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
@ -1742,7 +1714,7 @@ func (u *usesLibrary) freezeEnforceUsesLibraries() {
// an APK with the manifest embedded in it (manifest_check will know which one it is by the file
// extension: APKs are supposed to end with '.apk').
func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile android.Path,
outputFile android.WritablePath) android.Path {
outputFile android.WritablePath, classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
@ -1770,27 +1742,37 @@ func (u *usesLibrary) verifyUsesLibraries(ctx android.ModuleContext, inputFile a
cmd.Flag("--enforce-uses-libraries-relax")
}
for _, lib := range u.usesLibraryProperties.Uses_libs {
requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
for _, lib := range requiredUsesLibs {
cmd.FlagWithArg("--uses-library ", lib)
}
for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
for _, lib := range optionalUsesLibs {
cmd.FlagWithArg("--optional-uses-library ", lib)
}
// Also add missing optional uses libs, as the manifest check expects them.
// Note that what we add here are the module names of those missing libs, not library names, while
// the manifest check actually expects library names. However, the case where a library is missing
// and the module name != the library name is too rare for us to handle.
for _, lib := range u.usesLibraryProperties.Missing_optional_uses_libs {
cmd.FlagWithArg("--missing-optional-uses-library ", lib)
}
rule.Build("verify_uses_libraries", "verify <uses-library>")
return outputFile
}
// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against
// the build system and returns the path to a copy of the manifest.
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path,
classLoaderContexts *dexpreopt.ClassLoaderContextMap) android.Path {
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
return u.verifyUsesLibraries(ctx, manifest, outputFile)
return u.verifyUsesLibraries(ctx, manifest, outputFile, classLoaderContexts)
}
// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the build
// system and returns the path to a copy of the APK.
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) {
u.verifyUsesLibraries(ctx, apk, nil) // for APKs manifest_check does not write output file
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path,
classLoaderContexts *dexpreopt.ClassLoaderContextMap) {
u.verifyUsesLibraries(ctx, apk, nil, classLoaderContexts) // for APKs manifest_check does not write output file
}

View file

@ -355,7 +355,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
}
if a.usesLibrary.enforceUsesLibraries() {
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk, &a.dexpreopter.classLoaderContexts)
}
a.dexpreopter.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), jnisUncompressed)
@ -611,6 +611,12 @@ func createArchDpiVariantGroupType(archNames []string, dpiNames []string) reflec
return return_struct
}
func (a *AndroidAppImport) UsesLibrary() *usesLibrary {
return &a.usesLibrary
}
var _ ModuleWithUsesLibrary = (*AndroidAppImport)(nil)
// android_app_import imports a prebuilt apk with additional processing specified in the module.
// DPI-specific apk source files can be specified using dpi_variants. Example:
//

View file

@ -3244,7 +3244,10 @@ func TestUsesLibraries(t *testing.T) {
name: "static-y",
srcs: ["a.java"],
uses_libs: ["runtime-required-y"],
optional_uses_libs: ["runtime-optional-y"],
optional_uses_libs: [
"runtime-optional-y",
"missing-lib-a",
],
sdk_version: "current",
}
@ -3280,7 +3283,7 @@ func TestUsesLibraries(t *testing.T) {
sdk_version: "current",
optional_uses_libs: [
"bar",
"baz",
"missing-lib-b",
],
}
@ -3295,7 +3298,7 @@ func TestUsesLibraries(t *testing.T) {
],
optional_uses_libs: [
"bar",
"baz",
"missing-lib-b",
],
}
`
@ -3317,10 +3320,10 @@ func TestUsesLibraries(t *testing.T) {
// propagated from dependencies.
actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
expectManifestFixerArgs := `--extract-native-libs=true ` +
`--uses-library qux ` +
`--uses-library quuz ` +
`--uses-library foo ` +
`--uses-library com.non.sdk.lib ` +
`--uses-library qux ` +
`--uses-library quuz ` +
`--uses-library runtime-library ` +
`--uses-library runtime-required-x ` +
`--uses-library runtime-required-y ` +
@ -3339,9 +3342,10 @@ func TestUsesLibraries(t *testing.T) {
`--uses-library runtime-required-x ` +
`--uses-library runtime-required-y ` +
`--optional-uses-library bar ` +
`--optional-uses-library baz ` +
`--optional-uses-library runtime-optional-x ` +
`--optional-uses-library runtime-optional-y `
`--optional-uses-library runtime-optional-y ` +
`--missing-optional-uses-library missing-lib-b ` +
`--missing-optional-uses-library missing-lib-a`
android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
// Test that all libraries are verified for an APK (library order matters).
@ -3350,7 +3354,7 @@ func TestUsesLibraries(t *testing.T) {
`--uses-library com.non.sdk.lib ` +
`--uses-library android.test.runner ` +
`--optional-uses-library bar ` +
`--optional-uses-library baz `
`--missing-optional-uses-library missing-lib-b `
android.AssertStringDoesContain(t, "verify apk cmd args", verifyApkCmd, verifyApkArgs)
// Test that necessary args are passed for constructing CLC in Ninja phase.

View file

@ -843,9 +843,11 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
if dep != nil {
if component, ok := dep.(SdkLibraryComponentDependency); ok {
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
// Add library as optional if it's one of the optional compatibility libs.
// Add library as optional if it's one of the optional compatibility libs or it's
// explicitly listed in the optional_uses_libs property.
tag := usesLibReqTag
if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) ||
android.InList(*lib, j.usesLibrary.usesLibraryProperties.Optional_uses_libs) {
tag = usesLibOptTag
}
ctx.AddVariationDependencies(nil, tag, *lib)
@ -2387,6 +2389,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
addCLCFromDep(ctx, module, j.classLoaderContexts)
addMissingOptionalUsesLibsFromDep(ctx, module, &j.usesLibrary)
})
return deps
@ -2720,3 +2723,13 @@ type ModuleWithStem interface {
}
var _ ModuleWithStem = (*Module)(nil)
type ModuleWithUsesLibrary interface {
UsesLibrary() *usesLibrary
}
func (j *Module) UsesLibrary() *usesLibrary {
return &j.usesLibrary
}
var _ ModuleWithUsesLibrary = (*Module)(nil)

View file

@ -966,8 +966,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
j.deps(ctx)
j.usesLibrary.deps(ctx, false)
j.deps(ctx)
}
const (
@ -3162,13 +3162,35 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module,
// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
// from its CLC should be added to the current CLC.
if sdkLib != nil {
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
optional := false
if module, ok := ctx.Module().(ModuleWithUsesLibrary); ok {
if android.InList(*sdkLib, module.UsesLibrary().usesLibraryProperties.Optional_uses_libs) {
optional = true
}
}
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, optional,
dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}
func addMissingOptionalUsesLibsFromDep(ctx android.ModuleContext, depModule android.Module,
usesLibrary *usesLibrary) {
dep, ok := depModule.(ModuleWithUsesLibrary)
if !ok {
return
}
for _, lib := range dep.UsesLibrary().usesLibraryProperties.Missing_optional_uses_libs {
if !android.InList(lib, usesLibrary.usesLibraryProperties.Missing_optional_uses_libs) {
usesLibrary.usesLibraryProperties.Missing_optional_uses_libs =
append(usesLibrary.usesLibraryProperties.Missing_optional_uses_libs, lib)
}
}
}
type JavaApiContributionImport struct {
JavaApiContribution

View file

@ -51,6 +51,14 @@ def parse_args():
help='specify uses-library entries known to the build system with '
'required:false'
)
parser.add_argument(
'--missing-optional-uses-library',
dest='missing_optional_uses_libraries',
action='append',
help='specify uses-library entries missing from the build system with '
'required:false',
default=[]
)
parser.add_argument(
'--enforce-uses-libraries',
dest='enforce_uses_libraries',
@ -91,7 +99,7 @@ C_OFF = "\033[0m"
C_BOLD = "\033[1m"
def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
def enforce_uses_libraries(manifest, required, optional, missing_optional, relax, is_apk, path):
"""Verify that the <uses-library> tags in the manifest match those provided
by the build system.
@ -119,7 +127,12 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
required = trim_namespace_parts(required)
optional = trim_namespace_parts(optional)
if manifest_required == required and manifest_optional == optional:
existing_manifest_optional = [
lib for lib in manifest_optional if lib not in missing_optional]
# The order of the existing libraries matter, while the order of the missing
# ones doesn't.
if manifest_required == required and existing_manifest_optional == optional:
return None
#pylint: disable=line-too-long
@ -129,6 +142,7 @@ def enforce_uses_libraries(manifest, required, optional, relax, is_apk, path):
'\t- required libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(required), C_OFF),
'\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_required), C_OFF),
'\t- optional libraries in build system: %s[%s]%s\n' % (C_RED, ', '.join(optional), C_OFF),
'\t and missing ones in build system: %s[%s]%s\n' % (C_RED, ', '.join(missing_optional), C_OFF),
'\t vs. in the manifest: %s[%s]%s\n' % (C_RED, ', '.join(manifest_optional), C_OFF),
'\t- tags in the manifest (%s):\n' % path,
'\t\t%s\n' % '\t\t'.join(tags),
@ -340,11 +354,14 @@ def main():
if args.enforce_uses_libraries:
# Load dexpreopt.config files and build a mapping from module
# names to library names. This is necessary because build system
# addresses libraries by their module name (`uses_libs`,
# `optional_uses_libs`, `LOCAL_USES_LIBRARIES`,
# `LOCAL_OPTIONAL_LIBRARY_NAMES` all contain module names), while
# the manifest addresses libraries by their name.
# names to library names. This is for Make only and it's necessary
# because Make passes module names from `LOCAL_USES_LIBRARIES`,
# `LOCAL_OPTIONAL_LIBRARY_NAMES`, while the manifest addresses
# libraries by their name. Soong doesn't use it and doesn't need it
# because it converts the module names to the library names and
# passes the library names. There is no need to translate missing
# optional libs because they are missing and therefore there is no
# mapping for them.
mod_to_lib = load_dexpreopt_configs(args.dexpreopt_configs)
required = translate_libnames(args.uses_libraries, mod_to_lib)
optional = translate_libnames(args.optional_uses_libraries,
@ -354,8 +371,8 @@ def main():
# those in the manifest. Raise an exception on mismatch, unless the
# script was passed a special parameter to suppress exceptions.
errmsg = enforce_uses_libraries(manifest, required, optional,
args.enforce_uses_libraries_relax,
is_apk, args.input)
args.missing_optional_uses_libraries,
args.enforce_uses_libraries_relax, is_apk, args.input)
# Create a status file that is empty on success, or contains an
# error message on failure. When exceptions are suppressed,

View file

@ -44,15 +44,17 @@ def required_apk(value):
class EnforceUsesLibrariesTest(unittest.TestCase):
"""Unit tests for add_extract_native_libs function."""
def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
def run_test(self, xml, apk, uses_libraries=[], optional_uses_libraries=[],
missing_optional_uses_libraries=[]): #pylint: disable=dangerous-default-value
doc = minidom.parseString(xml)
try:
relax = False
manifest_check.enforce_uses_libraries(
doc, uses_libraries, optional_uses_libraries, relax, False,
'path/to/X/AndroidManifest.xml')
doc, uses_libraries, optional_uses_libraries, missing_optional_uses_libraries,
relax, False, 'path/to/X/AndroidManifest.xml')
manifest_check.enforce_uses_libraries(apk, uses_libraries,
optional_uses_libraries,
missing_optional_uses_libraries,
relax, True,
'path/to/X/X.apk')
return True
@ -102,6 +104,15 @@ class EnforceUsesLibrariesTest(unittest.TestCase):
matches = self.run_test(xml, apk, optional_uses_libraries=['foo'])
self.assertFalse(matches)
def test_expected_missing_optional_uses_library(self):
xml = self.xml_tmpl % (
uses_library_xml('foo') + uses_library_xml('missing') + uses_library_xml('bar'))
apk = self.apk_tmpl % (
uses_library_apk('foo') + uses_library_apk('missing') + uses_library_apk('bar'))
matches = self.run_test(xml, apk, optional_uses_libraries=['foo', 'bar'],
missing_optional_uses_libraries=['missing'])
self.assertFalse(matches)
def test_missing_uses_library(self):
xml = self.xml_tmpl % ('')
apk = self.apk_tmpl % ('')