Remove some global state from vendor and recovery snapshots

Snapshots storead global sets of modules that should be replaced with
vendor snapshot modules.  Move the data instead to a vendor_snapshot
or recovery_snapshot module type that depends on all the modules in
the snapshot, and then have modules that should use the snaphsot
depend on it to query for the set of modules that should be replaced.

Bug: 177098205
Test: vendor_snapshot_test.go
Change-Id: I2826adacfb473e9139b5ea93ba83b8a54cc1a56b
diff --git a/cc/cc.go b/cc/cc.go
index afa6bf9..0dd90cf 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -50,9 +50,7 @@
 		ctx.BottomUp("version", versionMutator).Parallel()
 		ctx.BottomUp("begin", BeginMutator).Parallel()
 		ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
-		ctx.BottomUp("vendor_snapshot", VendorSnapshotMutator).Parallel()
 		ctx.BottomUp("vendor_snapshot_source", VendorSnapshotSourceMutator).Parallel()
-		ctx.BottomUp("recovery_snapshot", RecoverySnapshotMutator).Parallel()
 		ctx.BottomUp("recovery_snapshot_source", RecoverySnapshotSourceMutator).Parallel()
 	})
 
@@ -1937,6 +1935,40 @@
 
 	c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
 
+	var snapshotInfo *SnapshotInfo
+	getSnapshot := func() SnapshotInfo {
+		// Only modules with BOARD_VNDK_VERSION uses snapshot.  Others use the zero value of
+		// SnapshotInfo, which provides no mappings.
+		if snapshotInfo == nil {
+			// Only retrieve the snapshot on demand in order to avoid circular dependencies
+			// between the modules in the snapshot and the snapshot itself.
+			var snapshotModule []blueprint.Module
+			if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() {
+				snapshotModule = ctx.AddVariationDependencies(nil, nil, "vendor_snapshot")
+			} else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() {
+				snapshotModule = ctx.AddVariationDependencies(nil, nil, "recovery_snapshot")
+			}
+			if len(snapshotModule) > 0 {
+				snapshot := ctx.OtherModuleProvider(snapshotModule[0], SnapshotInfoProvider).(SnapshotInfo)
+				snapshotInfo = &snapshot
+				// republish the snapshot for use in later mutators on this module
+				ctx.SetProvider(SnapshotInfoProvider, snapshot)
+			} else {
+				snapshotInfo = &SnapshotInfo{}
+			}
+		}
+
+		return *snapshotInfo
+	}
+
+	rewriteSnapshotLib := func(lib string, snapshotMap map[string]string) string {
+		if snapshot, ok := snapshotMap[lib]; ok {
+			return snapshot
+		}
+
+		return lib
+	}
+
 	variantNdkLibs := []string{}
 	variantLateNdkLibs := []string{}
 	if ctx.Os() == android.Android {
@@ -1956,21 +1988,6 @@
 		// nonvariantLibs
 
 		vendorPublicLibraries := vendorPublicLibraries(actx.Config())
-		vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config())
-		recoverySnapshotSharedLibs := recoverySnapshotSharedLibs(actx.Config())
-
-		rewriteVendorLibs := func(lib string) string {
-			// only modules with BOARD_VNDK_VERSION uses snapshot.
-			if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
-				return lib
-			}
-
-			if snapshot, ok := vendorSnapshotSharedLibs.get(lib, actx.Arch().ArchType); ok {
-				return snapshot
-			}
-
-			return lib
-		}
 
 		rewriteLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
 			variantLibs = []string{}
