From f9332f1c866ce87b5a8603256cd1a606c4753d5f Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Thu, 1 Feb 2018 00:54:12 +0900 Subject: [PATCH] Support recovery and recovery_available `recovery: true` installs a module to the recovery partition. `recovery_available: true` makes a module to be available to other `recovery:true` or `recovery_available: true` modules. These to are very similar to vendor, vendor_available properties, except for the target partition. Bug: 67916654 Bug: 64960723 Test: m -j, toybox_recovery is installed to the recovery/root/sbin Change-Id: Iaebe0593de16c69fa70de251a61f4d018a251509 --- Android.bp | 2 + android/module.go | 13 +++++ android/paths.go | 3 ++ android/paths_test.go | 5 ++ cc/androidmk.go | 7 ++- cc/binary.go | 5 ++ cc/cc.go | 107 ++++++++++++++++++++++++++++++++++-------- cc/cc_test.go | 2 +- cc/compiler.go | 13 +++++ cc/library.go | 7 ++- cc/linker.go | 17 +++++++ 11 files changed, 157 insertions(+), 24 deletions(-) diff --git a/Android.bp b/Android.bp index cb63d27f2..2daa958de 100644 --- a/Android.bp +++ b/Android.bp @@ -336,6 +336,7 @@ toolchain_library { name: "libatomic", defaults: ["linux_bionic_supported"], vendor_available: true, + recovery_available: true, arch: { arm: { instruction_set: "arm", @@ -347,6 +348,7 @@ toolchain_library { name: "libgcc", defaults: ["linux_bionic_supported"], vendor_available: true, + recovery_available: true, arch: { arm: { instruction_set: "arm", diff --git a/android/module.go b/android/module.go index fba19179d..3316a4441 100644 --- a/android/module.go +++ b/android/module.go @@ -124,6 +124,7 @@ type ModuleContext interface { InstallInData() bool InstallInSanitizerDir() bool + InstallInRecovery() bool RequiredModuleNames() []string @@ -176,6 +177,7 @@ type Module interface { Target() Target InstallInData() bool InstallInSanitizerDir() bool + InstallInRecovery() bool SkipInstall() ExportedToMake() bool @@ -237,6 +239,9 @@ type commonProperties struct { // /system/product if product partition does not exist). Product_specific *bool + // Whether this module is installed to recovery partition + Recovery *bool + // init.rc files to be installed if this module is installed Init_rc []string @@ -560,6 +565,10 @@ func (p *ModuleBase) InstallInSanitizerDir() bool { return false } +func (p *ModuleBase) InstallInRecovery() bool { + return Bool(p.commonProperties.Recovery) +} + func (a *ModuleBase) generateModuleTarget(ctx ModuleContext) { allInstalledFiles := Paths{} allCheckbuildFiles := Paths{} @@ -1008,6 +1017,10 @@ func (a *androidModuleContext) InstallInSanitizerDir() bool { return a.module.InstallInSanitizerDir() } +func (a *androidModuleContext) InstallInRecovery() bool { + return a.module.InstallInRecovery() +} + func (a *androidModuleContext) skipInstall(fullInstallPath OutputPath) bool { if a.module.base().commonProperties.SkipInstall { return true diff --git a/android/paths.go b/android/paths.go index 91dd9a6d2..8cc31826b 100644 --- a/android/paths.go +++ b/android/paths.go @@ -47,6 +47,7 @@ type ModuleInstallPathContext interface { InstallInData() bool InstallInSanitizerDir() bool + InstallInRecovery() bool } var _ ModuleInstallPathContext = ModuleContext(nil) @@ -948,6 +949,8 @@ func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string var partition string if ctx.InstallInData() { partition = "data" + } else if ctx.InstallInRecovery() { + partition = "recovery/root" } else if ctx.SocSpecific() { partition = ctx.DeviceConfig().VendorPath() } else if ctx.DeviceSpecific() { diff --git a/android/paths_test.go b/android/paths_test.go index cd9fbfd54..b3dc9de28 100644 --- a/android/paths_test.go +++ b/android/paths_test.go @@ -201,6 +201,7 @@ type moduleInstallPathContextImpl struct { inData bool inSanitizerDir bool + inRecovery bool } func (moduleInstallPathContextImpl) Fs() pathtools.FileSystem { @@ -221,6 +222,10 @@ func (m moduleInstallPathContextImpl) InstallInSanitizerDir() bool { return m.inSanitizerDir } +func (m moduleInstallPathContextImpl) InstallInRecovery() bool { + return m.inRecovery +} + func TestPathForModuleInstall(t *testing.T) { testConfig := TestConfig("", nil) diff --git a/cc/androidmk.go b/cc/androidmk.go index cdd4a5a39..f417de071 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -24,7 +24,8 @@ import ( ) var ( - vendorSuffix = ".vendor" + vendorSuffix = ".vendor" + recoverySuffix = ".recovery" ) type AndroidMkContext interface { @@ -99,6 +100,8 @@ func (c *Module) AndroidMk() android.AndroidMkData { // .vendor suffix is added only when we will have two variants: core and vendor. // The suffix is not added for vendor-only module. ret.SubName += vendorSuffix + } else if c.inRecovery() && !c.onlyInRecovery() { + ret.SubName += recoverySuffix } return ret @@ -345,7 +348,7 @@ func (c *stubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkDa func (c *llndkStubDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) { ret.Class = "SHARED_LIBRARIES" - ret.SubName = ".vendor" + ret.SubName = vendorSuffix ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { c.libraryDecorator.androidMkWriteExportedFlags(w) diff --git a/cc/binary.go b/cc/binary.go index 9e7b70b26..00fda0649 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -353,6 +353,11 @@ func (binary *binaryDecorator) link(ctx ModuleContext, } func (binary *binaryDecorator) install(ctx ModuleContext, file android.Path) { + // /bin is a symlink to /system/bin. Recovery binaries are all in /sbin. + if ctx.inRecovery() { + binary.baseInstaller.dir = "sbin" + } + binary.baseInstaller.install(ctx, file) for _, symlink := range binary.Properties.Symlinks { binary.symlinks = append(binary.symlinks, diff --git a/cc/cc.go b/cc/cc.go index 9c3de097c..a885c91b2 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -34,7 +34,7 @@ func init() { android.RegisterModuleType("cc_defaults", defaultsFactory) android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("image", vendorMutator).Parallel() + ctx.BottomUp("image", imageMutator).Parallel() ctx.BottomUp("link", linkageMutator).Parallel() ctx.BottomUp("vndk", vndkMutator).Parallel() ctx.BottomUp("ndk_api", ndkApiMutator).Parallel() @@ -175,6 +175,11 @@ type BaseProperties struct { // *.logtags files, to combine together in order to generate the /system/etc/event-log-tags // file Logtags []string + + // Make this module available when building for recovery + Recovery_available *bool + + InRecovery bool `blueprint:"mutated"` } type VendorProperties struct { @@ -217,6 +222,7 @@ type ModuleContextIntf interface { isVndk() bool isVndkSp() bool isVndkExt() bool + inRecovery() bool createVndkSourceAbiDump() bool selectedStl() string baseModuleName() string @@ -453,6 +459,14 @@ func (c *Module) hasVendorVariant() bool { return c.isVndk() || Bool(c.VendorProperties.Vendor_available) } +func (c *Module) inRecovery() bool { + return c.Properties.InRecovery || c.ModuleBase.InstallInRecovery() +} + +func (c *Module) onlyInRecovery() bool { + return c.ModuleBase.InstallInRecovery() +} + type baseModuleContext struct { android.BaseContext moduleContextImpl @@ -500,7 +514,7 @@ func (ctx *moduleContextImpl) staticBinary() bool { } func (ctx *moduleContextImpl) useSdk() bool { - if ctx.ctx.Device() && !ctx.useVndk() { + if ctx.ctx.Device() && !ctx.useVndk() && !ctx.inRecovery() { return String(ctx.mod.Properties.Sdk_version) != "" } return false @@ -544,6 +558,10 @@ func (ctx *moduleContextImpl) isVndkExt() bool { return ctx.mod.isVndkExt() } +func (ctx *moduleContextImpl) inRecovery() bool { + return ctx.mod.inRecovery() +} + // Create source abi dumps if the module belongs to the list of VndkLibraries. func (ctx *moduleContextImpl) createVndkSourceAbiDump() bool { skipAbiChecks := ctx.ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") @@ -1069,6 +1087,10 @@ func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag depe // Platform code can link to anything return } + if from.inRecovery() { + // Recovery code is not NDK + return + } if _, ok := to.linker.(*toolchainLibraryDecorator); ok { // These are always allowed return @@ -1360,6 +1382,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return libName + vendorSuffix } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib { return libName + vendorPublicLibrarySuffix + } else if ccDep.inRecovery() && !ccDep.onlyInRecovery() { + return libName + recoverySuffix } else { return libName } @@ -1411,6 +1435,10 @@ func (c *Module) InstallInSanitizerDir() bool { return c.installer.inSanitizerDir() } +func (c *Module) InstallInRecovery() bool { + return c.inRecovery() +} + func (c *Module) HostToolPath() android.OptionalPath { if c.installer == nil { return android.OptionalPath{} @@ -1496,6 +1524,8 @@ const ( // vendorMode is the variant used for /vendor code that compiles // against the VNDK. vendorMode = "vendor" + + recoveryMode = "recovery" ) func squashVendorSrcs(m *Module) { @@ -1508,7 +1538,17 @@ func squashVendorSrcs(m *Module) { } } -func vendorMutator(mctx android.BottomUpMutatorContext) { +func squashRecoverySrcs(m *Module) { + if lib, ok := m.compiler.(*libraryDecorator); ok { + lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs, + lib.baseCompiler.Properties.Target.Recovery.Srcs...) + + lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs, + lib.baseCompiler.Properties.Target.Recovery.Exclude_srcs...) + } +} + +func imageMutator(mctx android.BottomUpMutatorContext) { if mctx.Os() != android.Android { return } @@ -1577,43 +1617,70 @@ func vendorMutator(mctx android.BottomUpMutatorContext) { } } + var coreVariantNeeded bool = false + var vendorVariantNeeded bool = false + var recoveryVariantNeeded bool = false + if mctx.DeviceConfig().VndkVersion() == "" { // If the device isn't compiling against the VNDK, we always // use the core mode. - mctx.CreateVariations(coreMode) + coreVariantNeeded = true } else if _, ok := m.linker.(*llndkStubDecorator); ok { // LL-NDK stubs only exist in the vendor variant, since the // real libraries will be used in the core variant. - mctx.CreateVariations(vendorMode) + vendorVariantNeeded = true } else if _, ok := m.linker.(*llndkHeadersDecorator); ok { // ... and LL-NDK headers as well - mod := mctx.CreateVariations(vendorMode) - vendor := mod[0].(*Module) - vendor.Properties.UseVndk = true + vendorVariantNeeded = true } else if _, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { // Make vendor variants only for the versions in BOARD_VNDK_VERSION and // PRODUCT_EXTRA_VNDK_VERSIONS. - mod := mctx.CreateVariations(vendorMode) - vendor := mod[0].(*Module) - vendor.Properties.UseVndk = true + vendorVariantNeeded = true } else if m.hasVendorVariant() && !vendorSpecific { // This will be available in both /system and /vendor // or a /system directory that is available to vendor. - mod := mctx.CreateVariations(coreMode, vendorMode) - vendor := mod[1].(*Module) - vendor.Properties.UseVndk = true - squashVendorSrcs(vendor) + coreVariantNeeded = true + vendorVariantNeeded = true } else if vendorSpecific && String(m.Properties.Sdk_version) == "" { // This will be available in /vendor (or /odm) only - mod := mctx.CreateVariations(vendorMode) - vendor := mod[0].(*Module) - vendor.Properties.UseVndk = true - squashVendorSrcs(vendor) + vendorVariantNeeded = true } else { // This is either in /system (or similar: /data), or is a // modules built with the NDK. Modules built with the NDK // will be restricted using the existing link type checks. - mctx.CreateVariations(coreMode) + coreVariantNeeded = true + } + + if Bool(m.Properties.Recovery_available) { + recoveryVariantNeeded = true + } + + if m.ModuleBase.InstallInRecovery() { + recoveryVariantNeeded = true + coreVariantNeeded = false + } + + var variants []string + if coreVariantNeeded { + variants = append(variants, coreMode) + } + if vendorVariantNeeded { + variants = append(variants, vendorMode) + } + if recoveryVariantNeeded { + variants = append(variants, recoveryMode) + } + mod := mctx.CreateVariations(variants...) + for i, v := range variants { + if v == vendorMode { + m := mod[i].(*Module) + m.Properties.UseVndk = true + squashVendorSrcs(m) + } else if v == recoveryMode { + m := mod[i].(*Module) + m.Properties.InRecovery = true + squashRecoverySrcs(m) + } } } diff --git a/cc/cc_test.go b/cc/cc_test.go index 4f26827e6..1b12ad470 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -63,7 +63,7 @@ func createTestContext(t *testing.T, config android.Config, bp string) *android. ctx.RegisterModuleType("cc_object", android.ModuleFactoryAdaptor(objectFactory)) ctx.RegisterModuleType("filegroup", android.ModuleFactoryAdaptor(android.FileGroupFactory)) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("image", vendorMutator).Parallel() + ctx.BottomUp("image", imageMutator).Parallel() ctx.BottomUp("link", linkageMutator).Parallel() ctx.BottomUp("vndk", vndkMutator).Parallel() ctx.BottomUp("begin", beginMutator).Parallel() diff --git a/cc/compiler.go b/cc/compiler.go index 2ba19f1b7..b410115f8 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -142,6 +142,19 @@ type BaseCompilerProperties struct { // variant of the C/C++ module. Cflags []string } + Recovery struct { + // list of source files that should only be used in the + // recovery variant of the C/C++ module. + Srcs []string + + // list of source files that should not be used to + // build the recovery variant of the C/C++ module. + Exclude_srcs []string + + // List of additional cflags that should be used to build the recovery + // variant of the C/C++ module. + Cflags []string + } } Proto struct { diff --git a/cc/library.go b/cc/library.go index b31fee2d0..c83e89a31 100644 --- a/cc/library.go +++ b/cc/library.go @@ -477,6 +477,11 @@ func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Vendor.Exclude_shared_libs) deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Vendor.Exclude_static_libs) } + if ctx.inRecovery() { + deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs) + deps.SharedLibs = removeListFromList(deps.SharedLibs, library.baseLinker.Properties.Target.Recovery.Exclude_shared_libs) + deps.StaticLibs = removeListFromList(deps.StaticLibs, library.baseLinker.Properties.Target.Recovery.Exclude_static_libs) + } android.ExtractSourceDeps(ctx, library.Properties.Version_script) android.ExtractSourceDeps(ctx, library.Properties.Unexported_symbols_list) @@ -745,7 +750,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { } if Bool(library.Properties.Static_ndk_lib) && library.static() && - !ctx.useVndk() && ctx.Device() && + !ctx.useVndk() && !ctx.inRecovery() && ctx.Device() && library.sanitize.isUnsanitizedVariant() { installPath := getNdkSysrootBase(ctx).Join( ctx, "usr/lib", config.NDKTriple(ctx.toolchain()), file.Base()) diff --git a/cc/linker.go b/cc/linker.go index 71da09e7a..3e2ecc66f 100644 --- a/cc/linker.go +++ b/cc/linker.go @@ -107,6 +107,15 @@ type BaseLinkerProperties struct { // variant of the C/C++ module. Exclude_runtime_libs []string } + Recovery struct { + // list of shared libs that should not be used to build + // the recovery variant of the C/C++ module. + Exclude_shared_libs []string + + // list of static libs that should not be used to build + // the recovery variant of the C/C++ module. + Exclude_static_libs []string + } } // make android::build:GetBuildNumber() available containing the build ID. @@ -166,6 +175,14 @@ func (linker *baseLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { deps.RuntimeLibs = removeListFromList(deps.RuntimeLibs, linker.Properties.Target.Vendor.Exclude_runtime_libs) } + if ctx.inRecovery() { + deps.SharedLibs = removeListFromList(deps.SharedLibs, linker.Properties.Target.Recovery.Exclude_shared_libs) + deps.ReexportSharedLibHeaders = removeListFromList(deps.ReexportSharedLibHeaders, linker.Properties.Target.Recovery.Exclude_shared_libs) + deps.StaticLibs = removeListFromList(deps.StaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs) + deps.ReexportStaticLibHeaders = removeListFromList(deps.ReexportStaticLibHeaders, linker.Properties.Target.Recovery.Exclude_static_libs) + deps.WholeStaticLibs = removeListFromList(deps.WholeStaticLibs, linker.Properties.Target.Recovery.Exclude_static_libs) + } + if ctx.ModuleName() != "libcompiler_rt-extras" { deps.LateStaticLibs = append(deps.LateStaticLibs, "libcompiler_rt-extras") }