Export provenance metadata for prebuilt APKs and APEXes.
Bug: 217434690
Test: atest --host gen_provenance_metadata_test
Test: m provenance_metadata
Change-Id: I91c184b6e6fe5ccfc3fc65b55b09e7a3da9502a0
diff --git a/java/Android.bp b/java/Android.bp
index 4bcae4f..df0d1eb 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -15,6 +15,7 @@
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-provenance",
"soong-python",
"soong-remoteexec",
"soong-tradefed",
diff --git a/java/app_import.go b/java/app_import.go
index 3e5f972..a1c4d58 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -22,6 +22,7 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/provenance"
)
func init() {
@@ -57,6 +58,8 @@
installPath android.InstallPath
hideApexVariantFromMake bool
+
+ provenanceMetaDataFile android.OutputPath
}
type AndroidAppImportProperties struct {
@@ -343,6 +346,8 @@
if apexInfo.IsForPlatform() {
a.installPath = ctx.InstallFile(installDir, apkFilename, a.outputFile)
+ artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
+ a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
// TODO: androidmk converter jni libs
@@ -368,6 +373,10 @@
return a.certificate
}
+func (a *AndroidAppImport) ProvenanceMetaDataFile() android.OutputPath {
+ return a.provenanceMetaDataFile
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
diff --git a/java/app_import_test.go b/java/app_import_test.go
index efa52c1..8f6c75f 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -53,6 +53,11 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_NoDexPreopt(t *testing.T) {
@@ -74,6 +79,12 @@
variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_Presigned(t *testing.T) {
@@ -102,6 +113,12 @@
if variant.MaybeOutput("zip-aligned/foo.apk").Rule == nil {
t.Errorf("can't find aligning rule")
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineage(t *testing.T) {
@@ -137,6 +154,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_SigningLineageFilegroup(t *testing.T) {
@@ -163,6 +186,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DefaultDevCert(t *testing.T) {
@@ -192,6 +221,12 @@
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
+
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", "prebuilts/apk/app.apk", rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", rule.Args["install_path"])
}
func TestAndroidAppImport_DpiVariants(t *testing.T) {
@@ -214,40 +249,46 @@
}
`
testCases := []struct {
- name string
- aaptPreferredConfig *string
- aaptPrebuiltDPI []string
- expected string
+ name string
+ aaptPreferredConfig *string
+ aaptPrebuiltDPI []string
+ expected string
+ expectedProvenanceMetaDataArtifactPath string
}{
{
- name: "no preferred",
- aaptPreferredConfig: nil,
- aaptPrebuiltDPI: []string{},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no preferred",
+ aaptPreferredConfig: nil,
+ aaptPrebuiltDPI: []string{},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
{
- name: "AAPTPreferredConfig matches",
- aaptPreferredConfig: proptools.StringPtr("xhdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "AAPTPreferredConfig matches",
+ aaptPreferredConfig: proptools.StringPtr("xhdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ name: "AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"xxhdpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xxhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xxhdpi.apk",
},
{
- name: "non-first AAPTPrebuiltDPI matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
- expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ name: "non-first AAPTPrebuiltDPI matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xhdpi"},
+ expected: "verify_uses_libraries/apk/app_xhdpi.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app_xhdpi.apk",
},
{
- name: "no matches",
- aaptPreferredConfig: proptools.StringPtr("mdpi"),
- aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
- expected: "verify_uses_libraries/apk/app.apk",
+ name: "no matches",
+ aaptPreferredConfig: proptools.StringPtr("mdpi"),
+ aaptPrebuiltDPI: []string{"ldpi", "xxxhdpi"},
+ expected: "verify_uses_libraries/apk/app.apk",
+ expectedProvenanceMetaDataArtifactPath: "prebuilts/apk/app.apk",
},
}
@@ -270,6 +311,12 @@
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+
+ provenanceMetaDataRule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedProvenanceMetaDataArtifactPath, provenanceMetaDataRule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", provenanceMetaDataRule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", provenanceMetaDataRule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", "/system/app/foo/foo.apk", provenanceMetaDataRule.Args["install_path"])
}
}
@@ -290,16 +337,25 @@
`)
testCases := []struct {
- name string
- expected string
+ name string
+ expected string
+ onDevice string
+ expectedArtifactPath string
+ expectedMetaDataPath string
}{
{
- name: "foo",
- expected: "foo.apk",
+ name: "foo",
+ expected: "foo.apk",
+ onDevice: "/system/app/foo/foo.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto",
},
{
- name: "bar",
- expected: "bar_sample.apk",
+ name: "bar",
+ expected: "bar_sample.apk",
+ onDevice: "/system/app/bar/bar_sample.apk",
+ expectedArtifactPath: "prebuilts/apk/app.apk",
+ expectedMetaDataPath: "out/soong/.intermediates/provenance_metadata/bar/provenance_metadata.textproto",
},
}
@@ -316,15 +372,23 @@
t.Errorf("Incorrect LOCAL_INSTALLED_MODULE_STEM value '%s', expected '%s'",
actualValues, expectedValues)
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.expectedArtifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", test.expectedMetaDataPath, rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", test.name, rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.onDevice, rule.Args["install_path"])
}
}
func TestAndroidAppImport_ArchVariants(t *testing.T) {
// The test config's target arch is ARM64.
testCases := []struct {
- name string
- bp string
- expected string
+ name string
+ bp string
+ expected string
+ artifactPath string
+ metaDataPath string
+ installPath string
}{
{
name: "matching arch",
@@ -343,7 +407,9 @@
},
}
`,
- expected: "verify_uses_libraries/apk/app_arm64.apk",
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
+ artifactPath: "prebuilts/apk/app_arm64.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch",
@@ -362,7 +428,9 @@
},
}
`,
- expected: "verify_uses_libraries/apk/app.apk",
+ expected: "verify_uses_libraries/apk/app.apk",
+ artifactPath: "prebuilts/apk/app.apk",
+ installPath: "/system/app/foo/foo.apk",
},
{
name: "no matching arch without default",
@@ -380,7 +448,9 @@
},
}
`,
- expected: "",
+ expected: "",
+ artifactPath: "prebuilts/apk/app_arm.apk",
+ installPath: "/system/app/foo/foo.apk",
},
}
@@ -393,6 +463,8 @@
if variant.Module().Enabled() {
t.Error("module should have been disabled, but wasn't")
}
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
continue
}
jniRuleCommand := variant.Output("jnis-uncompressed/foo.apk").RuleParams.Command
@@ -403,6 +475,11 @@
if strings.HasSuffix(matches[1], test.expected) {
t.Errorf("wrong src apk, expected: %q got: %q", test.expected, matches[1])
}
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
}
}