@@ -1979,21 +1996,11 @@
 				// strip #version suffix out
 				name, _ := StubsLibNameAndVersion(entry)
 				if c.InRecovery() {
-					recoverySnapshotVersion :=
-						actx.DeviceConfig().RecoverySnapshotVersion()
-					if recoverySnapshotVersion == "current" ||
-						recoverySnapshotVersion == "" {
-						nonvariantLibs = append(nonvariantLibs, name)
-					} else if snapshot, ok := recoverySnapshotSharedLibs.get(
-						name, actx.Arch().ArchType); ok {
-						nonvariantLibs = append(nonvariantLibs, snapshot)
-					} else {
-						nonvariantLibs = append(nonvariantLibs, name)
-					}
+					nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
 				} else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
 					variantLibs = append(variantLibs, name+ndkLibrarySuffix)
 				} else if ctx.useVndk() {
-					nonvariantLibs = append(nonvariantLibs, rewriteVendorLibs(entry))
+					nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
 				} else if (ctx.Platform() || ctx.ProductSpecific()) && inList(name, *vendorPublicLibraries) {
 					vendorPublicLib := name + vendorPublicLibrarySuffix
 					if actx.OtherModuleExists(vendorPublicLib) {
@@ -2015,56 +2022,19 @@
 		deps.SharedLibs, variantNdkLibs = rewriteLibs(deps.SharedLibs)
 		deps.LateSharedLibs, variantLateNdkLibs = rewriteLibs(deps.LateSharedLibs)
 		deps.ReexportSharedLibHeaders, _ = rewriteLibs(deps.ReexportSharedLibHeaders)
-		if ctx.useVndk() {
-			for idx, lib := range deps.RuntimeLibs {
-				deps.RuntimeLibs[idx] = rewriteVendorLibs(lib)
-			}
+
+		for idx, lib := range deps.RuntimeLibs {
+			deps.RuntimeLibs[idx] = rewriteSnapshotLib(lib, getSnapshot().SharedLibs)
 		}
 	}
 
-	rewriteSnapshotLibs := func(lib string, snapshotMap *snapshotMap) string {
-		// only modules with BOARD_VNDK_VERSION uses snapshot.
-		if c.VndkVersion() != actx.DeviceConfig().VndkVersion() {
-			return lib
-		}
-
-		if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
-			return snapshot
-		}
-
-		return lib
-	}
-
-	snapshotHeaderLibs := vendorSnapshotHeaderLibs(actx.Config())
-	snapshotStaticLibs := vendorSnapshotStaticLibs(actx.Config())
-	snapshotObjects := vendorSnapshotObjects(actx.Config())
-
-	if c.InRecovery() {
-		rewriteSnapshotLibs = func(lib string, snapshotMap *snapshotMap) string {
-			recoverySnapshotVersion :=
-				actx.DeviceConfig().RecoverySnapshotVersion()
-			if recoverySnapshotVersion == "current" ||
-				recoverySnapshotVersion == "" {
-				return lib
-			} else if snapshot, ok := snapshotMap.get(lib, actx.Arch().ArchType); ok {
-				return snapshot
-			}
-
-			return lib
-		}
-
-		snapshotHeaderLibs = recoverySnapshotHeaderLibs(actx.Config())
-		snapshotStaticLibs = recoverySnapshotStaticLibs(actx.Config())
-		snapshotObjects = recoverySnapshotObjects(actx.Config())
-	}
-
 	for _, lib := range deps.HeaderLibs {
 		depTag := libraryDependencyTag{Kind: headerLibraryDependency}
 		if inList(lib, deps.ReexportHeaderLibHeaders) {
 			depTag.reexportFlags = true
 		}
 
-		lib = rewriteSnapshotLibs(lib, snapshotHeaderLibs)
+		lib = rewriteSnapshotLib(lib, getSnapshot().HeaderLibs)
 
 		if c.IsStubs() {
 			actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
@@ -2087,7 +2057,7 @@
 			lib = impl
 		}
 
-		lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
+		lib = rewriteSnapshotLib(lib, getSnapshot().StaticLibs)
 
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
@@ -2107,7 +2077,7 @@
 			lib = impl
 		}
 
-		lib = rewriteSnapshotLibs(lib, snapshotStaticLibs)
+		lib = rewriteSnapshotLib(lib, getSnapshot().StaticLibs)
 
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
@@ -2121,14 +2091,14 @@
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
-		}, depTag, rewriteSnapshotLibs(staticUnwinder(actx), snapshotStaticLibs))
+		}, depTag, rewriteSnapshotLib(staticUnwinder(actx), getSnapshot().StaticLibs))
 	}
 
 	for _, lib := range deps.LateStaticLibs {
 		depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
 		actx.AddVariationDependencies([]blueprint.Variation{
 			{Mutator: "link", Variation: "static"},
-		}, depTag, rewriteSnapshotLibs(lib, snapshotStaticLibs))
+		}, depTag, rewriteSnapshotLib(lib, getSnapshot().StaticLibs))
 	}
 
 	// shared lib names without the #version suffix
@@ -2192,11 +2162,11 @@
 	actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
 	if deps.CrtBegin != "" {
 		actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
-			rewriteSnapshotLibs(deps.CrtBegin, snapshotObjects))
+			rewriteSnapshotLib(deps.CrtBegin, getSnapshot().Objects))
 	}
 	if deps.CrtEnd != "" {
 		actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
-			rewriteSnapshotLibs(deps.CrtEnd, snapshotObjects))
+			rewriteSnapshotLib(deps.CrtEnd, getSnapshot().Objects))
 	}
 	if deps.LinkerFlagsFile != "" {
 		actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)