summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/androidmk.go3
-rw-r--r--java/app_import.go27
-rw-r--r--java/app_import_test.go63
-rw-r--r--java/builder.go11
-rw-r--r--java/dexpreopt_bootjars.go5
-rw-r--r--java/hiddenapi.go22
-rw-r--r--java/hiddenapi_singleton.go62
-rw-r--r--java/hiddenapi_singleton_test.go54
-rw-r--r--java/java.go35
9 files changed, 232 insertions, 50 deletions
diff --git a/java/androidmk.go b/java/androidmk.go
index 21f3012a4..6e7c437ab 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -646,6 +646,9 @@ func (a *AndroidAppImport) AndroidMkEntries() []android.AndroidMkEntries {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", a.dexpreopter.builtInstalled)
}
entries.AddStrings("LOCAL_INSTALLED_MODULE_STEM", a.installPath.Rel())
+ if Bool(a.properties.Export_package_resources) {
+ entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.outputFile)
+ }
},
},
}}
diff --git a/java/app_import.go b/java/app_import.go
index 6f21bfbbf..59eb10a9b 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -92,6 +92,10 @@ type AndroidAppImportProperties struct {
// Optional name for the installed app. If unspecified, it is derived from the module name.
Filename *string
+
+ // If set, create package-export.apk, which other packages can
+ // use to get PRODUCT-agnostic resource data like IDs and type definitions.
+ Export_package_resources *bool
}
func (a *AndroidAppImport) IsInstallable() bool {
@@ -142,13 +146,17 @@ func MergePropertiesFromVariant(ctx android.EarlyModuleContext,
}
}
+func (a *AndroidAppImport) isPrebuiltFrameworkRes() bool {
+ return a.Name() == "prebuilt_framework-res"
+}
+
func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
cert := android.SrcIsModule(String(a.properties.Certificate))
if cert != "" {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
- a.usesLibrary.deps(ctx, true)
+ a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
}
func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
@@ -247,7 +255,12 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
a.uncompressEmbeddedJniLibs(ctx, srcApk, jnisUncompressed.OutputPath)
var installDir android.InstallPath
- if Bool(a.properties.Privileged) {
+
+ if a.isPrebuiltFrameworkRes() {
+ // framework-res.apk is installed as system/framework/framework-res.apk
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ a.preprocessed = true
+ } else if Bool(a.properties.Privileged) {
installDir = android.PathForModuleInstall(ctx, "priv-app", a.BaseModuleName())
} else if ctx.InstallInTestcases() {
installDir = android.PathForModuleInstall(ctx, a.BaseModuleName(), ctx.DeviceConfig().DeviceArch())
@@ -275,7 +288,15 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
// TODO: Handle EXTERNAL
// Sign or align the package if package has not been preprocessed
- if a.preprocessed {
+
+ if a.isPrebuiltFrameworkRes() {
+ a.outputFile = srcApk
+ certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
+ if len(certificates) != 1 {
+ ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
+ }
+ a.certificate = certificates[0]
+ } else if a.preprocessed {
a.outputFile = srcApk
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 344d23b55..d7f69eb36 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -393,6 +393,69 @@ func TestAndroidAppImport_overridesDisabledAndroidApp(t *testing.T) {
}
}
+func TestAndroidAppImport_frameworkRes(t *testing.T) {
+ ctx, config := testJava(t, `
+ android_app_import {
+ name: "framework-res",
+ certificate: "platform",
+ apk: "package-res.apk",
+ prefer: true,
+ export_package_resources: true,
+ // Disable dexpreopt and verify_uses_libraries check as the app
+ // contains no Java code to be dexpreopted.
+ enforce_uses_libs: false,
+ dex_preopt: {
+ enabled: false,
+ },
+ }
+ `)
+
+ mod := ctx.ModuleForTests("prebuilt_framework-res", "android_common").Module()
+ a := mod.(*AndroidAppImport)
+
+ if !a.preprocessed {
+ t.Errorf("prebuilt framework-res is not preprocessed")
+ }
+
+ expectedInstallPath := buildDir + "/target/product/test_device/system/framework/framework-res.apk"
+
+ if a.dexpreopter.installPath.String() != expectedInstallPath {
+ t.Errorf("prebuilt framework-res installed to incorrect location, actual: %s, expected: %s", a.dexpreopter.installPath, expectedInstallPath)
+
+ }
+
+ entries := android.AndroidMkEntriesForTest(t, config, "", mod)[0]
+
+ expectedPath := "."
+ // From apk property above, in the root of the source tree.
+ expectedPrebuiltModuleFile := "package-res.apk"
+ // Verify that the apk is preprocessed: The export package is the same
+ // as the prebuilt.
+ expectedSoongResourceExportPackage := expectedPrebuiltModuleFile
+
+ actualPath := entries.EntryMap["LOCAL_PATH"]
+ actualPrebuiltModuleFile := entries.EntryMap["LOCAL_PREBUILT_MODULE_FILE"]
+ actualSoongResourceExportPackage := entries.EntryMap["LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE"]
+
+ if len(actualPath) != 1 {
+ t.Errorf("LOCAL_PATH incorrect len %d", len(actualPath))
+ } else if actualPath[0] != expectedPath {
+ t.Errorf("LOCAL_PATH mismatch, actual: %s, expected: %s", actualPath[0], expectedPath)
+ }
+
+ if len(actualPrebuiltModuleFile) != 1 {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE incorrect len %d", len(actualPrebuiltModuleFile))
+ } else if actualPrebuiltModuleFile[0] != expectedPrebuiltModuleFile {
+ t.Errorf("LOCAL_PREBUILT_MODULE_FILE mismatch, actual: %s, expected: %s", actualPrebuiltModuleFile[0], expectedPrebuiltModuleFile)
+ }
+
+ if len(actualSoongResourceExportPackage) != 1 {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE incorrect len %d", len(actualSoongResourceExportPackage))
+ } else if actualSoongResourceExportPackage[0] != expectedSoongResourceExportPackage {
+ t.Errorf("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE mismatch, actual: %s, expected: %s", actualSoongResourceExportPackage[0], expectedSoongResourceExportPackage)
+ }
+}
+
func TestAndroidTestImport(t *testing.T) {
ctx, config := testJava(t, `
android_test_import {
diff --git a/java/builder.go b/java/builder.go
index 995160d0e..22a891ae1 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -193,12 +193,19 @@ var (
jarjar = pctx.AndroidStaticRule("jarjar",
blueprint.RuleParams{
- Command: "${config.JavaCmd} ${config.JavaVmFlags}" +
+ Command: "" +
+ // Jarjar doesn't exit with an error when the rules file contains a syntax error,
+ // leading to stale or missing files later in the build. Remove the output file
+ // before running jarjar.
+ "rm -f ${out} && " +
+ "${config.JavaCmd} ${config.JavaVmFlags}" +
// b/146418363 Enable Android specific jarjar transformer to drop compat annotations
// for newly repackaged classes. Dropping @UnsupportedAppUsage on repackaged classes
// avoids adding new hiddenapis after jarjar'ing.
" -DremoveAndroidCompatAnnotations=true" +
- " -jar ${config.JarjarCmd} process $rulesFile $in $out",
+ " -jar ${config.JarjarCmd} process $rulesFile $in $out && " +
+ // Turn a missing output file into a ninja error
+ `[ -e ${out} ] || (echo "Missing output file"; exit 1)`,
CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
},
"rulesFile")
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 2a7eb42dc..86b189558 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -435,6 +435,11 @@ func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonC
// Inspect this module to see if it contains a bootclasspath dex jar.
// Note that the same jar may occur in multiple modules.
// This logic is tested in the apex package to avoid import cycle apex <-> java.
+//
+// This is similar to logic in isModuleInConfiguredList() so any changes needed here are likely to
+// be needed there too.
+//
+// TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it.
func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) {
name := ctx.ModuleName(module)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index eafbf5df0..ada11c341 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -108,9 +108,18 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bo
// not on the list then that will cause failures in the CtsHiddenApiBlacklist...
// tests.
if inList(bootJarName, ctx.Config().BootJars()) {
- // Create ninja rules to generate various CSV files needed by hiddenapi and store the paths
- // in the hiddenAPI structure.
- h.hiddenAPIGenerateCSV(ctx, implementationJar)
+ // More than one library with the same classes may need to be encoded but only one should be
+ // used as a source of information for hidden API processing otherwise it will result in
+ // duplicate entries in the files.
+ if primary {
+ // Create ninja rules to generate various CSV files needed by hiddenapi and store the paths
+ // in the hiddenAPI structure.
+ h.hiddenAPIGenerateCSV(ctx, implementationJar)
+
+ // Save the unencoded dex jar so it can be used when generating the
+ // hiddenAPISingletonPathsStruct.stubFlags file.
+ h.bootDexJarPath = dexJar
+ }
// If this module is actually on the boot jars list and not providing
// hiddenapi information for a module on the boot jars list then encode
@@ -118,13 +127,6 @@ func (h *hiddenAPI) hiddenAPI(ctx android.ModuleContext, name string, primary bo
if name == bootJarName {
hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", name+".jar").OutputPath
- // More than one library with the same classes can be encoded but only one can
- // be added to the global set of flags, otherwise it will result in duplicate
- // classes which is an error. Therefore, only add the dex jar of one of them
- // to the global set of flags.
- if primary {
- h.bootDexJarPath = dexJar
- }
hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
dexJar = hiddenAPIJar
}
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index ccb874506..46994c396 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -22,9 +22,13 @@ import (
)
func init() {
- android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
- android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
- android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
+ RegisterHiddenApiSingletonComponents(android.InitRegistrationContext)
+}
+
+func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) {
+ ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ ctx.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory)
+ ctx.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory)
}
type hiddenAPISingletonPathsStruct struct {
@@ -213,6 +217,10 @@ func stubFlagsRule(ctx android.SingletonContext) {
var bootDexJars android.Paths
+ // Get the configured non-updatable and updatable boot jars.
+ nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars()
+ updatableBootJars := ctx.Config().UpdatableBootJars()
+
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
if j, ok := module.(Dependency); ok {
@@ -227,11 +235,8 @@ func stubFlagsRule(ctx android.SingletonContext) {
// Collect dex jar paths for modules that had hiddenapi encode called on them.
if h, ok := module.(hiddenAPIIntf); ok {
if jar := h.bootDexJar(); jar != nil {
- // For a java lib included in an APEX, only take the one built for
- // the platform variant, and skip the variants for APEXes.
- // Otherwise, the hiddenapi tool will complain about duplicated classes
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
+ if !isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) &&
+ !isModuleInConfiguredList(ctx, module, updatableBootJars) {
return
}
@@ -280,6 +285,47 @@ func stubFlagsRule(ctx android.SingletonContext) {
rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags")
}
+// Checks to see whether the supplied module variant is in the list of boot jars.
+//
+// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed
+// there too.
+//
+// TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it.
+func isModuleInConfiguredList(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
+ name := ctx.ModuleName(module)
+
+ // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
+ name = android.RemoveOptionalPrebuiltPrefix(name)
+
+ // Ignore any module that is not listed in the boot image configuration.
+ index := configuredBootJars.IndexOfJar(name)
+ if index == -1 {
+ return false
+ }
+
+ // It is an error if the module is not an ApexModule.
+ if _, ok := module.(android.ApexModule); !ok {
+ ctx.Errorf("module %q configured in boot jars does not support being added to an apex", module)
+ return false
+ }
+
+ apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+
+ // Now match the apex part of the boot image configuration.
+ requiredApex := configuredBootJars.Apex(index)
+ if requiredApex == "platform" {
+ if len(apexInfo.InApexes) != 0 {
+ // A platform variant is required but this is for an apex so ignore it.
+ return false
+ }
+ } else if !apexInfo.InApexByBaseName(requiredApex) {
+ // An apex variant for a specific apex is required but this is the wrong apex.
+ return false
+ }
+
+ return true
+}
+
func prebuiltFlagsRule(ctx android.SingletonContext) android.Path {
outputPath := hiddenAPISingletonPaths(ctx).flags
inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv")
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 27f363e0c..fcaa94adc 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -15,11 +15,12 @@
package java
import (
- "android/soong/android"
"fmt"
"strings"
"testing"
+ "android/soong/android"
+
"github.com/google/blueprint/proptools"
)
@@ -32,7 +33,7 @@ func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir *
func testContextWithHiddenAPI(config android.Config) *android.TestContext {
ctx := testContext(config)
- ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory)
+ RegisterHiddenApiSingletonComponents(ctx)
return ctx
}
@@ -64,7 +65,7 @@ func TestHiddenAPISingleton(t *testing.T) {
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
@@ -75,6 +76,45 @@ func TestHiddenAPISingleton(t *testing.T) {
}
}
+func checkRuleInputs(t *testing.T, expected string, hiddenAPIRule android.TestingBuildParams) {
+ actual := strings.TrimSpace(strings.Join(android.NormalizePathsForTesting(hiddenAPIRule.Implicits), "\n"))
+ expected = strings.TrimSpace(expected)
+ if actual != expected {
+ t.Errorf("Expected hiddenapi rule inputs:\n%s\nactual inputs:\n%s", expected, actual)
+ }
+}
+
+func TestHiddenAPIIndexSingleton(t *testing.T) {
+ ctx, _ := testHiddenAPIBootJars(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ compile_dex: true,
+ prefer: false,
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+ `, []string{"platform:foo", "platform:bar"}, nil)
+
+ hiddenAPIIndex := ctx.SingletonForTests("hiddenapi_index")
+ indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
+ checkRuleInputs(t, `
+.intermediates/bar/android_common/hiddenapi/index.csv
+.intermediates/foo/android_common/hiddenapi/index.csv
+`,
+ indexRule)
+}
+
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
ctx, _ := testHiddenAPIBootJars(t, `
java_import {
@@ -98,14 +138,14 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) {
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
java_import {
name: "foo",
jars: ["a.jar"],
compile_dex: true,
prefer: false,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
@@ -127,14 +167,14 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) {
name: "foo",
srcs: ["a.java"],
compile_dex: true,
- }
+ }
java_import {
name: "foo",
jars: ["a.jar"],
compile_dex: true,
prefer: true,
- }
+ }
`, []string{"platform:foo"}, nil)
hiddenAPI := ctx.SingletonForTests("hiddenapi")
diff --git a/java/java.go b/java/java.go
index 91944f6e3..bed232b4e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -40,18 +40,21 @@ func init() {
// Register sdk member types.
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
+ // Export implementation classes jar as part of the sdk.
+ exportImplementationClassesJar := func(_ android.SdkMemberContext, j *Library) android.Path {
+ implementationJars := j.ImplementationAndResourcesJars()
+ if len(implementationJars) != 1 {
+ panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
+ }
+ return implementationJars[0]
+ }
+
// Register java implementation libraries for use only in module_exports (not sdk).
android.RegisterSdkMemberType(&librarySdkMemberType{
android.SdkMemberTypeBase{
PropertyName: "java_libs",
},
- func(_ android.SdkMemberContext, j *Library) android.Path {
- implementationJars := j.ImplementationAndResourcesJars()
- if len(implementationJars) != 1 {
- panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
- }
- return implementationJars[0]
- },
+ exportImplementationClassesJar,
sdkSnapshotFilePathForJar,
copyEverythingToSnapshot,
})
@@ -72,19 +75,11 @@ func init() {
PropertyName: "java_boot_libs",
SupportsSdk: true,
},
- func(ctx android.SdkMemberContext, j *Library) android.Path {
- // Java boot libs are only provided in the SDK to provide access to their dex implementation
- // jar for use by dexpreopting and boot jars package check. They do not need to provide an
- // actual implementation jar but the java_import will need a file that exists so just copy an
- // empty file. Any attempt to use that file as a jar will cause a build error.
- return ctx.SnapshotBuilder().EmptyFile()
- },
- func(osPrefix, name string) string {
- // Create a special name for the implementation jar to try and provide some useful information
- // to a developer that attempts to compile against this.
- // TODO(b/175714559): Provide a proper error message in Soong not ninja.
- return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
- },
+ // Temporarily export implementation classes jar for java_boot_libs as it is required for the
+ // hiddenapi processing.
+ // TODO(b/179354495): Revert once hiddenapi processing has been modularized.
+ exportImplementationClassesJar,
+ sdkSnapshotFilePathForJar,
onlyCopyJarToSnapshot,
})