Ensure APEX's Java deps use stable SDKs.
Test: m
Bug: 153333044
Change-Id: Ib1acf3073e96fe23c92d292ec0b1a91e2cd408db
Merged-In: Ib1acf3073e96fe23c92d292ec0b1a91e2cd408db
Exempt-From-Owner-Approval: cp from aosp
(cherry picked from commit 8cf899afcc69643f63350bc9f9f92677bb8feabd)
diff --git a/apex/apex.go b/apex/apex.go
index 6a0c4c1..7191365 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1871,6 +1871,8 @@
if String(a.properties.Min_sdk_version) == "" {
ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
}
+
+ a.checkJavaStableSdkVersion(ctx)
}
}
@@ -1940,7 +1942,6 @@
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
-
a.collectDepsInfo(ctx)
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
@@ -2247,6 +2248,23 @@
a.buildApexDependencyInfo(ctx)
}
+// Enforce that Java deps of the apex are using stable SDKs to compile
+func (a *apexBundle) checkJavaStableSdkVersion(ctx android.ModuleContext) {
+ // Visit direct deps only. As long as we guarantee top-level deps are using
+ // stable SDKs, java's checkLinkType guarantees correct usage for transitive deps
+ ctx.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ tag := ctx.OtherModuleDependencyTag(module)
+ switch tag {
+ case javaLibTag, androidAppTag:
+ if m, ok := module.(interface{ CheckStableSdkVersion() error }); ok {
+ if err := m.CheckStableSdkVersion(); err != nil {
+ ctx.ModuleErrorf("cannot depend on \"%v\": %v", ctx.OtherModuleName(module), err)
+ }
+ }
+ }
+ })
+}
+
func whitelistedApexAvailable(apex, moduleName string) bool {
key := apex
moduleName = normalizeModuleName(moduleName)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2618db3..f1d80ae 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1377,6 +1377,122 @@
`)
}
+func TestJavaStableSdkVersion(t *testing.T) {
+ testCases := []struct {
+ name string
+ expectedError string
+ bp string
+ }{
+ {
+ name: "Non-updatable apex with non-stable dep",
+ bp: `
+ apex {
+ name: "myapex",
+ java_libs: ["myjar"],
+ key: "myapex.key",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ java_library {
+ name: "myjar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "core_platform",
+ apex_available: ["myapex"],
+ }
+ `,
+ },
+ {
+ name: "Updatable apex with stable dep",
+ bp: `
+ apex {
+ name: "myapex",
+ java_libs: ["myjar"],
+ key: "myapex.key",
+ updatable: true,
+ min_sdk_version: "29",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ java_library {
+ name: "myjar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "current",
+ apex_available: ["myapex"],
+ }
+ `,
+ },
+ {
+ name: "Updatable apex with non-stable dep",
+ expectedError: "cannot depend on \"myjar\"",
+ bp: `
+ apex {
+ name: "myapex",
+ java_libs: ["myjar"],
+ key: "myapex.key",
+ updatable: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ java_library {
+ name: "myjar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "core_platform",
+ apex_available: ["myapex"],
+ }
+ `,
+ },
+ {
+ name: "Updatable apex with non-stable transitive dep",
+ expectedError: "compiles against Android API, but dependency \"transitive-jar\" is compiling against non-public Android API.",
+ bp: `
+ apex {
+ name: "myapex",
+ java_libs: ["myjar"],
+ key: "myapex.key",
+ updatable: true,
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ java_library {
+ name: "myjar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "current",
+ apex_available: ["myapex"],
+ static_libs: ["transitive-jar"],
+ }
+ java_library {
+ name: "transitive-jar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "core_platform",
+ apex_available: ["myapex"],
+ }
+ `,
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ if test.expectedError == "" {
+ testApex(t, test.bp)
+ } else {
+ testApexError(t, test.expectedError, test.bp)
+ }
+ })
+ }
+}
+
func TestFilesInSubDir(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -4289,6 +4405,7 @@
java_library {
name: "some-updatable-apex-lib",
srcs: ["a.java"],
+ sdk_version: "current",
apex_available: [
"some-updatable-apex",
],
@@ -4297,12 +4414,14 @@
java_library {
name: "some-platform-lib",
srcs: ["a.java"],
+ sdk_version: "current",
installable: true,
}
java_library {
name: "some-art-lib",
srcs: ["a.java"],
+ sdk_version: "current",
apex_available: [
"com.android.art.something",
],
diff --git a/java/java.go b/java/java.go
index 5d77807..6589721 100644
--- a/java/java.go
+++ b/java/java.go
@@ -86,6 +86,14 @@
ctx.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory)
}
+func (j *Module) CheckStableSdkVersion() error {
+ sdkVersion := j.sdkVersion()
+ if sdkVersion.stable() {
+ return nil
+ }
+ return fmt.Errorf("non stable SDK %v", sdkVersion)
+}
+
func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
if j.SocSpecific() || j.DeviceSpecific() ||
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
diff --git a/java/sdk.go b/java/sdk.go
index be5e512..4414600 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -170,9 +170,12 @@
return false
}
switch s.kind {
+ case sdkNone:
+ // there is nothing to manage and version in this case; de facto stable API.
+ return true
case sdkCore, sdkPublic, sdkSystem, sdkModule, sdkSystemServer:
return true
- case sdkNone, sdkCorePlatform, sdkTest, sdkPrivate:
+ case sdkCorePlatform, sdkTest, sdkPrivate:
return false
default:
panic(fmt.Errorf("unknown sdkKind=%v", s.kind))