Port uses-shared library verification and dexpreopting to Soong
Ports 09f3b97f4b488cd3a7b7d72038b173575b02c162 (Add support for preopt with uses-libraries) from Make to Soong to support verifying and preopting shared libraries. This reapplies Id25f55f07a55120bebe2a9b32c094209efc85c8b with fixes for unbundled builds and builds with ALLOW_MISSING_DEPENDENCIES=true set. Bug: 132357300 Test: app_test.go Test: m checkbuild Change-Id: I964309a68ec4ed081f3f3154879c71048ecb5455
This commit is contained in:
parent
7d06395f0c
commit
50ddcc4b69
|
@ -1103,6 +1103,10 @@ func (c *config) ProductCompatibleProperty() bool {
|
||||||
return Bool(c.productVariables.ProductCompatibleProperty)
|
return Bool(c.productVariables.ProductCompatibleProperty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *config) MissingUsesLibraries() []string {
|
||||||
|
return c.productVariables.MissingUsesLibraries
|
||||||
|
}
|
||||||
|
|
||||||
func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
|
func (c *deviceConfig) BoardVndkRuntimeDisable() bool {
|
||||||
return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
|
return Bool(c.config.productVariables.BoardVndkRuntimeDisable)
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,8 @@ type productVariables struct {
|
||||||
ProductCompatibleProperty *bool `json:",omitempty"`
|
ProductCompatibleProperty *bool `json:",omitempty"`
|
||||||
|
|
||||||
TargetFSConfigGen []string `json:",omitempty"`
|
TargetFSConfigGen []string `json:",omitempty"`
|
||||||
|
|
||||||
|
MissingUsesLibraries []string `json:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func boolPtr(v bool) *bool {
|
func boolPtr(v bool) *bool {
|
||||||
|
|
|
@ -65,8 +65,6 @@ type GlobalConfig struct {
|
||||||
AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
|
AlwaysOtherDebugInfo bool // always generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
|
||||||
NeverOtherDebugInfo bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
|
NeverOtherDebugInfo bool // never generate mini debug info for non-system server modules (overrides NoDebugInfo=true)
|
||||||
|
|
||||||
MissingUsesLibraries []string // libraries that may be listed in OptionalUsesLibraries but will not be installed by the product
|
|
||||||
|
|
||||||
IsEng bool // build is a eng variant
|
IsEng bool // build is a eng variant
|
||||||
SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
|
SanitizeLite bool // build is the second phase of a SANITIZE_LITE build
|
||||||
|
|
||||||
|
@ -119,7 +117,7 @@ type ModuleConfig struct {
|
||||||
ProfileIsTextListing bool
|
ProfileIsTextListing bool
|
||||||
|
|
||||||
EnforceUsesLibraries bool
|
EnforceUsesLibraries bool
|
||||||
OptionalUsesLibraries []string
|
PresentOptionalUsesLibraries []string
|
||||||
UsesLibraries []string
|
UsesLibraries []string
|
||||||
LibraryPaths map[string]android.Path
|
LibraryPaths map[string]android.Path
|
||||||
|
|
||||||
|
@ -310,7 +308,6 @@ func GlobalConfigForTests(ctx android.PathContext) GlobalConfig {
|
||||||
NeverSystemServerDebugInfo: false,
|
NeverSystemServerDebugInfo: false,
|
||||||
AlwaysOtherDebugInfo: false,
|
AlwaysOtherDebugInfo: false,
|
||||||
NeverOtherDebugInfo: false,
|
NeverOtherDebugInfo: false,
|
||||||
MissingUsesLibraries: nil,
|
|
||||||
IsEng: false,
|
IsEng: false,
|
||||||
SanitizeLite: false,
|
SanitizeLite: false,
|
||||||
DefaultAppImages: false,
|
DefaultAppImages: false,
|
||||||
|
|
|
@ -226,11 +226,6 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
||||||
bootImageLocation = PathToLocation(bootImage, arch)
|
bootImageLocation = PathToLocation(bootImage, arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lists of used and optional libraries from the build config, with optional libraries that are known to not
|
|
||||||
// be present in the current product removed.
|
|
||||||
var filteredUsesLibs []string
|
|
||||||
var filteredOptionalUsesLibs []string
|
|
||||||
|
|
||||||
// The class loader context using paths in the build
|
// The class loader context using paths in the build
|
||||||
var classLoaderContextHost android.Paths
|
var classLoaderContextHost android.Paths
|
||||||
|
|
||||||
|
@ -248,11 +243,10 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
||||||
var classLoaderContextHostString string
|
var classLoaderContextHostString string
|
||||||
|
|
||||||
if module.EnforceUsesLibraries {
|
if module.EnforceUsesLibraries {
|
||||||
filteredOptionalUsesLibs = filterOut(global.MissingUsesLibraries, module.OptionalUsesLibraries)
|
usesLibs := append(copyOf(module.UsesLibraries), module.PresentOptionalUsesLibraries...)
|
||||||
filteredUsesLibs = append(copyOf(module.UsesLibraries), filteredOptionalUsesLibs...)
|
|
||||||
|
|
||||||
// Create class loader context for dex2oat from uses libraries and filtered optional libraries
|
// Create class loader context for dex2oat from uses libraries and filtered optional libraries
|
||||||
for _, l := range filteredUsesLibs {
|
for _, l := range usesLibs {
|
||||||
|
|
||||||
classLoaderContextHost = append(classLoaderContextHost,
|
classLoaderContextHost = append(classLoaderContextHost,
|
||||||
pathForLibrary(module, l))
|
pathForLibrary(module, l))
|
||||||
|
@ -267,7 +261,9 @@ func dexpreoptCommand(ctx android.PathContext, global GlobalConfig, module Modul
|
||||||
// targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly depend on
|
// targetSdkVersion in the manifest or APK is < 28, and the module does not explicitly depend on
|
||||||
// org.apache.http.legacy, then implicitly add the classes to the classpath for dexpreopt. One the
|
// org.apache.http.legacy, then implicitly add the classes to the classpath for dexpreopt. One the
|
||||||
// device the classes will be in a file called org.apache.http.legacy.impl.jar.
|
// device the classes will be in a file called org.apache.http.legacy.impl.jar.
|
||||||
if !contains(module.UsesLibraries, httpLegacy) && !contains(module.OptionalUsesLibraries, httpLegacy) {
|
module.LibraryPaths[httpLegacyImpl] = module.LibraryPaths[httpLegacy]
|
||||||
|
|
||||||
|
if !contains(module.UsesLibraries, httpLegacy) && !contains(module.PresentOptionalUsesLibraries, httpLegacy) {
|
||||||
conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
|
conditionalClassLoaderContextHost28 = append(conditionalClassLoaderContextHost28,
|
||||||
pathForLibrary(module, httpLegacyImpl))
|
pathForLibrary(module, httpLegacyImpl))
|
||||||
conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
|
conditionalClassLoaderContextTarget28 = append(conditionalClassLoaderContextTarget28,
|
||||||
|
|
|
@ -33,7 +33,7 @@ func testModuleConfig(ctx android.PathContext) ModuleConfig {
|
||||||
ProfileClassListing: android.OptionalPath{},
|
ProfileClassListing: android.OptionalPath{},
|
||||||
ProfileIsTextListing: false,
|
ProfileIsTextListing: false,
|
||||||
EnforceUsesLibraries: false,
|
EnforceUsesLibraries: false,
|
||||||
OptionalUsesLibraries: nil,
|
PresentOptionalUsesLibraries: nil,
|
||||||
UsesLibraries: nil,
|
UsesLibraries: nil,
|
||||||
LibraryPaths: nil,
|
LibraryPaths: nil,
|
||||||
Archs: []android.ArchType{android.Arm},
|
Archs: []android.ArchType{android.Arm},
|
||||||
|
|
173
java/app.go
173
java/app.go
|
@ -17,12 +17,13 @@ package java
|
||||||
// This file contains the module types for compiling Android apps.
|
// This file contains the module types for compiling Android apps.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/blueprint"
|
|
||||||
"github.com/google/blueprint/proptools"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/cc"
|
"android/soong/cc"
|
||||||
"android/soong/tradefed"
|
"android/soong/tradefed"
|
||||||
|
@ -119,6 +120,8 @@ type AndroidApp struct {
|
||||||
aapt
|
aapt
|
||||||
android.OverridableModuleBase
|
android.OverridableModuleBase
|
||||||
|
|
||||||
|
usesLibrary usesLibrary
|
||||||
|
|
||||||
certificate Certificate
|
certificate Certificate
|
||||||
|
|
||||||
appProperties appProperties
|
appProperties appProperties
|
||||||
|
@ -176,6 +179,8 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.usesLibrary.deps(ctx, Bool(a.properties.No_framework_libs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
|
func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
|
@ -276,6 +281,7 @@ func (a *AndroidApp) aaptBuildActions(ctx android.ModuleContext) {
|
||||||
aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
|
aaptLinkFlags = append(aaptLinkFlags, a.additionalAaptFlags...)
|
||||||
|
|
||||||
a.aapt.splitNames = a.appProperties.Package_splits
|
a.aapt.splitNames = a.appProperties.Package_splits
|
||||||
|
a.aapt.sdkLibraries = a.exportedSdkLibs
|
||||||
|
|
||||||
a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
|
a.aapt.buildActions(ctx, sdkContext(a), aaptLinkFlags...)
|
||||||
|
|
||||||
|
@ -308,9 +314,17 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
|
||||||
} else {
|
} else {
|
||||||
installDir = filepath.Join("app", a.installApkName)
|
installDir = filepath.Join("app", a.installApkName)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
|
a.dexpreopter.installPath = android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
|
||||||
a.dexpreopter.isInstallable = Bool(a.properties.Installable)
|
a.dexpreopter.isInstallable = Bool(a.properties.Installable)
|
||||||
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||||
|
|
||||||
|
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||||
|
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
||||||
|
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
||||||
|
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
||||||
|
a.dexpreopter.manifestFile = a.mergedManifestFile
|
||||||
|
|
||||||
a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
|
a.deviceProperties.UncompressDex = a.dexpreopter.uncompressedDex
|
||||||
|
|
||||||
if ctx.ModuleName() != "framework-res" {
|
if ctx.ModuleName() != "framework-res" {
|
||||||
|
@ -368,12 +382,19 @@ func processMainCert(m android.ModuleBase, certPropValue string, certificates []
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
var apkDeps android.Paths
|
||||||
|
|
||||||
// Check if the install APK name needs to be overridden.
|
// Check if the install APK name needs to be overridden.
|
||||||
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
|
a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name())
|
||||||
|
|
||||||
// Process all building blocks, from AAPT to certificates.
|
// Process all building blocks, from AAPT to certificates.
|
||||||
a.aaptBuildActions(ctx)
|
a.aaptBuildActions(ctx)
|
||||||
|
|
||||||
|
if a.usesLibrary.enforceUsesLibraries() {
|
||||||
|
manifestCheckFile := a.usesLibrary.verifyUsesLibrariesManifest(ctx, a.mergedManifestFile)
|
||||||
|
apkDeps = append(apkDeps, manifestCheckFile)
|
||||||
|
}
|
||||||
|
|
||||||
a.proguardBuildActions(ctx)
|
a.proguardBuildActions(ctx)
|
||||||
|
|
||||||
dexJarFile := a.dexBuildActions(ctx)
|
dexJarFile := a.dexBuildActions(ctx)
|
||||||
|
@ -391,13 +412,13 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
// Build a final signed app package.
|
// Build a final signed app package.
|
||||||
// TODO(jungjw): Consider changing this to installApkName.
|
// TODO(jungjw): Consider changing this to installApkName.
|
||||||
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
|
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".apk")
|
||||||
CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates)
|
CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps)
|
||||||
a.outputFile = packageFile
|
a.outputFile = packageFile
|
||||||
|
|
||||||
for _, split := range a.aapt.splits {
|
for _, split := range a.aapt.splits {
|
||||||
// Sign the split APKs
|
// Sign the split APKs
|
||||||
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
|
packageFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"_"+split.suffix+".apk")
|
||||||
CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates)
|
CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps)
|
||||||
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
|
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,7 +504,8 @@ func AndroidAppFactory() android.Module {
|
||||||
&module.Module.protoProperties,
|
&module.Module.protoProperties,
|
||||||
&module.aaptProperties,
|
&module.aaptProperties,
|
||||||
&module.appProperties,
|
&module.appProperties,
|
||||||
&module.overridableAppProperties)
|
&module.overridableAppProperties,
|
||||||
|
&module.usesLibrary.usesLibraryProperties)
|
||||||
|
|
||||||
module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
|
module.Prefer32(func(ctx android.BaseModuleContext, base *android.ModuleBase, class android.OsClass) bool {
|
||||||
return class == android.Device && ctx.Config().DevicePrefer32BitApps()
|
return class == android.Device && ctx.Config().DevicePrefer32BitApps()
|
||||||
|
@ -559,6 +581,7 @@ func AndroidTestFactory() android.Module {
|
||||||
&module.appProperties,
|
&module.appProperties,
|
||||||
&module.appTestProperties,
|
&module.appTestProperties,
|
||||||
&module.overridableAppProperties,
|
&module.overridableAppProperties,
|
||||||
|
&module.usesLibrary.usesLibraryProperties,
|
||||||
&module.testProperties)
|
&module.testProperties)
|
||||||
|
|
||||||
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
||||||
|
@ -599,7 +622,8 @@ func AndroidTestHelperAppFactory() android.Module {
|
||||||
&module.aaptProperties,
|
&module.aaptProperties,
|
||||||
&module.appProperties,
|
&module.appProperties,
|
||||||
&module.appTestHelperAppProperties,
|
&module.appTestHelperAppProperties,
|
||||||
&module.overridableAppProperties)
|
&module.overridableAppProperties,
|
||||||
|
&module.usesLibrary.usesLibraryProperties)
|
||||||
|
|
||||||
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
|
||||||
android.InitDefaultableModule(module)
|
android.InitDefaultableModule(module)
|
||||||
|
@ -666,6 +690,8 @@ type AndroidAppImport struct {
|
||||||
certificate *Certificate
|
certificate *Certificate
|
||||||
|
|
||||||
dexpreopter
|
dexpreopter
|
||||||
|
|
||||||
|
usesLibrary usesLibrary
|
||||||
}
|
}
|
||||||
|
|
||||||
type AndroidAppImportProperties struct {
|
type AndroidAppImportProperties struct {
|
||||||
|
@ -753,6 +779,8 @@ func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||||
if cert != "" {
|
if cert != "" {
|
||||||
ctx.AddDependency(ctx.Module(), certificateTag, cert)
|
ctx.AddDependency(ctx.Module(), certificateTag, cert)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.usesLibrary.deps(ctx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
|
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
|
||||||
|
@ -808,7 +836,12 @@ func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext
|
||||||
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
|
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
|
||||||
// TODO: LOCAL_PACKAGE_SPLITS
|
// TODO: LOCAL_PACKAGE_SPLITS
|
||||||
|
|
||||||
srcApk := android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
|
var srcApk android.Path
|
||||||
|
srcApk = android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx))
|
||||||
|
|
||||||
|
if a.usesLibrary.enforceUsesLibraries() {
|
||||||
|
srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Install or embed JNI libraries
|
// TODO: Install or embed JNI libraries
|
||||||
|
|
||||||
|
@ -821,6 +854,12 @@ func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext
|
||||||
a.dexpreopter.isInstallable = true
|
a.dexpreopter.isInstallable = true
|
||||||
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
|
a.dexpreopter.isPresignedPrebuilt = Bool(a.properties.Presigned)
|
||||||
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
a.dexpreopter.uncompressedDex = a.shouldUncompressDex(ctx)
|
||||||
|
|
||||||
|
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
|
||||||
|
a.dexpreopter.usesLibs = a.usesLibrary.usesLibraryProperties.Uses_libs
|
||||||
|
a.dexpreopter.optionalUsesLibs = a.usesLibrary.presentOptionalUsesLibs(ctx)
|
||||||
|
a.dexpreopter.libraryPaths = a.usesLibrary.usesLibraryPaths(ctx)
|
||||||
|
|
||||||
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
|
dexOutput := a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
|
||||||
if a.dexpreopter.uncompressedDex {
|
if a.dexpreopter.uncompressedDex {
|
||||||
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
|
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
|
||||||
|
@ -866,9 +905,129 @@ func AndroidAppImportFactory() android.Module {
|
||||||
module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface()
|
module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface()
|
||||||
module.AddProperties(&module.properties)
|
module.AddProperties(&module.properties)
|
||||||
module.AddProperties(&module.dexpreoptProperties)
|
module.AddProperties(&module.dexpreoptProperties)
|
||||||
|
module.AddProperties(&module.usesLibrary.usesLibraryProperties)
|
||||||
|
|
||||||
InitJavaModule(module, android.DeviceSupported)
|
InitJavaModule(module, android.DeviceSupported)
|
||||||
android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk)
|
android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk)
|
||||||
|
|
||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UsesLibraryProperties struct {
|
||||||
|
// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file.
|
||||||
|
Uses_libs []string
|
||||||
|
|
||||||
|
// A list of shared library modules that will be listed in uses-library tags in the AndroidManifest.xml file with
|
||||||
|
// required=false.
|
||||||
|
Optional_uses_libs []string
|
||||||
|
|
||||||
|
// If true, the list of uses_libs and optional_uses_libs modules must match the AndroidManifest.xml file. Defaults
|
||||||
|
// to true if either uses_libs or optional_uses_libs is set. Will unconditionally default to true in the future.
|
||||||
|
Enforce_uses_libs *bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// usesLibrary provides properties and helper functions for AndroidApp and AndroidAppImport to verify that the
|
||||||
|
// <uses-library> tags that end up in the manifest of an APK match the ones known to the build system through the
|
||||||
|
// uses_libs and optional_uses_libs properties. The build system's values are used by dexpreopt to preopt apps
|
||||||
|
// with knowledge of their shared libraries.
|
||||||
|
type usesLibrary struct {
|
||||||
|
usesLibraryProperties UsesLibraryProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, noFrameworkLibs bool) {
|
||||||
|
ctx.AddVariationDependencies(nil, usesLibTag, u.usesLibraryProperties.Uses_libs...)
|
||||||
|
ctx.AddVariationDependencies(nil, usesLibTag, u.presentOptionalUsesLibs(ctx)...)
|
||||||
|
if !noFrameworkLibs {
|
||||||
|
// dexpreopt/dexpreopt.go needs the paths to the dex jars of these libraries in case construct_context.sh needs
|
||||||
|
// to pass them to dex2oat. Add them as a dependency so we can determine the path to the dex jar of each
|
||||||
|
// library to dexpreopt.
|
||||||
|
ctx.AddVariationDependencies(nil, usesLibTag,
|
||||||
|
"org.apache.http.legacy",
|
||||||
|
"android.hidl.base-V1.0-java",
|
||||||
|
"android.hidl.manager-V1.0-java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// presentOptionalUsesLibs returns optional_uses_libs after filtering out MissingUsesLibraries, which don't exist in the
|
||||||
|
// build.
|
||||||
|
func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []string {
|
||||||
|
optionalUsesLibs, _ := android.FilterList(u.usesLibraryProperties.Optional_uses_libs, ctx.Config().MissingUsesLibraries())
|
||||||
|
return optionalUsesLibs
|
||||||
|
}
|
||||||
|
|
||||||
|
// usesLibraryPaths returns a map of module names of shared library dependencies to the paths to their dex jars.
|
||||||
|
func (u *usesLibrary) usesLibraryPaths(ctx android.ModuleContext) map[string]android.Path {
|
||||||
|
usesLibPaths := make(map[string]android.Path)
|
||||||
|
|
||||||
|
if !ctx.Config().UnbundledBuild() {
|
||||||
|
ctx.VisitDirectDepsWithTag(usesLibTag, func(m android.Module) {
|
||||||
|
if lib, ok := m.(Dependency); ok {
|
||||||
|
if dexJar := lib.DexJar(); dexJar != nil {
|
||||||
|
usesLibPaths[ctx.OtherModuleName(m)] = dexJar
|
||||||
|
} else {
|
||||||
|
ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must produce a dex jar, does it have installable: true?",
|
||||||
|
ctx.OtherModuleName(m))
|
||||||
|
}
|
||||||
|
} else if ctx.Config().AllowMissingDependencies() {
|
||||||
|
ctx.AddMissingDependencies([]string{ctx.OtherModuleName(m)})
|
||||||
|
} else {
|
||||||
|
ctx.ModuleErrorf("module %q in uses_libs or optional_uses_libs must be a java library",
|
||||||
|
ctx.OtherModuleName(m))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return usesLibPaths
|
||||||
|
}
|
||||||
|
|
||||||
|
// enforceUsesLibraries returns true of <uses-library> tags should be checked against uses_libs and optional_uses_libs
|
||||||
|
// properties. Defaults to true if either of uses_libs or optional_uses_libs is specified. Will default to true
|
||||||
|
// unconditionally in the future.
|
||||||
|
func (u *usesLibrary) enforceUsesLibraries() bool {
|
||||||
|
defaultEnforceUsesLibs := len(u.usesLibraryProperties.Uses_libs) > 0 ||
|
||||||
|
len(u.usesLibraryProperties.Optional_uses_libs) > 0
|
||||||
|
return BoolDefault(u.usesLibraryProperties.Enforce_uses_libs, defaultEnforceUsesLibs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyUsesLibrariesManifest checks the <uses-library> tags in an AndroidManifest.xml against the ones specified
|
||||||
|
// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the manifest.
|
||||||
|
func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, manifest android.Path) android.Path {
|
||||||
|
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
|
||||||
|
|
||||||
|
rule := android.NewRuleBuilder()
|
||||||
|
cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")).
|
||||||
|
Flag("--enforce-uses-libraries").
|
||||||
|
Input(manifest).
|
||||||
|
FlagWithOutput("-o ", outputFile)
|
||||||
|
|
||||||
|
for _, lib := range u.usesLibraryProperties.Uses_libs {
|
||||||
|
cmd.FlagWithArg("--uses-library ", lib)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, lib := range u.usesLibraryProperties.Optional_uses_libs {
|
||||||
|
cmd.FlagWithArg("--optional-uses-library ", lib)
|
||||||
|
}
|
||||||
|
|
||||||
|
rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
|
||||||
|
|
||||||
|
return outputFile
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyUsesLibrariesAPK checks the <uses-library> tags in the manifest of an APK against the ones specified
|
||||||
|
// in the uses_libs and optional_uses_libs properties. It returns the path to a copy of the APK.
|
||||||
|
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) android.Path {
|
||||||
|
outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
|
||||||
|
|
||||||
|
rule := android.NewRuleBuilder()
|
||||||
|
aapt := ctx.Config().HostToolPath(ctx, "aapt")
|
||||||
|
rule.Command().
|
||||||
|
Textf("aapt_binary=%s", aapt.String()).Implicit(aapt).
|
||||||
|
Textf(`uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Uses_libs, " ")).
|
||||||
|
Textf(`optional_uses_library_names="%s"`, strings.Join(u.usesLibraryProperties.Optional_uses_libs, " ")).
|
||||||
|
Tool(android.PathForSource(ctx, "build/make/core/verify_uses_libraries.sh")).Input(apk)
|
||||||
|
rule.Command().Text("cp -f").Input(apk).Output(outputFile)
|
||||||
|
|
||||||
|
rule.Build(pctx, ctx, "verify_uses_libraries", "verify <uses-library>")
|
||||||
|
|
||||||
|
return outputFile
|
||||||
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ var combineApk = pctx.AndroidStaticRule("combineApk",
|
||||||
})
|
})
|
||||||
|
|
||||||
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
|
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
|
||||||
packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate) {
|
packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths) {
|
||||||
|
|
||||||
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
|
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
|
||||||
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
|
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
|
||||||
|
@ -81,6 +81,7 @@ func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.Writa
|
||||||
Rule: combineApk,
|
Rule: combineApk,
|
||||||
Inputs: inputs,
|
Inputs: inputs,
|
||||||
Output: unsignedApk,
|
Output: unsignedApk,
|
||||||
|
Implicits: deps,
|
||||||
})
|
})
|
||||||
|
|
||||||
SignAppPackage(ctx, outputFile, unsignedApk, certificates)
|
SignAppPackage(ctx, outputFile, unsignedApk, certificates)
|
||||||
|
|
|
@ -1239,3 +1239,83 @@ func TestStl(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUsesLibraries(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
java_sdk_library {
|
||||||
|
name: "foo",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
api_packages: ["foo"],
|
||||||
|
}
|
||||||
|
|
||||||
|
java_sdk_library {
|
||||||
|
name: "bar",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
api_packages: ["bar"],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_app {
|
||||||
|
name: "app",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
uses_libs: ["foo"],
|
||||||
|
optional_uses_libs: [
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
android_app_import {
|
||||||
|
name: "prebuilt",
|
||||||
|
apk: "prebuilts/apk/app.apk",
|
||||||
|
certificate: "platform",
|
||||||
|
uses_libs: ["foo"],
|
||||||
|
optional_uses_libs: [
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
config := testConfig(nil)
|
||||||
|
config.TestProductVariables.MissingUsesLibraries = []string{"baz"}
|
||||||
|
|
||||||
|
ctx := testAppContext(config, bp, nil)
|
||||||
|
|
||||||
|
run(t, ctx, config)
|
||||||
|
|
||||||
|
app := ctx.ModuleForTests("app", "android_common")
|
||||||
|
prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
|
||||||
|
|
||||||
|
// Test that all libraries are verified
|
||||||
|
cmd := app.Rule("verify_uses_libraries").RuleParams.Command
|
||||||
|
if w := "--uses-library foo"; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
|
||||||
|
|
||||||
|
if w := `uses_library_names="foo"`; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test that only present libraries are preopted
|
||||||
|
cmd = app.Rule("dexpreopt").RuleParams.Command
|
||||||
|
|
||||||
|
if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
|
||||||
|
|
||||||
|
if w := `dex_preopt_target_libraries="/system/framework/foo.jar /system/framework/bar.jar"`; !strings.Contains(cmd, w) {
|
||||||
|
t.Errorf("wanted %q in %q", w, cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,12 @@ type dexpreopter struct {
|
||||||
isInstallable bool
|
isInstallable bool
|
||||||
isPresignedPrebuilt bool
|
isPresignedPrebuilt bool
|
||||||
|
|
||||||
|
manifestFile android.Path
|
||||||
|
usesLibs []string
|
||||||
|
optionalUsesLibs []string
|
||||||
|
enforceUsesLibs bool
|
||||||
|
libraryPaths map[string]android.Path
|
||||||
|
|
||||||
builtInstalled string
|
builtInstalled string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +160,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
||||||
DexLocation: dexLocation,
|
DexLocation: dexLocation,
|
||||||
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
BuildPath: android.PathForModuleOut(ctx, "dexpreopt", ctx.ModuleName()+".jar").OutputPath,
|
||||||
DexPath: dexJarFile,
|
DexPath: dexJarFile,
|
||||||
|
ManifestPath: d.manifestFile,
|
||||||
UncompressedDex: d.uncompressedDex,
|
UncompressedDex: d.uncompressedDex,
|
||||||
HasApkLibraries: false,
|
HasApkLibraries: false,
|
||||||
PreoptFlags: nil,
|
PreoptFlags: nil,
|
||||||
|
@ -161,10 +168,10 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo
|
||||||
ProfileClassListing: profileClassListing,
|
ProfileClassListing: profileClassListing,
|
||||||
ProfileIsTextListing: profileIsTextListing,
|
ProfileIsTextListing: profileIsTextListing,
|
||||||
|
|
||||||
EnforceUsesLibraries: false,
|
EnforceUsesLibraries: d.enforceUsesLibs,
|
||||||
OptionalUsesLibraries: nil,
|
PresentOptionalUsesLibraries: d.optionalUsesLibs,
|
||||||
UsesLibraries: nil,
|
UsesLibraries: d.usesLibs,
|
||||||
LibraryPaths: nil,
|
LibraryPaths: d.libraryPaths,
|
||||||
|
|
||||||
Archs: archs,
|
Archs: archs,
|
||||||
DexPreoptImages: images,
|
DexPreoptImages: images,
|
||||||
|
|
|
@ -420,6 +420,7 @@ var (
|
||||||
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
|
proguardRaiseTag = dependencyTag{name: "proguard-raise"}
|
||||||
certificateTag = dependencyTag{name: "certificate"}
|
certificateTag = dependencyTag{name: "certificate"}
|
||||||
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
|
instrumentationForTag = dependencyTag{name: "instrumentation_for"}
|
||||||
|
usesLibTag = dependencyTag{name: "uses-library"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type sdkDep struct {
|
type sdkDep struct {
|
||||||
|
|
|
@ -174,6 +174,8 @@ func testContext(config android.Config, bp string,
|
||||||
|
|
||||||
"build/soong/scripts/jar-wrapper.sh": nil,
|
"build/soong/scripts/jar-wrapper.sh": nil,
|
||||||
|
|
||||||
|
"build/make/core/verify_uses_libraries.sh": nil,
|
||||||
|
|
||||||
"build/make/core/proguard.flags": nil,
|
"build/make/core/proguard.flags": nil,
|
||||||
"build/make/core/proguard_basic_keeps.flags": nil,
|
"build/make/core/proguard_basic_keeps.flags": nil,
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,33 @@ func GatherRequiredDepsForTest() string {
|
||||||
name: "framework-res",
|
name: "framework-res",
|
||||||
no_framework_libs: true,
|
no_framework_libs: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "android.hidl.base-V1.0-java",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
no_standard_libs: true,
|
||||||
|
sdk_version: "core_current",
|
||||||
|
system_modules: "core-platform-api-stubs-system-modules",
|
||||||
|
installable: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "android.hidl.manager-V1.0-java",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
no_standard_libs: true,
|
||||||
|
sdk_version: "core_current",
|
||||||
|
system_modules: "core-platform-api-stubs-system-modules",
|
||||||
|
installable: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "org.apache.http.legacy",
|
||||||
|
srcs: ["a.java"],
|
||||||
|
no_standard_libs: true,
|
||||||
|
sdk_version: "core_current",
|
||||||
|
system_modules: "core-platform-api-stubs-system-modules",
|
||||||
|
installable: true,
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
systemModules := []string{
|
systemModules := []string{
|
||||||
|
|
Loading…
Reference in New Issue