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

Commit 6cb124b8 authored by Jingwen Chen's avatar Jingwen Chen
Browse files

Append APEX version instead of build ID for APK-in-APEX paths.

This CL removes the build_id.mk suffix and replaces it with a hardcoded
placeholder string that will be replaced with the actual version in
apex_manifest.json by apexer at apex construction time.

This means that as long as the apex version is incremented, the
APK-in-APEX will be installed to a new directory path from the package
manager's perspective.

Fixes: 229574810
Bug: 229625490
Bug: 226559955
Bug: 224589412
Bug: 227417611
Bug: 228157333
Bug: 228803590
Bug: 229136249

Test: atest StrictJavaPackagesTest
Test: soong tests
Test: deapexer list out/dist/com.google.android.permission.apex
Change-Id: I9cef1418c3fc7e0970d96995b8398f5e82f479e0
parent 3a5be76d
Loading
Loading
Loading
Loading
+3 −17
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package apex
import (
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

@@ -1657,20 +1656,7 @@ type androidApp interface {
var _ androidApp = (*java.AndroidApp)(nil)
var _ androidApp = (*java.AndroidAppImport)(nil)

func sanitizedBuildIdForPath(ctx android.BaseModuleContext) string {
	buildId := ctx.Config().BuildId()

	// The build ID is used as a suffix for a filename, so ensure that
	// the set of characters being used are sanitized.
	// - any word character: [a-zA-Z0-9_]
	// - dots: .
	// - dashes: -
	validRegex := regexp.MustCompile(`^[\w\.\-\_]+$`)
	if !validRegex.MatchString(buildId) {
		ctx.ModuleErrorf("Unable to use build id %s as filename suffix, valid characters are [a-z A-Z 0-9 _ . -].", buildId)
	}
	return buildId
}
const APEX_VERSION_PLACEHOLDER = "__APEX_VERSION_PLACEHOLDER__"

func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile {
	appDir := "app"
@@ -1681,7 +1667,7 @@ func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexF
	// TODO(b/224589412, b/226559955): Ensure that the subdirname is suffixed
	// so that PackageManager correctly invalidates the existing installed apk
	// in favour of the new APK-in-APEX.  See bugs for more information.
	dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+sanitizedBuildIdForPath(ctx))
	dirInApex := filepath.Join(appDir, aapp.InstallApkName()+"@"+APEX_VERSION_PLACEHOLDER)
	fileToCopy := aapp.OutputFile()

	af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
@@ -1920,7 +1906,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
					// suffixed so that PackageManager correctly invalidates the
					// existing installed apk in favour of the new APK-in-APEX.
					// See bugs for more information.
					appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+sanitizedBuildIdForPath(ctx))
					appDirName := filepath.Join(appDir, ap.BaseModuleName()+"@"+APEX_VERSION_PLACEHOLDER)
					af := newApexFile(ctx, ap.OutputFile(), ap.BaseModuleName(), appDirName, appSet, ap)
					af.certificate = java.PresignedCertificate
					filesInfo = append(filesInfo, af)
+13 −44
Original line number Diff line number Diff line
@@ -223,7 +223,6 @@ var prepareForApexTest = android.GroupFixturePreparers(
		// not because of these tests specifically (it's not used by the tests)
		variables.Platform_version_active_codenames = []string{"Q", "Tiramisu"}
		variables.Platform_vndk_version = proptools.StringPtr("29")
		variables.BuildId = proptools.StringPtr("TEST.BUILD_ID")
	}),
)

