Merge changes I3c73920d,I03b09e51,I09069828

* changes:
  Remove deviceInstalls from bootImageVariant
  Remove profilePathOnHost from bootImageConfig
  Document bootImageConfig and bootImageVariant structs
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index f5b5f99..3a28c59 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -264,7 +264,7 @@
 	//
 	// If it could not create the files then it will return nil. Otherwise, it will return a map from
 	// android.ArchType to the predefined paths of the boot image files.
-	produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch
+	produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs
 }
 
 var _ commonBootclasspathFragment = (*BootclasspathFragmentModule)(nil)
@@ -583,23 +583,24 @@
 		// Perform hidden API processing.
 		hiddenAPIOutput := b.generateHiddenAPIBuildActions(ctx, contents, fragments)
 
-		var bootImageFilesByArch bootImageFilesByArch
+		var bootImageFiles bootImageOutputs
 		if imageConfig != nil {
 			// Delegate the production of the boot image files to a module type specific method.
 			common := ctx.Module().(commonBootclasspathFragment)
-			bootImageFilesByArch = common.produceBootImageFiles(ctx, imageConfig)
+			bootImageFiles = common.produceBootImageFiles(ctx, imageConfig)
 
 			if shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
 				// Zip the boot image files up, if available. This will generate the zip file in a
 				// predefined location.
-				buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFilesByArch)
+				buildBootImageZipInPredefinedLocation(ctx, imageConfig, bootImageFiles.byArch)
 
 				// Copy the dex jars of this fragment's content modules to their predefined locations.
 				copyBootJarsToPredefinedLocations(ctx, hiddenAPIOutput.EncodedBootDexFilesByModule, imageConfig.dexPathsByModule)
 			}
 
