Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 81e46817 authored by Jiakai Zhang's avatar Jiakai Zhang
Browse files

Use the profiles in the APEX to dexpreopt system server jars.

After this change, if "profile_guided: true" is set, profile-guided
compilation will be enabled for the jar and the ".prof" file next to
the jar in the APEX ("javalib/<name>.jar.prof") will be used as the
profile when dexpreopting for the prebuilt APEX.

Bug: 241823638
Test: m nothing
Test: -
  1. (on internal master) Patch aosp/2426453.
  2. Build the APEX bundle and the module SDK of com.android.wifi
  3. (on tm-dev) Patch this CL and aosp/2141972.
  4. Copy the APEX bundle and the module SDK built on step 2 to the
     source tree
  5. Disable hiddenapi check
  6. lunch cf_x86_64_phone-userdebug && m MODULE_BUILD_FROM_SOURCE=false com.google.android.wifi
  7. cat out/soong/.intermediates/prebuilts/module_sdk/Wifi/current/prebuilt_service-wifi/android_common_com.android.wifi/dexpreopt/oat/x86_64/javalib.invocation
  8. See the profile being used.
Change-Id: I55a5a295e9c5d6f0564afb139c5fb7da91ab8cae
parent 1f4542c8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1769,7 +1769,7 @@ func apexFileForJavaModuleWithFile(ctx android.BaseModuleContext, module javaMod

func apexFileForJavaModuleProfile(ctx android.BaseModuleContext, module javaModule) *apexFile {
	if dexpreopter, ok := module.(java.DexpreopterInterface); ok {
		if profilePathOnHost := dexpreopter.ProfilePathOnHost(); profilePathOnHost != nil {
		if profilePathOnHost := dexpreopter.OutputProfilePathOnHost(); profilePathOnHost != nil {
			dirInApex := "javalib"
			af := newApexFile(ctx, profilePathOnHost, module.BaseModuleName()+"-profile", dirInApex, etc, nil)
			af.customStem = module.Stem() + ".jar.prof"
+53 −5
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForTestWithSystemserverclasspathFragment,
		prepareForTestWithMyapex,
		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
		dexpreopt.FixtureSetApexSystemServerJars("myapex:foo", "myapex:bar"),
	).RunTestWithBp(t, `
		prebuilt_apex {
			name: "myapex",
@@ -245,11 +245,23 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
			],
		}

		java_import {
			name: "bar",
			jars: ["bar.jar"],
			dex_preopt: {
				profile_guided: true,
			},
			apex_available: [
				"myapex",
			],
		}

		prebuilt_systemserverclasspath_fragment {
			name: "mysystemserverclasspathfragment",
			prefer: true,
			contents: [
				"foo",
				"bar",
			],
			apex_available: [
				"myapex",
@@ -257,15 +269,27 @@ func TestPrebuiltSystemserverclasspathFragmentContents(t *testing.T) {
		}
	`)

	java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
	ctx := result.TestContext

	java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
		`myapex.apex.selector`,
		`prebuilt_mysystemserverclasspathfragment`,
	})

	java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{
	java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
		`myapex.deapexer`,
		`prebuilt_bar`,
		`prebuilt_foo`,
	})

	ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
		"javalib/foo.jar",
		"javalib/bar.jar",
		"javalib/bar.jar.prof",
	})

	assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
	assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
}

func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
@@ -354,7 +378,7 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForTestWithSystemserverclasspathFragment,
		prepareForTestWithMyapex,
		dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo"),
		dexpreopt.FixtureSetApexStandaloneSystemServerJars("myapex:foo", "myapex:bar"),
	).RunTestWithBp(t, `
		prebuilt_apex {
			name: "myapex",
@@ -377,11 +401,23 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
			],
		}

		java_import {
			name: "bar",
			jars: ["bar.jar"],
			dex_preopt: {
				profile_guided: true,
			},
			apex_available: [
				"myapex",
			],
		}

		prebuilt_systemserverclasspath_fragment {
			name: "mysystemserverclasspathfragment",
			prefer: true,
			standalone_contents: [
				"foo",
				"bar",
			],
			apex_available: [
				"myapex",
@@ -389,10 +425,22 @@ func TestPrebuiltStandaloneSystemserverclasspathFragmentContents(t *testing.T) {
		}
	`)

	java.CheckModuleDependencies(t, result.TestContext, "mysystemserverclasspathfragment", "android_common_myapex", []string{
	ctx := result.TestContext

	java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
		`myapex.deapexer`,
		`prebuilt_bar`,
		`prebuilt_foo`,
	})

	ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
		"javalib/foo.jar",
		"javalib/bar.jar",
		"javalib/bar.jar.prof",
	})

	assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
	assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
}

func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
+28 −8
Original line number Diff line number Diff line
@@ -23,11 +23,24 @@ import (
)