@@ -683,7 +682,7 @@ func TestDefaults(t *testing.T) {
		"etc/myetc",
		"javalib/myjar.jar",
		"lib64/mylib.so",
		"app/AppFoo@TEST.BUILD_ID/AppFoo.apk",
		"app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk",
		"overlay/blue/rro.apk",
		"etc/bpf/bpf.o",
		"etc/bpf/bpf2.o",
@@ -5683,8 +5682,8 @@ func TestApexWithApps(t *testing.T) {
	apexRule := module.Rule("apexRule")
	copyCmds := apexRule.Args["copy_commands"]

	ensureContains(t, copyCmds, "image.apex/app/AppFoo@TEST.BUILD_ID/AppFoo.apk")
	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@TEST.BUILD_ID/AppFooPriv.apk")
	ensureContains(t, copyCmds, "image.apex/app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk")
	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@__APEX_VERSION_PLACEHOLDER__/AppFooPriv.apk")

	appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
	// JNI libraries are uncompressed
@@ -5701,36 +5700,6 @@ func TestApexWithApps(t *testing.T) {
	}
}

func TestApexWithAppImportBuildId(t *testing.T) {
	invalidBuildIds := []string{"../", "a b", "a/b", "a/b/../c", "/a"}
	for _, id := range invalidBuildIds {
		message := fmt.Sprintf("Unable to use build id %s as filename suffix", id)
		fixture := android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
			variables.BuildId = proptools.StringPtr(id)
		})
		testApexError(t, message, `apex {
			name: "myapex",
			key: "myapex.key",
			apps: ["AppFooPrebuilt"],
			updatable: false,
		}

		apex_key {
			name: "myapex.key",
			public_key: "testkey.avbpubkey",
			private_key: "testkey.pem",
		}

		android_app_import {
			name: "AppFooPrebuilt",
			apk: "PrebuiltAppFoo.apk",
			presigned: true,
			apex_available: ["myapex"],
		}
	`, fixture)
	}
}

func TestApexWithAppImports(t *testing.T) {
	ctx := testApex(t, `
		apex {
@@ -5776,8 +5745,8 @@ func TestApexWithAppImports(t *testing.T) {
	apexRule := module.Rule("apexRule")
	copyCmds := apexRule.Args["copy_commands"]

	ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt@TEST.BUILD_ID/AppFooPrebuilt.apk")
	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt@TEST.BUILD_ID/AwesomePrebuiltAppFooPriv.apk")
	ensureContains(t, copyCmds, "image.apex/app/AppFooPrebuilt@__APEX_VERSION_PLACEHOLDER__/AppFooPrebuilt.apk")
	ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPrivPrebuilt@__APEX_VERSION_PLACEHOLDER__/AwesomePrebuiltAppFooPriv.apk")
}

func TestApexWithAppImportsPrefer(t *testing.T) {
@@ -5818,7 +5787,7 @@ func TestApexWithAppImportsPrefer(t *testing.T) {
	}))

	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
		"app/AppFoo@TEST.BUILD_ID/AppFooPrebuilt.apk",
		"app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFooPrebuilt.apk",
	})
}

@@ -5851,7 +5820,7 @@ func TestApexWithTestHelperApp(t *testing.T) {
	apexRule := module.Rule("apexRule")
	copyCmds := apexRule.Args["copy_commands"]

	ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo@TEST.BUILD_ID/TesterHelpAppFoo.apk")
	ensureContains(t, copyCmds, "image.apex/app/TesterHelpAppFoo@__APEX_VERSION_PLACEHOLDER__/TesterHelpAppFoo.apk")
}

func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
@@ -6294,8 +6263,8 @@ func TestOverrideApex(t *testing.T) {
	apexRule := module.Rule("apexRule")
	copyCmds := apexRule.Args["copy_commands"]

	ensureNotContains(t, copyCmds, "image.apex/app/app@TEST.BUILD_ID/app.apk")
	ensureContains(t, copyCmds, "image.apex/app/override_app@TEST.BUILD_ID/override_app.apk")
	ensureNotContains(t, copyCmds, "image.apex/app/app@__APEX_VERSION_PLACEHOLDER__/app.apk")
	ensureContains(t, copyCmds, "image.apex/app/override_app@__APEX_VERSION_PLACEHOLDER__/override_app.apk")

	ensureNotContains(t, copyCmds, "image.apex/etc/bpf/bpf.o")
	ensureContains(t, copyCmds, "image.apex/etc/bpf/override_bpf.o")
@@ -7199,7 +7168,7 @@ func TestAppBundle(t *testing.T) {
	content := bundleConfigRule.Args["content"]

	ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
	ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo@TEST.BUILD_ID/AppFoo.apk"}]}`)
	ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo@__APEX_VERSION_PLACEHOLDER__/AppFoo.apk"}]}`)
}