-			for _, variant := range imageConfig.apexVariants() {
-				arch := variant.target.Arch.ArchType.String()
+			for _, variant := range bootImageFiles.variants {
+				archType := variant.config.target.Arch.ArchType
+				arch := archType.String()
 				for _, install := range variant.deviceInstalls {
 					// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
 					installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
@@ -620,7 +621,7 @@
 		// A prebuilt fragment cannot contribute to an apex.
 		if !android.IsModulePrebuilt(ctx.Module()) {
 			// Provide the apex content info.
-			b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFilesByArch)
+			b.provideApexContentInfo(ctx, imageConfig, hiddenAPIOutput, bootImageFiles)
 		}
 	} else {
 		// Versioned fragments are not needed by make.
@@ -663,7 +664,7 @@
 
 // provideApexContentInfo creates, initializes and stores the apex content info for use by other
 // modules.
-func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFilesByArch bootImageFilesByArch) {
+func (b *BootclasspathFragmentModule) provideApexContentInfo(ctx android.ModuleContext, imageConfig *bootImageConfig, hiddenAPIOutput *HiddenAPIOutput, bootImageFiles bootImageOutputs) {
 	// Construct the apex content info from the config.
 	info := BootclasspathFragmentApexContentInfo{
 		// Populate the apex content info with paths to the dex jars.
@@ -674,14 +675,14 @@
 		info.modules = imageConfig.modules
 		global := dexpreopt.GetGlobalConfig(ctx)
 		if !global.DisableGenerateProfile {
-			info.profilePathOnHost = imageConfig.profilePathOnHost
+			info.profilePathOnHost = bootImageFiles.profile
 			info.profileInstallPathInApex = imageConfig.profileInstallPathInApex
 		}
 
 		info.shouldInstallBootImageInApex = imageConfig.shouldInstallInApex()
 	}
 
-	info.bootImageFilesByArch = bootImageFilesByArch
+	info.bootImageFilesByArch = bootImageFiles.byArch
 
 	// Make the apex content info available for other modules.
 	ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
@@ -934,9 +935,9 @@
 }
 
 // produceBootImageFiles builds the boot image files from the source if it is required.
-func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
 	if SkipDexpreoptBootJars(ctx) {
-		return nil
+		return bootImageOutputs{}
 	}
 
 	// Only generate the boot image if the configuration does not skip it.
@@ -948,21 +949,21 @@
 //
 // If it could not create the files then it will return nil. Otherwise, it will return a map from
 // android.ArchType to the predefined paths of the boot image files.
-func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (b *BootclasspathFragmentModule) generateBootImageBuildActions(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
 	global := dexpreopt.GetGlobalConfig(ctx)
 	if !shouldBuildBootImages(ctx.Config(), global) {
-		return nil
+		return bootImageOutputs{}
 	}
 
 	// Bootclasspath fragment modules that are for the platform do not produce a boot image.
 	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
 	if apexInfo.IsForPlatform() {
-		return nil
+		return bootImageOutputs{}
 	}
 
 	// Bootclasspath fragment modules that are versioned do not produce a boot image.
 	if android.IsModuleInVersionedSdk(ctx.Module()) {
-		return nil
+		return bootImageOutputs{}
 	}
 
 	// Build a profile for the image config and then use that to build the boot image.
@@ -972,11 +973,11 @@
 	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)
 
 	// Build boot image files for the android variants.
-	androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+	bootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
 
 	// Return the boot image files for the android variants for inclusion in an APEX and to be zipped
 	// up for the dist.
-	return androidBootImageFilesByArch
+	return bootImageFiles
 }
 
 func (b *BootclasspathFragmentModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1277,14 +1278,14 @@
 }
 
 // produceBootImageFiles extracts the boot image files from the APEX if available.
-func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageFilesByArch {
+func (module *PrebuiltBootclasspathFragmentModule) produceBootImageFiles(ctx android.ModuleContext, imageConfig *bootImageConfig) bootImageOutputs {
 	if !shouldCopyBootFilesToPredefinedLocations(ctx, imageConfig) {
-		return nil
+		return bootImageOutputs{}
 	}
 
 	di := android.FindDeapexerProviderForModule(ctx)
 	if di == nil {
-		return nil // An error has been reported by FindDeapexerProviderForModule.
+		return bootImageOutputs{} // An error has been reported by FindDeapexerProviderForModule.
 	}
 
 	profile := (android.WritablePath)(nil)
@@ -1302,8 +1303,17 @@
 		// If the boot image files for the android variants are in the prebuilt apex, we must use those
 		// rather than building new ones because those boot image files are going to be used on device.
 		files := bootImageFilesByArch{}
+		bootImageFiles := bootImageOutputs{
+			byArch:  files,
+			profile: profile,
+		}
 		for _, variant := range imageConfig.apexVariants() {
 			arch := variant.target.Arch.ArchType
+			bootImageFiles.variants = append(bootImageFiles.variants, bootImageVariantOutputs{
+				variant,
+				// No device installs needed when installed in APEX.
+				nil,
+			})
 			for _, toPath := range variant.imagesDeps {
 				apexRelativePath := apexRootRelativePathToBootImageFile(arch, toPath.Base())
 				// Get the path to the file that the deapexer extracted from the prebuilt apex file.
@@ -1321,11 +1331,11 @@
 				})
 			}
 		}
-		return files
+		return bootImageFiles
 	} else {
 		if profile == nil {
 			ctx.ModuleErrorf("Unable to produce boot image files: neither boot image files nor profiles exists in the prebuilt apex")
-			return nil
+			return bootImageOutputs{}
 		}
 		// Build boot image files for the android variants from the dex files provided by the contents
 		// of this module.
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 4e416fc..9237e89 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -228,6 +228,11 @@
 }
 
 // Target-independent description of a boot image.
+//
+// WARNING: All fields in this struct should be initialized in the genBootImageConfigs function.
+// Failure to do so can lead to data races if there is no synchronization enforced ordering between
+// the writer and the reader. Fields which break this rule are marked as deprecated and should be
+// removed and replaced with something else, e.g. providers.
 type bootImageConfig struct {
 	// If this image is an extension, the image that it extends.
 	extends *bootImageConfig
@@ -268,14 +273,15 @@
 	zip android.WritablePath
 
 	// Rules which should be used in make to install the outputs.
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
 	profileInstalls android.RuleBuilderInstalls
 
 	// Path to the license metadata file for the module that built the profile.
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
 	profileLicenseMetadataFile android.OptionalPath
 
-	// Path to the image profile file on host (or empty, if profile is not generated).
-	profilePathOnHost android.Path
-
 	// Target-dependent fields.
 	variants []*bootImageVariant
 
@@ -284,6 +290,8 @@
 }
 
 // Target-dependent description of a boot image.
