Merge "manifest_check.py: trim namespace part of the module, if needed."
diff --git a/android/bazel.go b/android/bazel.go
index 46212dc..d40e650 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -140,6 +140,7 @@
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
+ "packages/apps/Music":/* recursive = */ false,
}
// Configure modules in these directories to enable bp2build_available: true or false by default.
diff --git a/android/module.go b/android/module.go
index 11f63bd..b40310b 100644
--- a/android/module.go
+++ b/android/module.go
@@ -413,6 +413,7 @@
InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
+ InstallInVendor() bool
InstallBypassMake() bool
InstallForceOS() (*OsType, *ArchType)
@@ -471,6 +472,7 @@
InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
+ InstallInVendor() bool
InstallBypassMake() bool
InstallForceOS() (*OsType, *ArchType)
HideFromMake()
@@ -1579,6 +1581,10 @@
return Bool(m.commonProperties.Recovery)
}
+func (m *ModuleBase) InstallInVendor() bool {
+ return Bool(m.commonProperties.Vendor)
+}
+
func (m *ModuleBase) InstallInRoot() bool {
return false
}
@@ -2645,6 +2651,10 @@
return m.module.InstallForceOS()
}
+func (m *moduleContext) InstallInVendor() bool {
+ return m.module.InstallInVendor()
+}
+
func (m *moduleContext) skipInstall() bool {
if m.module.base().commonProperties.SkipInstall {
return true
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 422e46c..d6c7142 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4667,6 +4667,13 @@
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
contents: ["core-oj"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -4890,7 +4897,7 @@
}
}
- checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
+ checkHiddenAPIIndexFromClassesInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
t.Helper()
platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
var rule android.TestingBuildParams
@@ -4899,6 +4906,15 @@
java.CheckHiddenAPIRuleInputs(t, "intermediate index", expectedIntermediateInputs, rule)
}
+ checkHiddenAPIIndexFromFlagsInputs := func(t *testing.T, ctx *android.TestContext, expectedIntermediateInputs string) {
+ t.Helper()
+ platformBootclasspath := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ var rule android.TestingBuildParams
+
+ rule = platformBootclasspath.Output("hiddenapi-index.csv")
+ java.CheckHiddenAPIRuleInputs(t, "monolithic index", expectedIntermediateInputs, rule)
+ }
+
fragment := java.ApexVariantReference{
Apex: proptools.StringPtr("myapex"),
Module: proptools.StringPtr("my-bootclasspath-fragment"),
@@ -4923,6 +4939,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -4946,9 +4969,10 @@
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
- checkHiddenAPIIndexInputs(t, ctx, `
- out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
- out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
+ checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
+ checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
+ my-bootclasspath-fragment/index.csv
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
})
@@ -4964,6 +4988,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -4987,9 +5018,10 @@
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
- checkHiddenAPIIndexInputs(t, ctx, `
- out/soong/.intermediates/libbar.stubs/android_common/combined/libbar.stubs.jar
- out/soong/.intermediates/libfoo/android_common_myapex/combined/libfoo.jar
+ checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
+ checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
+ my-bootclasspath-fragment/index.csv
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
})
@@ -5012,6 +5044,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -5070,6 +5109,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -5108,9 +5154,10 @@
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
- checkHiddenAPIIndexInputs(t, ctx, `
- out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
- out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
+ checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
+ checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
+ my-bootclasspath-fragment/index.csv
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
})
@@ -5146,6 +5193,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -5182,9 +5236,10 @@
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
- checkHiddenAPIIndexInputs(t, ctx, `
- out/soong/.intermediates/libbar/android_common_myapex/javac/libbar.jar
- out/soong/.intermediates/libfoo/android_common_apex10000/javac/libfoo.jar
+ checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
+ checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
+ my-bootclasspath-fragment/index.csv
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
})
@@ -5220,6 +5275,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo", "libbar"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
@@ -5258,9 +5320,10 @@
checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
- checkHiddenAPIIndexInputs(t, ctx, `
- out/soong/.intermediates/prebuilt_libbar.stubs/android_common/combined/libbar.stubs.jar
- out/soong/.intermediates/prebuilt_libfoo/android_common_myapex/combined/libfoo.jar
+ checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
+ checkHiddenAPIIndexFromFlagsInputs(t, ctx, `
+ my-bootclasspath-fragment/index.csv
+ out/soong/.intermediates/frameworks/base/boot/platform-bootclasspath/android_common/hiddenapi-monolithic/index-from-classes.csv
`)
})
}
@@ -7183,6 +7246,13 @@
name: "my-bootclasspath-fragment",
contents: ["libfoo"],
apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
}
java_import {
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 4b1600e..5cd3eab 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -383,6 +383,13 @@
apex_available: [
"com.android.art",
],
+ hidden_api: {
+ annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
+ metadata: "mybootclasspathfragment/metadata.csv",
+ index: "mybootclasspathfragment/index.csv",
+ stub_flags: "mybootclasspathfragment/stub-flags.csv",
+ all_flags: "mybootclasspathfragment/all-flags.csv",
+ },
}
`, contentsInsert(contents), prefer)
return android.FixtureAddTextFile("prebuilts/module_sdk/art/Android.bp", text)
@@ -582,6 +589,13 @@
apex_available: [
"com.android.art",
],
+ hidden_api: {
+ annotation_flags: "mybootclasspathfragment/annotation-flags.csv",
+ metadata: "mybootclasspathfragment/metadata.csv",
+ index: "mybootclasspathfragment/index.csv",
+ stub_flags: "mybootclasspathfragment/stub-flags.csv",
+ all_flags: "mybootclasspathfragment/all-flags.csv",
+ },
}
`)
diff --git a/apex/builder.go b/apex/builder.go
index 24c049b..148f42f 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -761,7 +761,7 @@
rule := java.Signapk
args := map[string]string{
"certificates": pem.String() + " " + key.String(),
- "flags": "-a 4096", //alignment
+ "flags": "-a 4096 --align-file-size", //alignment
}
implicits := android.Paths{pem, key}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_SIGNAPK") {
diff --git a/cc/Android.bp b/cc/Android.bp
index 4b750ff..164d32b 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -14,6 +14,7 @@
"soong-cc-config",
"soong-etc",
"soong-genrule",
+ "soong-snapshot",
"soong-tradefed",
],
srcs: [
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 536f112..484e922 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -72,36 +72,34 @@
allDeps = append(allDeps, baseLinkerProps.Whole_static_libs...)
allDeps = append(allDeps, baseLinkerProps.Shared_libs...)
allDeps = append(allDeps, baseLinkerProps.Exclude_shared_libs...)
+ allDeps = append(allDeps, baseLinkerProps.System_shared_libs...)
}
}
}
// Deps in the static: { .. } and shared: { .. } props of a cc_library.
if lib, ok := module.compiler.(*libraryDecorator); ok {
- appendDeps := func(deps []string, p StaticOrSharedProperties) []string {
+ appendDeps := func(deps []string, p StaticOrSharedProperties, system bool) []string {
deps = append(deps, p.Static_libs...)
deps = append(deps, p.Whole_static_libs...)
deps = append(deps, p.Shared_libs...)
+ // TODO(b/186024507, b/186489250): Temporarily exclude adding
+ // system_shared_libs deps until libc and libm builds.
+ if system {
+ allDeps = append(allDeps, p.System_shared_libs...)
+ }
return deps
}
- allDeps = appendDeps(allDeps, lib.SharedProperties.Shared)
- allDeps = appendDeps(allDeps, lib.StaticProperties.Static)
-
- // TODO(b/186024507, b/186489250): Temporarily exclude adding
- // system_shared_libs deps until libc and libm builds.
- if lib.static() {
- allDeps = append(allDeps, lib.StaticProperties.Static.System_shared_libs...)
- } else if lib.shared() {
- allDeps = append(allDeps, lib.SharedProperties.Shared.System_shared_libs...)
- }
+ allDeps = appendDeps(allDeps, lib.SharedProperties.Shared, lib.shared())
+ allDeps = appendDeps(allDeps, lib.StaticProperties.Static, lib.static())
// Deps in the target/arch nested static: { .. } and shared: { .. } props of a cc_library.
// target: { <target>: shared: { ... } }
for _, configToProps := range module.GetArchVariantProperties(ctx, &SharedProperties{}) {
for _, props := range configToProps {
if p, ok := props.(*SharedProperties); ok {
- allDeps = appendDeps(allDeps, p.Shared)
+ allDeps = appendDeps(allDeps, p.Shared, lib.shared())
}
}
}
@@ -109,7 +107,7 @@
for _, configToProps := range module.GetArchVariantProperties(ctx, &StaticProperties{}) {
for _, props := range configToProps {
if p, ok := props.(*StaticProperties); ok {
- allDeps = appendDeps(allDeps, p.Static)
+ allDeps = appendDeps(allDeps, p.Static, lib.static())
}
}
}
diff --git a/cc/builder.go b/cc/builder.go
index b0842ec..842ce85 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -237,7 +237,7 @@
// -w has been added since header-abi-dumper does not need to produce any sort of diagnostic information.
sAbiDump, sAbiDumpRE = pctx.RemoteStaticRules("sAbiDump",
blueprint.RuleParams{
- Command: "rm -f $out && $reTemplate$sAbiDumper -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
+ Command: "rm -f $out && $reTemplate$sAbiDumper --root-dir . --root-dir $$OUT_DIR:out -o ${out} $in $exportDirs -- $cFlags -w -isystem prebuilts/clang-tools/${config.HostPrebuiltTag}/clang-headers",
CommandDeps: []string{"$sAbiDumper"},
}, &remoteexec.REParams{
Labels: map[string]string{"type": "abi-dump", "tool": "header-abi-dumper"},
@@ -255,7 +255,7 @@
// sAbi dump file.
sAbiLink, sAbiLinkRE = pctx.RemoteStaticRules("sAbiLink",
blueprint.RuleParams{
- Command: "$reTemplate$sAbiLinker -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp ",
+ Command: "$reTemplate$sAbiLinker --root-dir . --root-dir $$OUT_DIR:out -o ${out} $symbolFilter -arch $arch $exportedHeaderFlags @${out}.rsp",
CommandDeps: []string{"$sAbiLinker"},
Rspfile: "${out}.rsp",
RspfileContent: "${in}",
diff --git a/cc/genrule.go b/cc/genrule.go
index b0efc6c..0ca901e 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"android/soong/genrule"
+ "android/soong/snapshot"
)
func init() {
@@ -84,7 +85,7 @@
// is not needed.
recoverySnapshotVersion := ctx.DeviceConfig().RecoverySnapshotVersion()
if recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" &&
- !isRecoveryProprietaryModule(ctx) {
+ !snapshot.IsRecoveryProprietaryModule(ctx) {
return false
} else {
return Bool(g.Recovery_available)
@@ -103,7 +104,7 @@
// If not, we assume modules under proprietary paths are compatible for
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
// PLATFORM_VNDK_VERSION.
- if vndkVersion == "current" || !IsVendorProprietaryModule(ctx) {
+ if vndkVersion == "current" || !snapshot.IsVendorProprietaryModule(ctx) {
variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
} else {
variants = append(variants, VendorVariationPrefix+vndkVersion)
diff --git a/cc/image.go b/cc/image.go
index 15ec1c8..3a0857b 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/android"
+ "android/soong/snapshot"
)
var _ android.ImageInterface = (*Module)(nil)
@@ -496,7 +497,7 @@
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
// PLATFORM_VNDK_VERSION.
if m.HasVendorVariant() {
- if IsVendorProprietaryModule(mctx) {
+ if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, platformVndkVersion)
@@ -525,7 +526,7 @@
platformVndkVersion,
boardVndkVersion,
)
- } else if IsVendorProprietaryModule(mctx) {
+ } else if snapshot.IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, platformVndkVersion)
@@ -582,7 +583,7 @@
if !m.KernelHeadersDecorator() &&
!m.IsSnapshotPrebuilt() &&
usingRecoverySnapshot &&
- !isRecoveryProprietaryModule(mctx) {
+ !snapshot.IsRecoveryProprietaryModule(mctx) {
recoveryVariantNeeded = false
}
diff --git a/cc/linkable.go b/cc/linkable.go
index 6232efb..b510508 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -3,6 +3,7 @@
import (
"android/soong/android"
"android/soong/bazel/cquery"
+ "android/soong/snapshot"
"github.com/google/blueprint"
)
@@ -71,15 +72,12 @@
// Snapshottable defines those functions necessary for handling module snapshots.
type Snapshottable interface {
+ snapshot.VendorSnapshotModuleInterface
+ snapshot.RecoverySnapshotModuleInterface
+
// SnapshotHeaders returns a list of header paths provided by this module.
SnapshotHeaders() android.Paths
- // ExcludeFromVendorSnapshot returns true if this module should be otherwise excluded from the vendor snapshot.
- ExcludeFromVendorSnapshot() bool
-
- // ExcludeFromRecoverySnapshot returns true if this module should be otherwise excluded from the recovery snapshot.
- ExcludeFromRecoverySnapshot() bool
-
// SnapshotLibrary returns true if this module is a snapshot library.
IsSnapshotLibrary() bool
diff --git a/cc/sanitize.go b/cc/sanitize.go
index defe8fd..3863c3a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -25,6 +25,7 @@
"android/soong/android"
"android/soong/cc/config"
+ "android/soong/snapshot"
)
var (
@@ -907,7 +908,7 @@
// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
// except for ones which explicitly disable cfi.
func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
- if IsVendorProprietaryModule(mctx) {
+ if snapshot.IsVendorProprietaryModule(mctx) {
return false
}
diff --git a/cc/sdk.go b/cc/sdk.go
index 69ad311..a83e5ad 100644
--- a/cc/sdk.go
+++ b/cc/sdk.go
@@ -76,7 +76,7 @@
}
ctx.AliasVariation("")
}
- case *snapshot:
+ case *snapshotModule:
ctx.CreateVariations("")
}
}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 4f031ff..9672c0f 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -18,57 +18,17 @@
// snapshot mutators and snapshot information maps which are also defined in this file.
import (
- "path/filepath"
"strings"
"android/soong/android"
+ "android/soong/snapshot"
"github.com/google/blueprint"
)
-// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
-// vendor, recovery, ramdisk.
+// This interface overrides snapshot.SnapshotImage to implement cc module specific functions
type SnapshotImage interface {
- // Returns true if a snapshot should be generated for this image.
- shouldGenerateSnapshot(ctx android.SingletonContext) bool
-
- // Function that returns true if the module is included in this image.
- // Using a function return instead of a value to prevent early
- // evalution of a function that may be not be defined.
- inImage(m LinkableInterface) func() bool
-
- // Returns true if the module is private and must not be included in the
- // snapshot. For example VNDK-private modules must return true for the
- // vendor snapshots. But false for the recovery snapshots.
- private(m LinkableInterface) bool
-
- // Returns true if a dir under source tree is an SoC-owned proprietary
- // directory, such as device/, vendor/, etc.
- //
- // For a given snapshot (e.g., vendor, recovery, etc.) if
- // isProprietaryPath(dir, deviceConfig) returns true, then the module in dir
- // will be built from sources.
- isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool
-
- // Whether to include VNDK in the snapshot for this image.
- includeVndk() bool
-
- // Whether a given module has been explicitly excluded from the
- // snapshot, e.g., using the exclude_from_vendor_snapshot or
- // exclude_from_recovery_snapshot properties.
- excludeFromSnapshot(m LinkableInterface) bool
-
- // Returns true if the build is using a snapshot for this image.
- isUsingSnapshot(cfg android.DeviceConfig) bool
-
- // Returns a version of which the snapshot should be used in this target.
- // This will only be meaningful when isUsingSnapshot is true.
- targetSnapshotVersion(cfg android.DeviceConfig) string
-
- // Whether to exclude a given module from the directed snapshot or not.
- // If the makefile variable DIRECTED_{IMAGE}_SNAPSHOT is true, directed snapshot is turned on,
- // and only modules listed in {IMAGE}_SNAPSHOT_MODULES will be captured.
- excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool
+ snapshot.SnapshotImage
// The image variant name for this snapshot image.
// For example, recovery snapshot image will return "recovery", and vendor snapshot image will
@@ -80,110 +40,12 @@
moduleNameSuffix() string
}
-type vendorSnapshotImage struct{}
-type recoverySnapshotImage struct{}
-
-type directoryMap map[string]bool
-
-var (
- // Modules under following directories are ignored. They are OEM's and vendor's
- // proprietary modules(device/, kernel/, vendor/, and hardware/).
- defaultDirectoryExcludedMap = directoryMap{
- "device": true,
- "hardware": true,
- "kernel": true,
- "vendor": true,
- }
-
- // Modules under following directories are included as they are in AOSP,
- // although hardware/ and kernel/ are normally for vendor's own.
- defaultDirectoryIncludedMap = directoryMap{
- "kernel/configs": true,
- "kernel/prebuilts": true,
- "kernel/tests": true,
- "hardware/interfaces": true,
- "hardware/libhardware": true,
- "hardware/libhardware_legacy": true,
- "hardware/ril": true,
- }
-)
-
-func (vendorSnapshotImage) Init(ctx android.RegistrationContext) {
- ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
- ctx.RegisterModuleType("vendor_snapshot", vendorSnapshotFactory)
- ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
- ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
- ctx.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
- ctx.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
- ctx.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
-
- ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
+type vendorSnapshotImage struct {
+ *snapshot.VendorSnapshotImage
}
-func (vendorSnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) {
- ctx.RegisterModuleType(name, factory)
-}
-
-func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
- // BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
- return ctx.DeviceConfig().VndkVersion() == "current"
-}
-
-func (vendorSnapshotImage) inImage(m LinkableInterface) func() bool {
- return m.InVendor
-}
-
-func (vendorSnapshotImage) private(m LinkableInterface) bool {
- return m.IsVndkPrivate()
-}
-
-func isDirectoryExcluded(dir string, excludedMap directoryMap, includedMap directoryMap) bool {
- if dir == "." || dir == "/" {
- return false
- }
- if includedMap[dir] {
- return false
- } else if excludedMap[dir] {
- return true
- } else if defaultDirectoryIncludedMap[dir] {
- return false
- } else if defaultDirectoryExcludedMap[dir] {
- return true
- } else {
- return isDirectoryExcluded(filepath.Dir(dir), excludedMap, includedMap)
- }
-}
-
-func (vendorSnapshotImage) isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
- return isDirectoryExcluded(dir, deviceConfig.VendorSnapshotDirsExcludedMap(), deviceConfig.VendorSnapshotDirsIncludedMap())
-}
-
-// vendor snapshot includes static/header libraries with vndk: {enabled: true}.
-func (vendorSnapshotImage) includeVndk() bool {
- return true
-}
-
-func (vendorSnapshotImage) excludeFromSnapshot(m LinkableInterface) bool {
- return m.ExcludeFromVendorSnapshot()
-}
-
-func (vendorSnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
- vndkVersion := cfg.VndkVersion()
- return vndkVersion != "current" && vndkVersion != ""
-}
-
-func (vendorSnapshotImage) targetSnapshotVersion(cfg android.DeviceConfig) string {
- return cfg.VndkVersion()
-}
-
-// returns true iff a given module SHOULD BE EXCLUDED, false if included
-func (vendorSnapshotImage) excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
- // If we're using full snapshot, not directed snapshot, capture every module
- if !cfg.DirectedVendorSnapshot() {
- return false
- }
- // Else, checks if name is in VENDOR_SNAPSHOT_MODULES.
- return !cfg.VendorSnapshotModules()[name]
+type recoverySnapshotImage struct {
+ *snapshot.RecoverySnapshotImage
}
func (vendorSnapshotImage) imageVariantName(cfg android.DeviceConfig) string {
@@ -194,62 +56,6 @@
return VendorSuffix
}
-func (recoverySnapshotImage) init(ctx android.RegistrationContext) {
- ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
- ctx.RegisterModuleType("recovery_snapshot", recoverySnapshotFactory)
- ctx.RegisterModuleType("recovery_snapshot_shared", RecoverySnapshotSharedFactory)
- ctx.RegisterModuleType("recovery_snapshot_static", RecoverySnapshotStaticFactory)
- ctx.RegisterModuleType("recovery_snapshot_header", RecoverySnapshotHeaderFactory)
- ctx.RegisterModuleType("recovery_snapshot_binary", RecoverySnapshotBinaryFactory)
- ctx.RegisterModuleType("recovery_snapshot_object", RecoverySnapshotObjectFactory)
-}
-
-func (recoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
- // RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
- // snapshot.
- return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
-}
-
-func (recoverySnapshotImage) inImage(m LinkableInterface) func() bool {
- return m.InRecovery
-}
-
-// recovery snapshot does not have private libraries.
-func (recoverySnapshotImage) private(m LinkableInterface) bool {
- return false
-}
-
-func (recoverySnapshotImage) isProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
- return isDirectoryExcluded(dir, deviceConfig.RecoverySnapshotDirsExcludedMap(), deviceConfig.RecoverySnapshotDirsIncludedMap())
-}
-
-// recovery snapshot does NOT treat vndk specially.
-func (recoverySnapshotImage) includeVndk() bool {
- return false
-}
-
-func (recoverySnapshotImage) excludeFromSnapshot(m LinkableInterface) bool {
- return m.ExcludeFromRecoverySnapshot()
-}
-
-func (recoverySnapshotImage) isUsingSnapshot(cfg android.DeviceConfig) bool {
- recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
- return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
-}
-
-func (recoverySnapshotImage) targetSnapshotVersion(cfg android.DeviceConfig) string {
- return cfg.RecoverySnapshotVersion()
-}
-
-func (recoverySnapshotImage) excludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
- // If we're using full snapshot, not directed snapshot, capture every module
- if !cfg.DirectedRecoverySnapshot() {
- return false
- }
- // Else, checks if name is in RECOVERY_SNAPSHOT_MODULES.
- return !cfg.RecoverySnapshotModules()[name]
-}
-
func (recoverySnapshotImage) imageVariantName(cfg android.DeviceConfig) string {
return android.RecoveryVariation
}
@@ -258,12 +64,31 @@
return recoverySuffix
}
-var VendorSnapshotImageSingleton vendorSnapshotImage
-var recoverySnapshotImageSingleton recoverySnapshotImage
+// Override existing vendor and recovery snapshot for cc module specific extra functions
+var VendorSnapshotImageSingleton vendorSnapshotImage = vendorSnapshotImage{&snapshot.VendorSnapshotImageSingleton}
+var recoverySnapshotImageSingleton recoverySnapshotImage = recoverySnapshotImage{&snapshot.RecoverySnapshotImageSingleton}
+
+func RegisterVendorSnapshotModules(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("vendor_snapshot", vendorSnapshotFactory)
+ ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
+ ctx.RegisterModuleType("vendor_snapshot_static", VendorSnapshotStaticFactory)
+ ctx.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
+ ctx.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
+ ctx.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
+}
+
+func RegisterRecoverySnapshotModules(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("recovery_snapshot", recoverySnapshotFactory)
+ ctx.RegisterModuleType("recovery_snapshot_shared", RecoverySnapshotSharedFactory)
+ ctx.RegisterModuleType("recovery_snapshot_static", RecoverySnapshotStaticFactory)
+ ctx.RegisterModuleType("recovery_snapshot_header", RecoverySnapshotHeaderFactory)
+ ctx.RegisterModuleType("recovery_snapshot_binary", RecoverySnapshotBinaryFactory)
+ ctx.RegisterModuleType("recovery_snapshot_object", RecoverySnapshotObjectFactory)
+}
func init() {
- VendorSnapshotImageSingleton.Init(android.InitRegistrationContext)
- recoverySnapshotImageSingleton.init(android.InitRegistrationContext)
+ RegisterVendorSnapshotModules(android.InitRegistrationContext)
+ RegisterRecoverySnapshotModules(android.InitRegistrationContext)
android.RegisterMakeVarsProvider(pctx, snapshotMakeVarsProvider)
}
@@ -285,8 +110,7 @@
Binaries []string `android:"arch_variant"`
Objects []string `android:"arch_variant"`
}
-
-type snapshot struct {
+type snapshotModule struct {
android.ModuleBase
properties SnapshotProperties
@@ -296,41 +120,41 @@
image SnapshotImage
}
-func (s *snapshot) ImageMutatorBegin(ctx android.BaseModuleContext) {
+func (s *snapshotModule) ImageMutatorBegin(ctx android.BaseModuleContext) {
cfg := ctx.DeviceConfig()
- if !s.image.isUsingSnapshot(cfg) || s.image.targetSnapshotVersion(cfg) != s.baseSnapshot.Version() {
+ if !s.image.IsUsingSnapshot(cfg) || s.image.TargetSnapshotVersion(cfg) != s.baseSnapshot.Version() {
s.Disable()
}
}
-func (s *snapshot) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *snapshotModule) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
-func (s *snapshot) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *snapshotModule) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
-func (s *snapshot) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *snapshotModule) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
-func (s *snapshot) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *snapshotModule) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
-func (s *snapshot) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
+func (s *snapshotModule) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool {
return false
}
-func (s *snapshot) ExtraImageVariations(ctx android.BaseModuleContext) []string {
+func (s *snapshotModule) ExtraImageVariations(ctx android.BaseModuleContext) []string {
return []string{s.image.imageVariantName(ctx.DeviceConfig())}
}
-func (s *snapshot) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
+func (s *snapshotModule) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
-func (s *snapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+func (s *snapshotModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Nothing, the snapshot module is only used to forward dependency information in DepsMutator.
}
@@ -342,7 +166,7 @@
return moduleSuffix + versionSuffix
}
-func (s *snapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
+func (s *snapshotModule) DepsMutator(ctx android.BottomUpMutatorContext) {
collectSnapshotMap := func(names []string, snapshotSuffix, moduleSuffix string) map[string]string {
snapshotMap := make(map[string]string)
for _, name := range names {
@@ -382,12 +206,12 @@
var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps")
-var _ android.ImageInterface = (*snapshot)(nil)
+var _ android.ImageInterface = (*snapshotModule)(nil)
func snapshotMakeVarsProvider(ctx android.MakeVarsContext) {
snapshotSet := map[string]struct{}{}
ctx.VisitAllModules(func(m android.Module) {
- if s, ok := m.(*snapshot); ok {
+ if s, ok := m.(*snapshotModule); ok {
if _, ok := snapshotSet[s.Name()]; ok {
// arch variant generates duplicated modules
// skip this as we only need to know the path of the module.
@@ -411,13 +235,13 @@
}
func snapshotFactory(image SnapshotImage) android.Module {
- snapshot := &snapshot{}
- snapshot.image = image
- snapshot.AddProperties(
- &snapshot.properties,
- &snapshot.baseSnapshot.baseProperties)
- android.InitAndroidArchModule(snapshot, android.DeviceSupported, android.MultilibBoth)
- return snapshot
+ snapshotModule := &snapshotModule{}
+ snapshotModule.image = image
+ snapshotModule.AddProperties(
+ &snapshotModule.properties,
+ &snapshotModule.baseSnapshot.baseProperties)
+ android.InitAndroidArchModule(snapshotModule, android.DeviceSupported, android.MultilibBoth)
+ return snapshotModule
}
type BaseSnapshotDecoratorProperties struct {
@@ -449,7 +273,7 @@
// will be seen as "libbase.vendor_static.30.arm64" by Soong.
type BaseSnapshotDecorator struct {
baseProperties BaseSnapshotDecoratorProperties
- image SnapshotImage
+ Image SnapshotImage
}
func (p *BaseSnapshotDecorator) Name(name string) string {
@@ -489,7 +313,7 @@
Variation: android.CoreVariation})
if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
- p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+ p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
@@ -498,14 +322,14 @@
Variation: ProductVariationPrefix + ctx.DeviceConfig().PlatformVndkVersion()})
if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
- p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+ p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
images := []SnapshotImage{VendorSnapshotImageSingleton, recoverySnapshotImageSingleton}
for _, image := range images {
- if p.image == image {
+ if p.Image == image {
continue
}
variations = append(ctx.Target().Variations(), blueprint.Variation{
@@ -518,7 +342,7 @@
image.moduleNameSuffix()+variant,
p.Version(),
ctx.DeviceConfig().Arches()[0].ArchType.String())) {
- p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+ p.baseProperties.Androidmk_suffix = p.Image.moduleNameSuffix()
return
}
}
@@ -529,7 +353,7 @@
// Call this with a module suffix after creating a snapshot module, such as
// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
func (p *BaseSnapshotDecorator) Init(m LinkableInterface, image SnapshotImage, moduleSuffix string) {
- p.image = image
+ p.Image = image
p.baseProperties.ModuleSuffix = image.moduleNameSuffix() + moduleSuffix
m.AddProperties(&p.baseProperties)
android.AddLoadHook(m, func(ctx android.LoadHookContext) {
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index b0538be..24abcce 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -114,7 +114,7 @@
}
for _, image := range []SnapshotImage{VendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
- if isSnapshotAware(ctx.DeviceConfig(), m, image.isProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()), apexInfo, image) {
+ if isSnapshotAware(ctx.DeviceConfig(), m, image.IsProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()), apexInfo, image) {
return true
}
}
diff --git a/cc/testing.go b/cc/testing.go
index b9d84f6..6a002c0 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -20,6 +20,7 @@
"android/soong/android"
"android/soong/genrule"
+ "android/soong/snapshot"
)
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@@ -638,8 +639,10 @@
var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
PrepareForIntegrationTestWithCc,
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- VendorSnapshotImageSingleton.Init(ctx)
- recoverySnapshotImageSingleton.init(ctx)
+ snapshot.VendorSnapshotImageSingleton.Init(ctx)
+ snapshot.RecoverySnapshotImageSingleton.Init(ctx)
+ RegisterVendorSnapshotModules(ctx)
+ RegisterRecoverySnapshotModules(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
}),
)
@@ -687,8 +690,10 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
- VendorSnapshotImageSingleton.Init(ctx)
- recoverySnapshotImageSingleton.init(ctx)
+ snapshot.VendorSnapshotImageSingleton.Init(ctx)
+ snapshot.RecoverySnapshotImageSingleton.Init(ctx)
+ RegisterVendorSnapshotModules(ctx)
+ RegisterRecoverySnapshotModules(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
RegisterVndkLibraryTxtTypes(ctx)
diff --git a/cc/util.go b/cc/util.go
index 1220d84..9bba876 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -21,6 +21,7 @@
"strings"
"android/soong/android"
+ "android/soong/snapshot"
)
// Efficiently converts a list of include directories to a single string
@@ -126,20 +127,6 @@
"ln -sf " + target + " " + filepath.Join(dir, linkName)
}
-func copyFileRule(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: path,
- Output: outPath,
- Description: "copy " + path.String() + " -> " + out,
- Args: map[string]string{
- "cpFlags": "-f -L",
- },
- })
- return outPath
-}
-
func combineNoticesRule(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
outPath := android.PathForOutput(ctx, out)
ctx.Build(pctx, android.BuildParams{
@@ -151,12 +138,6 @@
return outPath
}
-func writeStringToFileRule(ctx android.SingletonContext, content, out string) android.OutputPath {
- outPath := android.PathForOutput(ctx, out)
- android.WriteFileRule(ctx, outPath, content)
- return outPath
-}
-
// Dump a map to a list file as:
//
// {key1} {value1}
@@ -172,5 +153,5 @@
txtBuilder.WriteString(" ")
txtBuilder.WriteString(m[k])
}
- return writeStringToFileRule(ctx, txtBuilder.String(), path)
+ return snapshot.WriteStringToFileRule(ctx, txtBuilder.String(), path)
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 003b7c9..ba4d79f 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -13,141 +13,46 @@
// limitations under the License.
package cc
-// This file contains singletons to capture vendor and recovery snapshot. They consist of prebuilt
-// modules under AOSP so older vendor and recovery can be built with a newer system in a single
-// source tree.
-
import (
"encoding/json"
"path/filepath"
- "sort"
"strings"
"android/soong/android"
+ "android/soong/snapshot"
)
-var vendorSnapshotSingleton = snapshotSingleton{
- "vendor",
- "SOONG_VENDOR_SNAPSHOT_ZIP",
- android.OptionalPath{},
- true,
- VendorSnapshotImageSingleton,
- false, /* fake */
-}
+// This file defines how to capture cc modules into snapshot package.
-var vendorFakeSnapshotSingleton = snapshotSingleton{
- "vendor",
- "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
- android.OptionalPath{},
- true,
- VendorSnapshotImageSingleton,
- true, /* fake */
-}
-
-var recoverySnapshotSingleton = snapshotSingleton{
- "recovery",
- "SOONG_RECOVERY_SNAPSHOT_ZIP",
- android.OptionalPath{},
- false,
- recoverySnapshotImageSingleton,
- false, /* fake */
-}
-
-func VendorSnapshotSingleton() android.Singleton {
- return &vendorSnapshotSingleton
-}
-
-func VendorFakeSnapshotSingleton() android.Singleton {
- return &vendorFakeSnapshotSingleton
-}
-
-func RecoverySnapshotSingleton() android.Singleton {
- return &recoverySnapshotSingleton
-}
-
-type snapshotSingleton struct {
- // Name, e.g., "vendor", "recovery", "ramdisk".
- name string
-
- // Make variable that points to the snapshot file, e.g.,
- // "SOONG_RECOVERY_SNAPSHOT_ZIP".
- makeVar string
-
- // Path to the snapshot zip file.
- snapshotZipFile android.OptionalPath
-
- // Whether the image supports VNDK extension modules.
- supportsVndkExt bool
-
- // Implementation of the image interface specific to the image
- // associated with this snapshot (e.g., specific to the vendor image,
- // recovery image, etc.).
- image SnapshotImage
-
- // Whether this singleton is for fake snapshot or not.
- // Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
- // It is much faster to generate, and can be used to inspect dependencies.
- fake bool
-}
-
-// Determine if a dir under source tree is an SoC-owned proprietary directory based
-// on vendor snapshot configuration
-// Examples: device/, vendor/
-func isVendorProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
- return VendorSnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
-}
-
-// Determine if a dir under source tree is an SoC-owned proprietary directory based
-// on recovery snapshot configuration
-// Examples: device/, vendor/
-func isRecoveryProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
- return RecoverySnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
-}
-
-func IsVendorProprietaryModule(ctx android.BaseModuleContext) bool {
- // Any module in a vendor proprietary path is a vendor proprietary
- // module.
- if isVendorProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+// Checks if the target image would contain VNDK
+func includeVndk(image snapshot.SnapshotImage) bool {
+ if image.ImageName() == snapshot.VendorSnapshotImageName {
return true
}
- // However if the module is not in a vendor proprietary path, it may
- // still be a vendor proprietary module. This happens for cc modules
- // that are excluded from the vendor snapshot, and it means that the
- // vendor has assumed control of the framework-provided module.
- if c, ok := ctx.Module().(LinkableInterface); ok {
- if c.ExcludeFromVendorSnapshot() {
- return true
- }
- }
-
return false
}
-func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
-
- // Any module in a recovery proprietary path is a recovery proprietary
- // module.
- if isRecoveryProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+// Check if the module is VNDK private
+func isPrivate(image snapshot.SnapshotImage, m LinkableInterface) bool {
+ if image.ImageName() == snapshot.VendorSnapshotImageName && m.IsVndkPrivate() {
return true
}
- // However if the module is not in a recovery proprietary path, it may
- // still be a recovery proprietary module. This happens for cc modules
- // that are excluded from the recovery snapshot, and it means that the
- // vendor has assumed control of the framework-provided module.
+ return false
+}
- if c, ok := ctx.Module().(LinkableInterface); ok {
- if c.ExcludeFromRecoverySnapshot() {
- return true
- }
+// Checks if target image supports VNDK Ext
+func supportsVndkExt(image snapshot.SnapshotImage) bool {
+ if image.ImageName() == snapshot.VendorSnapshotImageName {
+ return true
}
return false
}
// Determines if the module is a candidate for snapshot.
-func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image SnapshotImage) bool {
+func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshot.SnapshotImage) bool {
if !m.Enabled() || m.HiddenFromMake() {
return false
}
@@ -158,12 +63,12 @@
}
// skip proprietary modules, but (for the vendor snapshot only)
// include all VNDK (static)
- if inProprietaryPath && (!image.includeVndk() || !m.IsVndk()) {
+ if inProprietaryPath && (!includeVndk(image) || !m.IsVndk()) {
return false
}
// If the module would be included based on its path, check to see if
// the module is marked to be excluded. If so, skip it.
- if image.excludeFromSnapshot(m) {
+ if image.ExcludeFromSnapshot(m) {
return false
}
if m.Target().Os.Class != android.Device {
@@ -173,7 +78,7 @@
return false
}
// the module must be installed in target image
- if !apexInfo.IsForPlatform() || m.IsSnapshotPrebuilt() || !image.inImage(m)() {
+ if !apexInfo.IsForPlatform() || m.IsSnapshotPrebuilt() || !image.InImage(m)() {
return false
}
// skip kernel_headers which always depend on vendor
@@ -203,13 +108,13 @@
}
}
if sanitizable.Static() {
- return sanitizable.OutputFile().Valid() && !image.private(m)
+ return sanitizable.OutputFile().Valid() && !isPrivate(image, m)
}
if sanitizable.Shared() || sanitizable.Rlib() {
if !sanitizable.OutputFile().Valid() {
return false
}
- if image.includeVndk() {
+ if includeVndk(image) {
if !sanitizable.IsVndk() {
return true
}
@@ -256,15 +161,9 @@
VintfFragments []string `json:",omitempty"`
}
-func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- if !c.image.shouldGenerateSnapshot(ctx) {
- return
- }
-
- var snapshotOutputs android.Paths
-
+var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths {
/*
- Vendor snapshot zipped artifacts directory structure:
+ Vendor snapshot zipped artifacts directory structure for cc modules:
{SNAPSHOT_ARCH}/
arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
shared/
@@ -296,13 +195,7 @@
(header files of same directory structure with source tree)
*/
- snapshotDir := c.name + "-snapshot"
- if c.fake {
- // If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
- // collision with real snapshot files
- snapshotDir = filepath.Join("fake", snapshotDir)
- }
- snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
+ var snapshotOutputs android.Paths
includeDir := filepath.Join(snapshotArchDir, "include")
configsDir := filepath.Join(snapshotArchDir, "configs")
@@ -317,9 +210,9 @@
if fake {
// All prebuilt binaries and headers are installed by copyFile function. This makes a fake
// snapshot just touch prebuilts and headers, rather than installing real files.
- return writeStringToFileRule(ctx, "", out)
+ return snapshot.WriteStringToFileRule(ctx, "", out)
} else {
- return copyFileRule(ctx, path, out)
+ return snapshot.CopyFileRule(pctx, ctx, path, out)
}
}
@@ -337,7 +230,7 @@
// Common properties among snapshots.
prop.ModuleName = ctx.ModuleName(m)
- if c.supportsVndkExt && m.IsVndkExt() {
+ if supportsVndkExt(s.Image) && m.IsVndkExt() {
// vndk exts are installed to /vendor/lib(64)?/vndk(-sp)?
if m.IsVndkSp() {
prop.RelativeInstallPath = "vndk-sp"
@@ -457,7 +350,7 @@
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil
}
- ret = append(ret, writeStringToFileRule(ctx, string(j), propOut))
+ ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
return ret
}
@@ -469,10 +362,10 @@
}
moduleDir := ctx.ModuleDir(module)
- inProprietaryPath := c.image.isProprietaryPath(moduleDir, ctx.DeviceConfig())
+ inProprietaryPath := s.Image.IsProprietaryPath(moduleDir, ctx.DeviceConfig())
apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
- if c.image.excludeFromSnapshot(m) {
+ if s.Image.ExcludeFromSnapshot(m) {
if inProprietaryPath {
// Error: exclude_from_vendor_snapshot applies
// to framework-path modules only.
@@ -481,7 +374,7 @@
}
}
- if !isSnapshotAware(ctx.DeviceConfig(), m, inProprietaryPath, apexInfo, c.image) {
+ if !isSnapshotAware(ctx.DeviceConfig(), m, inProprietaryPath, apexInfo, s.Image) {
return
}
@@ -489,8 +382,8 @@
// list, we will still include the module as if it was a fake module.
// The reason is that soong needs all the dependencies to be present, even
// if they are not using during the build.
- installAsFake := c.fake
- if c.image.excludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
+ installAsFake := s.Fake
+ if s.Image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
installAsFake = true
}
@@ -514,47 +407,12 @@
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), c.fake))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), s.Fake))
}
- // All artifacts are ready. Sort them to normalize ninja and then zip.
- sort.Slice(snapshotOutputs, func(i, j int) bool {
- return snapshotOutputs[i].String() < snapshotOutputs[j].String()
- })
-
- zipPath := android.PathForOutput(
- ctx,
- snapshotDir,
- c.name+"-"+ctx.Config().DeviceName()+".zip")
- zipRule := android.NewRuleBuilder(pctx, ctx)
-
- // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
- snapshotOutputList := android.PathForOutput(
- ctx,
- snapshotDir,
- c.name+"-"+ctx.Config().DeviceName()+"_list")
- rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
- zipRule.Command().
- Text("tr").
- FlagWithArg("-d ", "\\'").
- FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
- FlagWithOutput("> ", snapshotOutputList)
-
- zipRule.Temporary(snapshotOutputList)
-
- zipRule.Command().
- BuiltTool("soong_zip").
- FlagWithOutput("-o ", zipPath).
- FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
- FlagWithInput("-l ", snapshotOutputList)
-
- zipRule.Build(zipPath.String(), c.name+" snapshot "+zipPath.String())
- zipRule.DeleteTemporaryFiles()
- c.snapshotZipFile = android.OptionalPathForPath(zipPath)
+ return snapshotOutputs
}
-func (c *snapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
- ctx.Strict(
- c.makeVar,
- c.snapshotZipFile.String())
+func init() {
+ snapshot.RegisterSnapshotAction(ccSnapshotAction)
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 499d428..1ae79de 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -25,6 +25,7 @@
"android/soong/android"
"android/soong/cc/config"
"android/soong/etc"
+ "android/soong/snapshot"
"github.com/google/blueprint"
)
@@ -698,7 +699,7 @@
libPath := m.outputFile.Path()
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
- ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
+ ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))
if ctx.Config().VndkSnapshotBuildArtifacts() {
prop := struct {
@@ -720,7 +721,7 @@
ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
return nil, false
}
- ret = append(ret, writeStringToFileRule(ctx, string(j), propOut))
+ ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
}
return ret, true
}
@@ -778,8 +779,8 @@
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFileRule(
- ctx, header, filepath.Join(includeDir, header.String())))
+ snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
+ pctx, ctx, header, filepath.Join(includeDir, header.String())))
}
// install *.libraries.txt except vndkcorevariant.libraries.txt
@@ -788,8 +789,8 @@
if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
return
}
- snapshotOutputs = append(snapshotOutputs, copyFileRule(
- ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
+ snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
+ pctx, ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
})
/*
diff --git a/etc/Android.bp b/etc/Android.bp
index cab7389..06a2fa1 100644
--- a/etc/Android.bp
+++ b/etc/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"soong",
"soong-android",
+ "soong-snapshot",
],
srcs: [
"prebuilt_etc.go",
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index 4dd383d..4107916 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -28,12 +28,15 @@
// various `prebuilt_*` mutators.
import (
+ "encoding/json"
"fmt"
+ "path/filepath"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/snapshot"
)
var pctx = android.NewPackageContext("android/soong/etc")
@@ -43,6 +46,7 @@
func init() {
pctx.Import("android/soong/android")
RegisterPrebuiltEtcBuildComponents(android.InitRegistrationContext)
+ snapshot.RegisterSnapshotAction(generatePrebuiltSnapshot)
}
func RegisterPrebuiltEtcBuildComponents(ctx android.RegistrationContext) {
@@ -128,6 +132,9 @@
android.ModuleBase
android.DefaultableModuleBase
+ snapshot.VendorSnapshotModuleInterface
+ snapshot.RecoverySnapshotModuleInterface
+
properties prebuiltEtcProperties
subdirProperties prebuiltSubdirProperties
@@ -183,7 +190,7 @@
return p.inDebugRamdisk()
}
-func (p *PrebuiltEtc) inRecovery() bool {
+func (p *PrebuiltEtc) InRecovery() bool {
return p.ModuleBase.InRecovery() || p.ModuleBase.InstallInRecovery()
}
@@ -192,7 +199,7 @@
}
func (p *PrebuiltEtc) InstallInRecovery() bool {
- return p.inRecovery()
+ return p.InRecovery()
}
var _ android.ImageInterface = (*PrebuiltEtc)(nil)
@@ -271,6 +278,18 @@
return p.properties.Installable == nil || proptools.Bool(p.properties.Installable)
}
+func (p *PrebuiltEtc) InVendor() bool {
+ return p.ModuleBase.InstallInVendor()
+}
+
+func (p *PrebuiltEtc) ExcludeFromVendorSnapshot() bool {
+ return false
+}
+
+func (p *PrebuiltEtc) ExcludeFromRecoverySnapshot() bool {
+ return false
+}
+
func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if p.properties.Src == nil {
ctx.PropertyErrorf("src", "missing prebuilt source file")
@@ -344,7 +363,7 @@
if p.inDebugRamdisk() && !p.onlyInDebugRamdisk() {
nameSuffix = ".debug_ramdisk"
}
- if p.inRecovery() && !p.onlyInRecovery() {
+ if p.InRecovery() && !p.onlyInRecovery() {
nameSuffix = ".recovery"
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
@@ -494,3 +513,137 @@
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
return module
}
+
+// Flags to be included in the snapshot
+type snapshotJsonFlags struct {
+ ModuleName string `json:",omitempty"`
+ Filename string `json:",omitempty"`
+ RelativeInstallPath string `json:",omitempty"`
+}
+
+// Copy file into the snapshot
+func copyFile(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath {
+ if fake {
+ // Create empty file instead for the fake snapshot
+ return snapshot.WriteStringToFileRule(ctx, "", out)
+ } else {
+ return snapshot.CopyFileRule(pctx, ctx, path, out)
+ }
+}
+
+// Check if the module is target of the snapshot
+func isSnapshotAware(ctx android.SingletonContext, m *PrebuiltEtc, image snapshot.SnapshotImage) bool {
+ if !m.Enabled() {
+ return false
+ }
+
+ // Skip if the module is not included in the image
+ if !image.InImage(m)() {
+ return false
+ }
+
+ // When android/prebuilt.go selects between source and prebuilt, it sets
+ // HideFromMake on the other one to avoid duplicate install rules in make.
+ if m.IsHideFromMake() {
+ return false
+ }
+
+ // There are some prebuilt_etc module with multiple definition of same name.
+ // Check if the target would be included from the build
+ if !m.ExportedToMake() {
+ return false
+ }
+
+ // Skip if the module is in the predefined path list to skip
+ if image.IsProprietaryPath(ctx.ModuleDir(m), ctx.DeviceConfig()) {
+ return false
+ }
+
+ // Skip if the module should be excluded
+ if image.ExcludeFromSnapshot(m) || image.ExcludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) {
+ return false
+ }
+
+ // Skip from other exceptional cases
+ if m.Target().Os.Class != android.Device {
+ return false
+ }
+ if m.Target().NativeBridge == android.NativeBridgeEnabled {
+ return false
+ }
+
+ return true
+}
+
+func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths {
+ /*
+ Snapshot zipped artifacts directory structure for etc modules:
+ {SNAPSHOT_ARCH}/
+ arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
+ etc/
+ (prebuilt etc files)
+ arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
+ etc/
+ (prebuilt etc files)
+ NOTICE_FILES/
+ (notice files)
+ */
+ var snapshotOutputs android.Paths
+ noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
+ installedNotices := make(map[string]bool)
+
+ ctx.VisitAllModules(func(module android.Module) {
+ m, ok := module.(*PrebuiltEtc)
+ if !ok {
+ return
+ }
+
+ if !isSnapshotAware(ctx, m, s.Image) {
+ return
+ }
+
+ targetArch := "arch-" + m.Target().Arch.ArchType.String()
+
+ snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake))
+
+ prop := snapshotJsonFlags{}
+ propOut := snapshotLibOut + ".json"
+ prop.ModuleName = m.BaseModuleName()
+ if m.subdirProperties.Relative_install_path != nil {
+ prop.RelativeInstallPath = *m.subdirProperties.Relative_install_path
+ }
+
+ if m.properties.Filename != nil {
+ prop.Filename = *m.properties.Filename
+ }
+
+ j, err := json.Marshal(prop)
+ if err != nil {
+ ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
+ return
+ }
+ snapshotOutputs = append(snapshotOutputs, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
+
+ if len(m.EffectiveLicenseFiles()) > 0 {
+ noticeName := ctx.ModuleName(m) + ".txt"
+ noticeOut := filepath.Join(noticeDir, noticeName)
+ // skip already copied notice file
+ if !installedNotices[noticeOut] {
+ installedNotices[noticeOut] = true
+
+ noticeOutPath := android.PathForOutput(ctx, noticeOut)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: m.EffectiveLicenseFiles(),
+ Output: noticeOutPath,
+ Description: "combine notices for " + noticeOut,
+ })
+ snapshotOutputs = append(snapshotOutputs, noticeOutPath)
+ }
+ }
+
+ })
+
+ return snapshotOutputs
+}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 354f6bb..0c5cfe4 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -15,11 +15,15 @@
package etc
import (
+ "fmt"
"os"
"path/filepath"
"testing"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
+ "android/soong/snapshot"
)
func TestMain(m *testing.M) {
@@ -36,6 +40,18 @@
}),
)
+var prepareForPrebuiltEtcSnapshotTest = android.GroupFixturePreparers(
+ prepareForPrebuiltEtcTest,
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ snapshot.VendorSnapshotImageSingleton.Init(ctx)
+ snapshot.RecoverySnapshotImageSingleton.Init(ctx)
+ }),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
+ config.TestProductVariables.RecoverySnapshotVersion = proptools.StringPtr("current")
+ }),
+)
+
func TestPrebuiltEtcVariants(t *testing.T) {
result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
prebuilt_etc {
@@ -346,3 +362,110 @@
})
}
}
+
+func checkIfSnapshotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
+ checkIfSnapshotExistAsExpected(t, result, image, moduleName, true)
+}
+
+func checkIfSnapshotNotTaken(t *testing.T, result *android.TestResult, image string, moduleName string) {
+ checkIfSnapshotExistAsExpected(t, result, image, moduleName, false)
+}
+
+func checkIfSnapshotExistAsExpected(t *testing.T, result *android.TestResult, image string, moduleName string, expectToExist bool) {
+ snapshotSingleton := result.SingletonForTests(image + "-snapshot")
+ archType := "arm64"
+ archVariant := "armv8-a"
+ archDir := fmt.Sprintf("arch-%s", archType)
+
+ snapshotDir := fmt.Sprintf("%s-snapshot", image)
+ snapshotVariantPath := filepath.Join(snapshotDir, archType)
+ outputDir := filepath.Join(snapshotVariantPath, archDir, "etc")
+ imageVariant := ""
+ if image == "recovery" {
+ imageVariant = "recovery_"
+ }
+ mod := result.ModuleForTests(moduleName, fmt.Sprintf("android_%s%s_%s", imageVariant, archType, archVariant))
+ outputFiles := mod.OutputFiles(t, "")
+ if len(outputFiles) != 1 {
+ t.Errorf("%q must have single output\n", moduleName)
+ return
+ }
+ snapshotPath := filepath.Join(outputDir, moduleName)
+
+ if expectToExist {
+ out := snapshotSingleton.Output(snapshotPath)
+
+ if out.Input.String() != outputFiles[0].String() {
+ t.Errorf("The input of snapshot %q must be %q, but %q", "prebuilt_vendor", out.Input.String(), outputFiles[0])
+ }
+
+ snapshotJsonPath := snapshotPath + ".json"
+
+ if snapshotSingleton.MaybeOutput(snapshotJsonPath).Rule == nil {
+ t.Errorf("%q expected but not found", snapshotJsonPath)
+ }
+ } else {
+ out := snapshotSingleton.MaybeOutput(snapshotPath)
+ if out.Rule != nil {
+ t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
+ }
+ }
+}
+
+func TestPrebuiltTakeSnapshot(t *testing.T) {
+ var testBp = `
+ prebuilt_etc {
+ name: "prebuilt_vendor",
+ src: "foo.conf",
+ vendor: true,
+ }
+
+ prebuilt_etc {
+ name: "prebuilt_vendor_indirect",
+ src: "foo.conf",
+ vendor: true,
+ }
+
+ prebuilt_etc {
+ name: "prebuilt_recovery",
+ src: "bar.conf",
+ recovery: true,
+ }
+
+ prebuilt_etc {
+ name: "prebuilt_recovery_indirect",
+ src: "bar.conf",
+ recovery: true,
+ }
+ `
+
+ t.Run("prebuilt: vendor and recovery snapshot", func(t *testing.T) {
+ result := prepareForPrebuiltEtcSnapshotTest.RunTestWithBp(t, testBp)
+
+ checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
+ checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
+ checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
+ checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
+ })
+
+ t.Run("prebuilt: directed snapshot", func(t *testing.T) {
+ prepareForPrebuiltEtcDirectedSnapshotTest := android.GroupFixturePreparers(
+ prepareForPrebuiltEtcSnapshotTest,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.TestProductVariables.DirectedVendorSnapshot = true
+ config.TestProductVariables.VendorSnapshotModules = make(map[string]bool)
+ config.TestProductVariables.VendorSnapshotModules["prebuilt_vendor"] = true
+ config.TestProductVariables.DirectedRecoverySnapshot = true
+ config.TestProductVariables.RecoverySnapshotModules = make(map[string]bool)
+ config.TestProductVariables.RecoverySnapshotModules["prebuilt_recovery"] = true
+ }),
+ )
+
+ result := prepareForPrebuiltEtcDirectedSnapshotTest.RunTestWithBp(t, testBp)
+
+ checkIfSnapshotTaken(t, result, "vendor", "prebuilt_vendor")
+ checkIfSnapshotNotTaken(t, result, "vendor", "prebuilt_vendor_indirect")
+ checkIfSnapshotTaken(t, result, "recovery", "prebuilt_recovery")
+ checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
+ })
+}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index 503c31f..1ce9911 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -599,7 +599,7 @@
// The monolithic hidden API processing also needs access to all the output files produced by
// hidden API processing of this fragment.
- hiddenAPIInfo.HiddenAPIFlagOutput = (*output).HiddenAPIFlagOutput
+ hiddenAPIInfo.HiddenAPIFlagOutput = output.HiddenAPIFlagOutput
// Provide it for use by other modules.
ctx.SetProvider(HiddenAPIInfoProvider, hiddenAPIInfo)
@@ -896,10 +896,10 @@
// produceHiddenAPIOutput returns a path to the prebuilt all-flags.csv or nil if none is specified.
func (module *prebuiltBootclasspathFragmentModule) produceHiddenAPIOutput(ctx android.ModuleContext, contents []android.Module, input HiddenAPIFlagInput) *HiddenAPIOutput {
- pathForOptionalSrc := func(src *string) android.Path {
+ pathForSrc := func(property string, src *string) android.Path {
if src == nil {
- // TODO(b/179354495): Fail if this is not provided once prebuilts have been updated.
- return nil
+ ctx.PropertyErrorf(property, "is required but was not specified")
+ return android.PathForModuleSrc(ctx, "missing", property)
}
return android.PathForModuleSrc(ctx, *src)
}
@@ -910,11 +910,11 @@
output := HiddenAPIOutput{
HiddenAPIFlagOutput: HiddenAPIFlagOutput{
- StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags),
- AnnotationFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Annotation_flags),
- MetadataPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Metadata),
- IndexPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Index),
- AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags),
+ AnnotationFlagsPath: pathForSrc("hidden_api.annotation_flags", module.prebuiltProperties.Hidden_api.Annotation_flags),
+ MetadataPath: pathForSrc("hidden_api.metadata", module.prebuiltProperties.Hidden_api.Metadata),
+ IndexPath: pathForSrc("hidden_api.index", module.prebuiltProperties.Hidden_api.Index),
+ StubFlagsPath: pathForSrc("hidden_api.stub_flags", module.prebuiltProperties.Hidden_api.Stub_flags),
+ AllFlagsPath: pathForSrc("hidden_api.all_flags", module.prebuiltProperties.Hidden_api.All_flags),
},
EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
}
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index 654ebb7..86ab825 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -510,14 +510,6 @@
}
}
-// dedup removes duplicates in the flag files, while maintaining the order in which they were
-// appended.
-func (s FlagFilesByCategory) dedup() {
- for category, paths := range s {
- s[category] = android.FirstUniquePaths(paths)
- }
-}
-
// HiddenAPIInfo contains information provided by the hidden API processing.
//
// That includes paths resolved from HiddenAPIFlagFileProperties and also generated by hidden API
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index 52f0770..404b4c1 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -58,68 +58,33 @@
// Merge all the information from the classpathElements. The fragments form a DAG so it is possible that
// this will introduce duplicates so they will be resolved after processing all the classpathElements.
for _, element := range classpathElements {
- var classesJars android.Paths
switch e := element.(type) {
case *ClasspathLibraryElement:
- classesJars = retrieveClassesJarsFromModule(e.Module())
+ classesJars := retrieveClassesJarsFromModule(e.Module())
+ monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...)
case *ClasspathFragmentElement:
fragment := e.Module()
if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
monolithicInfo.append(&info)
-
- // If the bootclasspath fragment actually perform hidden API processing itself then use the
- // CSV files it provides and do not bother processing the classesJars files. This ensures
- // consistent behavior between source and prebuilt as prebuilt modules do not provide
- // classesJars.
- if info.AllFlagsPath != nil {
- continue
- }
+ } else {
+ ctx.ModuleErrorf("%s does not provide hidden API information", fragment)
}
-
- classesJars = extractClassesJarsFromModules(e.Contents)
}
-
- monolithicInfo.ClassesJars = append(monolithicInfo.ClassesJars, classesJars...)
}
- // Dedup paths.
- monolithicInfo.dedup()
-
return monolithicInfo
}
// append appends all the files from the supplied info to the corresponding files in this struct.
func (i *MonolithicHiddenAPIInfo) append(other *HiddenAPIInfo) {
i.FlagsFilesByCategory.append(other.FlagFilesByCategory)
-
- // The output may not be set if the bootclasspath_fragment has not yet been updated to support
- // hidden API processing.
- // TODO(b/179354495): Switch back to append once all bootclasspath_fragment modules have been
- // updated to support hidden API processing properly.
- appendIfNotNil := func(paths android.Paths, path android.Path) android.Paths {
- if path == nil {
- return paths
- }
- return append(paths, path)
- }
- i.StubFlagsPaths = appendIfNotNil(i.StubFlagsPaths, other.StubFlagsPath)
- i.AnnotationFlagsPaths = appendIfNotNil(i.AnnotationFlagsPaths, other.AnnotationFlagsPath)
- i.MetadataPaths = appendIfNotNil(i.MetadataPaths, other.MetadataPath)
- i.IndexPaths = appendIfNotNil(i.IndexPaths, other.IndexPath)
- i.AllFlagsPaths = appendIfNotNil(i.AllFlagsPaths, other.AllFlagsPath)
-}
-
-// dedup removes duplicates in all the paths, while maintaining the order in which they were
-// appended.
-func (i *MonolithicHiddenAPIInfo) dedup() {
- i.FlagsFilesByCategory.dedup()
- i.StubFlagsPaths = android.FirstUniquePaths(i.StubFlagsPaths)
- i.AnnotationFlagsPaths = android.FirstUniquePaths(i.AnnotationFlagsPaths)
- i.MetadataPaths = android.FirstUniquePaths(i.MetadataPaths)
- i.IndexPaths = android.FirstUniquePaths(i.IndexPaths)
- i.AllFlagsPaths = android.FirstUniquePaths(i.AllFlagsPaths)
+ i.StubFlagsPaths = append(i.StubFlagsPaths, other.StubFlagsPath)
+ i.AnnotationFlagsPaths = append(i.AnnotationFlagsPaths, other.AnnotationFlagsPath)
+ i.MetadataPaths = append(i.MetadataPaths, other.MetadataPath)
+ i.IndexPaths = append(i.IndexPaths, other.IndexPath)
+ i.AllFlagsPaths = append(i.AllFlagsPaths, other.AllFlagsPath)
}
var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
diff --git a/rust/Android.bp b/rust/Android.bp
index 11069d1..221014e 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -11,6 +11,7 @@
"soong-bloaty",
"soong-cc",
"soong-rust-config",
+ "soong-snapshot",
],
srcs: [
"androidmk.go",
diff --git a/rust/library.go b/rust/library.go
index 5a36bd1..8c10e29 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -21,6 +21,7 @@
"android/soong/android"
"android/soong/cc"
+ "android/soong/snapshot"
)
var (
@@ -645,7 +646,7 @@
variation := v.(*Module).ModuleBase.ImageVariation().Variation
if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
m.HasVendorVariant() &&
- !cc.IsVendorProprietaryModule(mctx) &&
+ !snapshot.IsVendorProprietaryModule(mctx) &&
strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
// cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go
index 2f54973..79eaab3 100644
--- a/rust/snapshot_prebuilt.go
+++ b/rust/snapshot_prebuilt.go
@@ -17,6 +17,7 @@
import (
"android/soong/android"
"android/soong/cc"
+
"github.com/google/blueprint/proptools"
)
diff --git a/scripts/hiddenapi/Android.bp b/scripts/hiddenapi/Android.bp
index 7472f52..c50dc24 100644
--- a/scripts/hiddenapi/Android.bp
+++ b/scripts/hiddenapi/Android.bp
@@ -48,6 +48,27 @@
},
}
+python_test_host {
+ name: "generate_hiddenapi_lists_test",
+ main: "generate_hiddenapi_lists_test.py",
+ srcs: [
+ "generate_hiddenapi_lists.py",
+ "generate_hiddenapi_lists_test.py",
+ ],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: true,
+ },
+ },
+ test_options: {
+ unit_test: true,
+ },
+}
+
python_binary_host {
name: "verify_overlaps",
main: "verify_overlaps.py",
diff --git a/scripts/hiddenapi/generate_hiddenapi_lists_test.py b/scripts/hiddenapi/generate_hiddenapi_lists_test.py
index ff3d708..b81424b 100755
--- a/scripts/hiddenapi/generate_hiddenapi_lists_test.py
+++ b/scripts/hiddenapi/generate_hiddenapi_lists_test.py
@@ -101,4 +101,4 @@
self.assertEqual(extract_package(signature), expected_package)
if __name__ == '__main__':
- unittest.main()
+ unittest.main(verbosity=2)
diff --git a/snapshot/Android.bp b/snapshot/Android.bp
new file mode 100644
index 0000000..f17ac53
--- /dev/null
+++ b/snapshot/Android.bp
@@ -0,0 +1,22 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-snapshot",
+ pkgPath: "android/soong/snapshot",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "soong",
+ "soong-android",
+ ],
+ srcs: [
+ "recovery_snapshot.go",
+ "snapshot.go",
+ "snapshot_base.go",
+ "util.go",
+ "vendor_snapshot.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/snapshot/recovery_snapshot.go b/snapshot/recovery_snapshot.go
new file mode 100644
index 0000000..9b3919c
--- /dev/null
+++ b/snapshot/recovery_snapshot.go
@@ -0,0 +1,130 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package snapshot
+
+import "android/soong/android"
+
+// Interface for modules which can be captured in the recovery snapshot.
+type RecoverySnapshotModuleInterface interface {
+ SnapshotModuleInterfaceBase
+ InRecovery() bool
+ ExcludeFromRecoverySnapshot() bool
+}
+
+var recoverySnapshotSingleton = SnapshotSingleton{
+ "recovery", // name
+ "SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ RecoverySnapshotImageSingleton, // Image
+ false, // Fake
+}
+
+func RecoverySnapshotSingleton() android.Singleton {
+ return &recoverySnapshotSingleton
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory based
+// on recovery snapshot configuration
+// Examples: device/, vendor/
+func isRecoveryProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return RecoverySnapshotSingleton().(*SnapshotSingleton).Image.IsProprietaryPath(dir, deviceConfig)
+}
+
+func IsRecoveryProprietaryModule(ctx android.BaseModuleContext) bool {
+
+ // Any module in a recovery proprietary path is a recovery proprietary
+ // module.
+ if isRecoveryProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+ return true
+ }
+
+ // However if the module is not in a recovery proprietary path, it may
+ // still be a recovery proprietary module. This happens for cc modules
+ // that are excluded from the recovery snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+
+ if c, ok := ctx.Module().(RecoverySnapshotModuleInterface); ok {
+ if c.ExcludeFromRecoverySnapshot() {
+ return true
+ }
+ }
+
+ return false
+}
+
+var RecoverySnapshotImageName = "recovery"
+
+type RecoverySnapshotImage struct{}
+
+func (RecoverySnapshotImage) Init(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
+}
+
+func (RecoverySnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // RECOVERY_SNAPSHOT_VERSION must be set to 'current' in order to generate a
+ // snapshot.
+ return ctx.DeviceConfig().RecoverySnapshotVersion() == "current"
+}
+
+func (RecoverySnapshotImage) InImage(m SnapshotModuleInterfaceBase) func() bool {
+ r, ok := m.(RecoverySnapshotModuleInterface)
+
+ if !ok {
+ // This module does not support recovery snapshot
+ return func() bool { return false }
+ }
+ return r.InRecovery
+}
+
+func (RecoverySnapshotImage) IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return isDirectoryExcluded(dir, deviceConfig.RecoverySnapshotDirsExcludedMap(), deviceConfig.RecoverySnapshotDirsIncludedMap())
+}
+
+func (RecoverySnapshotImage) ExcludeFromSnapshot(m SnapshotModuleInterfaceBase) bool {
+ r, ok := m.(RecoverySnapshotModuleInterface)
+
+ if !ok {
+ // This module does not support recovery snapshot
+ return true
+ }
+ return r.ExcludeFromRecoverySnapshot()
+}
+
+func (RecoverySnapshotImage) IsUsingSnapshot(cfg android.DeviceConfig) bool {
+ recoverySnapshotVersion := cfg.RecoverySnapshotVersion()
+ return recoverySnapshotVersion != "current" && recoverySnapshotVersion != ""
+}
+
+func (RecoverySnapshotImage) TargetSnapshotVersion(cfg android.DeviceConfig) string {
+ return cfg.RecoverySnapshotVersion()
+}
+
+func (RecoverySnapshotImage) ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
+ // If we're using full snapshot, not directed snapshot, capture every module
+ if !cfg.DirectedRecoverySnapshot() {
+ return false
+ }
+ // Else, checks if name is in RECOVERY_SNAPSHOT_MODULES.
+ return !cfg.RecoverySnapshotModules()[name]
+}
+
+func (RecoverySnapshotImage) ImageName() string {
+ return RecoverySnapshotImageName
+}
+
+var RecoverySnapshotImageSingleton RecoverySnapshotImage
+
+func init() {
+ RecoverySnapshotImageSingleton.Init(android.InitRegistrationContext)
+}
diff --git a/snapshot/snapshot.go b/snapshot/snapshot.go
new file mode 100644
index 0000000..294f8b6
--- /dev/null
+++ b/snapshot/snapshot.go
@@ -0,0 +1,122 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package snapshot
+
+import (
+ "path/filepath"
+ "sort"
+
+ "android/soong/android"
+)
+
+// This file contains singletons to capture snapshots. This singleton will generate snapshot of each target
+// image, and capturing snapshot module will be delegated to each module which implements GenerateSnapshotAction
+// function and register with RegisterSnapshotAction.
+
+var pctx = android.NewPackageContext("android/soong/snapshot")
+
+type SnapshotSingleton struct {
+ // Name, e.g., "vendor", "recovery", "ramdisk".
+ name string
+
+ // Make variable that points to the snapshot file, e.g.,
+ // "SOONG_RECOVERY_SNAPSHOT_ZIP".
+ makeVar string
+
+ // Path to the snapshot zip file.
+ snapshotZipFile android.OptionalPath
+
+ // Implementation of the image interface specific to the image
+ // associated with this snapshot (e.g., specific to the vendor image,
+ // recovery image, etc.).
+ Image SnapshotImage
+
+ // Whether this singleton is for fake snapshot or not.
+ // Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
+ // It is much faster to generate, and can be used to inspect dependencies.
+ Fake bool
+}
+
+// Interface of function to capture snapshot from each module
+type GenerateSnapshotAction func(snapshot SnapshotSingleton, ctx android.SingletonContext, snapshotArchDir string) android.Paths
+
+var snapshotActionList []GenerateSnapshotAction
+
+// Register GenerateSnapshotAction function so it can be called while generating snapshot
+func RegisterSnapshotAction(x GenerateSnapshotAction) {
+ snapshotActionList = append(snapshotActionList, x)
+}
+
+func (c *SnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ if !c.Image.shouldGenerateSnapshot(ctx) {
+ return
+ }
+
+ var snapshotOutputs android.Paths
+
+ // Snapshot zipped artifacts will be captured under {SNAPSHOT_ARCH} directory
+
+ snapshotDir := c.name + "-snapshot"
+ if c.Fake {
+ // If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
+ // collision with real snapshot files
+ snapshotDir = filepath.Join("fake", snapshotDir)
+ }
+ snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
+
+ for _, f := range snapshotActionList {
+ snapshotOutputs = append(snapshotOutputs, f(*c, ctx, snapshotArchDir)...)
+ }
+
+ // All artifacts are ready. Sort them to normalize ninja and then zip.
+ sort.Slice(snapshotOutputs, func(i, j int) bool {
+ return snapshotOutputs[i].String() < snapshotOutputs[j].String()
+ })
+
+ zipPath := android.PathForOutput(
+ ctx,
+ snapshotDir,
+ c.name+"-"+ctx.Config().DeviceName()+".zip")
+ zipRule := android.NewRuleBuilder(pctx, ctx)
+
+ // filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
+ snapshotOutputList := android.PathForOutput(
+ ctx,
+ snapshotDir,
+ c.name+"-"+ctx.Config().DeviceName()+"_list")
+ rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
+ zipRule.Command().
+ Text("tr").
+ FlagWithArg("-d ", "\\'").
+ FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
+ FlagWithOutput("> ", snapshotOutputList)
+
+ zipRule.Temporary(snapshotOutputList)
+
+ zipRule.Command().
+ BuiltTool("soong_zip").
+ FlagWithOutput("-o ", zipPath).
+ FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
+ FlagWithInput("-l ", snapshotOutputList)
+
+ zipRule.Build(zipPath.String(), c.name+" snapshot "+zipPath.String())
+ zipRule.DeleteTemporaryFiles()
+ c.snapshotZipFile = android.OptionalPathForPath(zipPath)
+}
+
+func (c *SnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.Strict(
+ c.makeVar,
+ c.snapshotZipFile.String())
+}
diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go
new file mode 100644
index 0000000..de93f3e
--- /dev/null
+++ b/snapshot/snapshot_base.go
@@ -0,0 +1,104 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package snapshot
+
+import (
+ "android/soong/android"
+ "path/filepath"
+)
+
+// Interface for modules which can be captured in the snapshot.
+type SnapshotModuleInterfaceBase interface{}
+
+// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
+// vendor, recovery, ramdisk.
+type SnapshotImage interface {
+ // Returns true if a snapshot should be generated for this image.
+ shouldGenerateSnapshot(ctx android.SingletonContext) bool
+
+ // Function that returns true if the module is included in this image.
+ // Using a function return instead of a value to prevent early
+ // evalution of a function that may be not be defined.
+ InImage(m SnapshotModuleInterfaceBase) func() bool
+
+ // Returns true if a dir under source tree is an SoC-owned proprietary
+ // directory, such as device/, vendor/, etc.
+ //
+ // For a given snapshot (e.g., vendor, recovery, etc.) if
+ // isProprietaryPath(dir, deviceConfig) returns true, then the module in dir
+ // will be built from sources.
+ IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool
+
+ // Whether a given module has been explicitly excluded from the
+ // snapshot, e.g., using the exclude_from_vendor_snapshot or
+ // exclude_from_recovery_snapshot properties.
+ ExcludeFromSnapshot(m SnapshotModuleInterfaceBase) bool
+
+ // Returns true if the build is using a snapshot for this image.
+ IsUsingSnapshot(cfg android.DeviceConfig) bool
+
+ // Returns a version of which the snapshot should be used in this target.
+ // This will only be meaningful when isUsingSnapshot is true.
+ TargetSnapshotVersion(cfg android.DeviceConfig) string
+
+ // Whether to exclude a given module from the directed snapshot or not.
+ // If the makefile variable DIRECTED_{IMAGE}_SNAPSHOT is true, directed snapshot is turned on,
+ // and only modules listed in {IMAGE}_SNAPSHOT_MODULES will be captured.
+ ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool
+
+ // Returns target image name
+ ImageName() string
+}
+
+type directoryMap map[string]bool
+
+var (
+ // Modules under following directories are ignored. They are OEM's and vendor's
+ // proprietary modules(device/, kernel/, vendor/, and hardware/).
+ defaultDirectoryExcludedMap = directoryMap{
+ "device": true,
+ "hardware": true,
+ "kernel": true,
+ "vendor": true,
+ }
+
+ // Modules under following directories are included as they are in AOSP,
+ // although hardware/ and kernel/ are normally for vendor's own.
+ defaultDirectoryIncludedMap = directoryMap{
+ "kernel/configs": true,
+ "kernel/prebuilts": true,
+ "kernel/tests": true,
+ "hardware/interfaces": true,
+ "hardware/libhardware": true,
+ "hardware/libhardware_legacy": true,
+ "hardware/ril": true,
+ }
+)
+
+func isDirectoryExcluded(dir string, excludedMap directoryMap, includedMap directoryMap) bool {
+ if dir == "." || dir == "/" {
+ return false
+ }
+ if includedMap[dir] {
+ return false
+ } else if excludedMap[dir] {
+ return true
+ } else if defaultDirectoryIncludedMap[dir] {
+ return false
+ } else if defaultDirectoryExcludedMap[dir] {
+ return true
+ } else {
+ return isDirectoryExcluded(filepath.Dir(dir), excludedMap, includedMap)
+ }
+}
diff --git a/snapshot/util.go b/snapshot/util.go
new file mode 100644
index 0000000..2297dfc
--- /dev/null
+++ b/snapshot/util.go
@@ -0,0 +1,36 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package snapshot
+
+import "android/soong/android"
+
+func WriteStringToFileRule(ctx android.SingletonContext, content, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ android.WriteFileRule(ctx, outPath, content)
+ return outPath
+}
+
+func CopyFileRule(pctx android.PackageContext, ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: path,
+ Output: outPath,
+ Description: "copy " + path.String() + " -> " + out,
+ Args: map[string]string{
+ "cpFlags": "-f -L",
+ },
+ })
+ return outPath
+}
diff --git a/snapshot/vendor_snapshot.go b/snapshot/vendor_snapshot.go
new file mode 100644
index 0000000..9bd26c2
--- /dev/null
+++ b/snapshot/vendor_snapshot.go
@@ -0,0 +1,147 @@
+// Copyright 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package snapshot
+
+import "android/soong/android"
+
+// Interface for modules which can be captured in the vendor snapshot.
+type VendorSnapshotModuleInterface interface {
+ SnapshotModuleInterfaceBase
+ InVendor() bool
+ ExcludeFromVendorSnapshot() bool
+}
+
+var vendorSnapshotSingleton = SnapshotSingleton{
+ "vendor", // name
+ "SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ VendorSnapshotImageSingleton, // Image
+ false, // Fake
+}
+
+var vendorFakeSnapshotSingleton = SnapshotSingleton{
+ "vendor", // name
+ "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ VendorSnapshotImageSingleton, // Image
+ true, // Fake
+}
+
+func VendorSnapshotSingleton() android.Singleton {
+ return &vendorSnapshotSingleton
+}
+
+func VendorFakeSnapshotSingleton() android.Singleton {
+ return &vendorFakeSnapshotSingleton
+}
+
+// Determine if a dir under source tree is an SoC-owned proprietary directory based
+// on vendor snapshot configuration
+// Examples: device/, vendor/
+func isVendorProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return VendorSnapshotSingleton().(*SnapshotSingleton).Image.IsProprietaryPath(dir, deviceConfig)
+}
+
+func IsVendorProprietaryModule(ctx android.BaseModuleContext) bool {
+ // Any module in a vendor proprietary path is a vendor proprietary
+ // module.
+ if isVendorProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
+ return true
+ }
+
+ // However if the module is not in a vendor proprietary path, it may
+ // still be a vendor proprietary module. This happens for cc modules
+ // that are excluded from the vendor snapshot, and it means that the
+ // vendor has assumed control of the framework-provided module.
+ if c, ok := ctx.Module().(VendorSnapshotModuleInterface); ok {
+ if c.ExcludeFromVendorSnapshot() {
+ return true
+ }
+ }
+
+ return false
+}
+
+var VendorSnapshotImageName = "vendor"
+
+type VendorSnapshotImage struct{}
+
+func (VendorSnapshotImage) Init(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
+}
+
+func (VendorSnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) {
+ ctx.RegisterModuleType(name, factory)
+}
+
+func (VendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
+ // BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
+ return ctx.DeviceConfig().VndkVersion() == "current"
+}
+
+func (VendorSnapshotImage) InImage(m SnapshotModuleInterfaceBase) func() bool {
+ v, ok := m.(VendorSnapshotModuleInterface)
+
+ if !ok {
+ // This module does not support Vendor snapshot
+ return func() bool { return false }
+ }
+
+ return v.InVendor
+}
+
+func (VendorSnapshotImage) IsProprietaryPath(dir string, deviceConfig android.DeviceConfig) bool {
+ return isDirectoryExcluded(dir, deviceConfig.VendorSnapshotDirsExcludedMap(), deviceConfig.VendorSnapshotDirsIncludedMap())
+}
+
+func (VendorSnapshotImage) ExcludeFromSnapshot(m SnapshotModuleInterfaceBase) bool {
+ v, ok := m.(VendorSnapshotModuleInterface)
+
+ if !ok {
+ // This module does not support Vendor snapshot
+ return true
+ }
+
+ return v.ExcludeFromVendorSnapshot()
+}
+
+func (VendorSnapshotImage) IsUsingSnapshot(cfg android.DeviceConfig) bool {
+ vndkVersion := cfg.VndkVersion()
+ return vndkVersion != "current" && vndkVersion != ""
+}
+
+func (VendorSnapshotImage) TargetSnapshotVersion(cfg android.DeviceConfig) string {
+ return cfg.VndkVersion()
+}
+
+// returns true iff a given module SHOULD BE EXCLUDED, false if included
+func (VendorSnapshotImage) ExcludeFromDirectedSnapshot(cfg android.DeviceConfig, name string) bool {
+ // If we're using full snapshot, not directed snapshot, capture every module
+ if !cfg.DirectedVendorSnapshot() {
+ return false
+ }
+ // Else, checks if name is in VENDOR_SNAPSHOT_MODULES.
+ return !cfg.VendorSnapshotModules()[name]
+}
+
+func (VendorSnapshotImage) ImageName() string {
+ return VendorSnapshotImageName
+}
+
+var VendorSnapshotImageSingleton VendorSnapshotImage
+
+func init() {
+ VendorSnapshotImageSingleton.Init(android.InitRegistrationContext)
+}