func TestAppSetBundle(t *testing.T) {
@@ -7230,9 +7199,9 @@ func TestAppSetBundle(t *testing.T) {
	if len(copyCmds) != 3 {
		t.Fatalf("Expected 3 commands, got %d in:\n%s", len(copyCmds), s)
	}
	ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@TEST.BUILD_ID$")
	ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@TEST.BUILD_ID$")
	ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@TEST.BUILD_ID .*/AppSet.zip$")
	ensureMatches(t, copyCmds[0], "^rm -rf .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__$")
	ensureMatches(t, copyCmds[1], "^mkdir -p .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__$")
	ensureMatches(t, copyCmds[2], "^unzip .*-d .*/app/AppSet@__APEX_VERSION_PLACEHOLDER__ .*/AppSet.zip$")
}

func TestAppSetBundlePrebuilt(t *testing.T) {
+20 −15
Original line number Diff line number Diff line
@@ -107,14 +107,16 @@ var (
			`--canned_fs_config ${canned_fs_config} ` +
			`--include_build_info ` +
			`--payload_type image ` +
			`--key ${key} ${opt_flags} ${image_dir} ${out} `,
			`--key ${key} ` +
			`--apex_version_placeholder ${apex_version_placeholder} ` +
			`${opt_flags} ${image_dir} ${out} `,
		CommandDeps: []string{"${apexer}", "${avbtool}", "${e2fsdroid}", "${merge_zips}",
			"${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}", "${sload_f2fs}", "${make_erofs}",
			"${soong_zip}", "${zipalign}", "${aapt2}", "prebuilts/sdk/current/public/android.jar"},
		Rspfile:        "${out}.copy_commands",
		RspfileContent: "${copy_commands}",
		Description:    "APEX ${image_dir} => ${out}",
	}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type")
	}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type", "apex_version_placeholder")

	zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
@@ -122,12 +124,13 @@ var (
			`APEXER_TOOL_PATH=${tool_path} ` +
			`${apexer} --force --manifest ${manifest} ` +
			`--payload_type zip ` +
			`--apex_version_placeholder ${apex_version_placeholder} ` +
			`${image_dir} ${out} `,
		CommandDeps:    []string{"${apexer}", "${merge_zips}", "${soong_zip}", "${zipalign}", "${aapt2}"},
		Rspfile:        "${out}.copy_commands",
		RspfileContent: "${copy_commands}",
		Description:    "ZipAPEX ${image_dir} => ${out}",
	}, "tool_path", "image_dir", "copy_commands", "manifest")
	}, "tool_path", "image_dir", "copy_commands", "manifest", "apex_version_placeholder")

	apexProtoConvertRule = pctx.AndroidStaticRule("apexProtoConvertRule",
		blueprint.RuleParams{
@@ -666,6 +669,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
				"canned_fs_config":         cannedFsConfig.String(),
				"key":                      a.privateKeyFile.String(),
				"opt_flags":                strings.Join(optFlags, " "),
				"apex_version_placeholder": APEX_VERSION_PLACEHOLDER,
			},
		})

@@ -761,6 +765,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
				"image_dir":                imageDir.String(),
				"copy_commands":            strings.Join(copyCommands, " && "),
				"manifest":                 a.manifestPbOut.String(),
				"apex_version_placeholder": APEX_VERSION_PLACEHOLDER,
			},
		})
	}