type DexpreopterInterface interface {
	IsInstallable() bool // Structs that embed dexpreopter must implement this.
	// True if the java module is to be dexed and installed on devices.
	// Structs that embed dexpreopter must implement this.
	IsInstallable() bool

	// True if dexpreopt is disabled for the java module.
	dexpreoptDisabled(ctx android.BaseModuleContext) bool

	// If the java module is to be installed into an APEX, this list contains information about the
	// dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed
	// outside of the APEX.
	DexpreoptBuiltInstalledForApex() []dexpreopterInstall

	// The Make entries to install the dexpreopt outputs. Derived from
	// `DexpreoptBuiltInstalledForApex`.
	AndroidMkEntriesForApex() []android.AndroidMkEntries
	ProfilePathOnHost() android.Path

	// See `dexpreopter.outputProfilePathOnHost`.
	OutputProfilePathOnHost() android.Path
}

type dexpreopterInstall struct {
@@ -106,8 +119,13 @@ type dexpreopter struct {
	//   dexpreopt another partition).
	configPath android.WritablePath

	// The path to the profile on host.
	profilePathOnHost android.Path
	// The path to the profile on host that dexpreopter generates. This is used as the input for
	// dex2oat.
	outputProfilePathOnHost android.Path

	// The path to the profile that dexpreopter accepts. It must be in the binary format. If this is
	// set, it overrides the profile settings in `dexpreoptProperties`.
	inputProfilePathOnHost android.Path
}

type DexpreoptProperties struct {
@@ -308,7 +326,9 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
	var profileClassListing android.OptionalPath
	var profileBootListing android.OptionalPath
	profileIsTextListing := false
	if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) {
	if d.inputProfilePathOnHost != nil {
		profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
	} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
		// If dex_preopt.profile_guided is not set, default it based on the existence of the
		// dexprepot.profile option or the profile class listing.
		if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" {
@@ -389,7 +409,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Wr
		isProfile := strings.HasSuffix(installBase, ".prof")

		if isProfile {
			d.profilePathOnHost = install.From
			d.outputProfilePathOnHost = install.From
		}

		if isApexSystemServerJar {
@@ -431,6 +451,6 @@ func (d *dexpreopter) AndroidMkEntriesForApex() []android.AndroidMkEntries {
	return entries
}

func (d *dexpreopter) ProfilePathOnHost() android.Path {
	return d.profilePathOnHost
func (d *dexpreopter) OutputProfilePathOnHost() android.Path {
	return d.outputProfilePathOnHost
}
+16 −5
Original line number Diff line number Diff line
@@ -2002,7 +2002,8 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
			if di == nil {
				return // An error has been reported by FindDeapexerProviderForModule.
			}
			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(j.BaseModuleName())); dexOutputPath != nil {
			dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName())
			if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
				dexJarFile := makeDexJarPathFromPath(dexOutputPath)
				j.dexJarFile = dexJarFile
				installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
@@ -2011,6 +2012,11 @@ func (j *Import) GenerateAndroidBuildActions(ctx android.ModuleContext) {
				j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
				setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
				j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex

				if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
					j.dexpreopter.inputProfilePathOnHost = profilePath
				}

				j.dexpreopt(ctx, dexOutputPath)

				// Initialize the hiddenapi structure.
@@ -2145,11 +2151,16 @@ func (j *Import) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
// requiredFilesFromPrebuiltApexForImport returns information about the files that a java_import or
// java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set.
func requiredFilesFromPrebuiltApexForImport(name string) []string {
func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string {
	dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name)
	// Add the dex implementation jar to the set of exported files.
	return []string{
		apexRootRelativePathToJavaLib(name),
	files := []string{
		dexJarFileApexRootRelative,
	}
	if BoolDefault(d.importDexpreoptProperties.Dex_preopt.Profile_guided, false) {
		files = append(files, dexJarFileApexRootRelative+".prof")
	}
	return files
}

// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
@@ -2162,7 +2173,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*Import)(nil)

func (j *Import) RequiredFilesFromPrebuiltApex(_ android.BaseModuleContext) []string {
	name := j.BaseModuleName()
	return requiredFilesFromPrebuiltApexForImport(name)
	return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
}

// Add compile time check for interface implementation
+10 −4
Original line number Diff line number Diff line
@@ -2445,18 +2445,24 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
			if di == nil {
				return // An error has been reported by FindDeapexerProviderForModule.
			}
			if dexOutputPath := di.PrebuiltExportPath(apexRootRelativePathToJavaLib(module.BaseModuleName())); dexOutputPath != nil {
			dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName())
			if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
				dexJarFile := makeDexJarPathFromPath(dexOutputPath)
				module.dexJarFile = dexJarFile
				installPath := android.PathForModuleInPartitionInstall(
					ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(module.BaseModuleName()))
					ctx, "apex", ai.ApexVariationName, dexJarFileApexRootRelative)
				module.installFile = installPath
				module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)

				// Dexpreopting.
				module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath)
				module.dexpreopter.isSDKLibrary = true
				module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter)

				if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
					module.dexpreopter.inputProfilePathOnHost = profilePath
				}

				// Dexpreopting.
				module.dexpreopt(ctx, dexOutputPath)
			} else {
				// This should never happen as a variant for a prebuilt_apex is only created if the
@@ -2585,7 +2591,7 @@ var _ android.RequiredFilesFromPrebuiltApex = (*SdkLibraryImport)(nil)

func (module *SdkLibraryImport) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
	name := module.BaseModuleName()
	return requiredFilesFromPrebuiltApexForImport(name)
	return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
}

// java_sdk_library_xml