+//
+// WARNING: The warning comment on bootImageConfig applies here too.
 type bootImageVariant struct {
 	*bootImageConfig
 
@@ -314,14 +322,23 @@
 	primaryImagesDeps android.Paths
 
 	// Rules which should be used in make to install the outputs on host.
-	installs           android.RuleBuilderInstalls
-	vdexInstalls       android.RuleBuilderInstalls
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
+	installs android.RuleBuilderInstalls
+
+	// Rules which should be used in make to install the vdex outputs on host.
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
+	vdexInstalls android.RuleBuilderInstalls
+
+	// Rules which should be used in make to install the unstripped outputs on host.
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
 	unstrippedInstalls android.RuleBuilderInstalls
 
-	// Rules which should be used in make to install the outputs on device.
-	deviceInstalls android.RuleBuilderInstalls
-
 	// Path to the license metadata file for the module that built the image.
+	//
+	// Deprecated: Not initialized correctly, see struct comment.
 	licenseMetadataFile android.OptionalPath
 }
 
@@ -548,7 +565,7 @@
 // boot image files.
 //
 // The paths are returned because they are needed elsewhere in Soong, e.g. for populating an APEX.
-func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageFilesByArch {
+func buildBootImageVariantsForAndroidOs(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath) bootImageOutputs {
 	return buildBootImageForOsType(ctx, image, profile, android.Android)
 }
 
@@ -563,21 +580,38 @@
 	buildBootImageForOsType(ctx, image, profile, ctx.Config().BuildOS)
 }
 
+// bootImageOutputs encapsulates information about boot images that were created/obtained by
+// commonBootclasspathFragment.produceBootImageFiles.
+type bootImageOutputs struct {
+	// Map from arch to the paths to the boot image files created/obtained for that arch.
+	byArch bootImageFilesByArch
+
+	variants []bootImageVariantOutputs
+
+	// The path to the profile file created/obtained for the boot image.
+	profile android.WritablePath
+}
+
 // buildBootImageForOsType takes a bootImageConfig, a profile file and an android.OsType
 // boot image files are required for and it creates rules to build the boot image
 // files for all the required architectures for them.
 //
 // It returns a map from android.ArchType to the predefined paths of the boot image files.
-func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageFilesByArch {
+func buildBootImageForOsType(ctx android.ModuleContext, image *bootImageConfig, profile android.WritablePath, requiredOsType android.OsType) bootImageOutputs {
 	filesByArch := bootImageFilesByArch{}
+	imageOutputs := bootImageOutputs{
+		byArch:  filesByArch,
+		profile: profile,
+	}
 	for _, variant := range image.variants {
 		if variant.target.Os == requiredOsType {
-			buildBootImageVariant(ctx, variant, profile)
+			variantOutputs := buildBootImageVariant(ctx, variant, profile)
+			imageOutputs.variants = append(imageOutputs.variants, variantOutputs)
 			filesByArch[variant.target.Arch.ArchType] = variant.imagesDeps.Paths()
 		}
 	}
 
-	return filesByArch
+	return imageOutputs
 }
 
 // buildBootImageZipInPredefinedLocation generates a zip file containing all the boot image files.
@@ -605,8 +639,13 @@
 	rule.Build("zip_"+image.name, "zip "+image.name+" image")
 }
 
+type bootImageVariantOutputs struct {
+	config         *bootImageVariant
+	deviceInstalls android.RuleBuilderInstalls
+}
+
 // Generate boot image build rules for a specific target.
-func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) {
+func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
 
 	globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
 	global := dexpreopt.GetGlobalConfig(ctx)
@@ -767,8 +806,12 @@
 	image.installs = rule.Installs()
 	image.vdexInstalls = vdexInstalls
 	image.unstrippedInstalls = unstrippedInstalls
-	image.deviceInstalls = deviceInstalls
 	image.licenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
+
+	return bootImageVariantOutputs{
+		image,
+		deviceInstalls,
+	}
 }
 
 const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -824,8 +867,6 @@
 
 	rule.Build("bootJarsProfile", "profile boot jars")
 
-	image.profilePathOnHost = profile
-
 	return profile
 }
 
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index 24f8253..f0de7a4 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -436,10 +436,10 @@
 	profile := bootImageProfileRule(ctx, imageConfig)
 
 	// Build boot image files for the android variants.
-	androidBootImageFilesByArch := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
+	androidBootImageFiles := buildBootImageVariantsForAndroidOs(ctx, imageConfig, profile)
 
 	// Zip the android variant boot image files up.
-	buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFilesByArch)
+	buildBootImageZipInPredefinedLocation(ctx, imageConfig, androidBootImageFiles.byArch)
 
 	// Build boot image files for the host variants. There are use directly by ART host side tests.
 	buildBootImageVariantsForBuildOs(ctx, imageConfig, profile)