From 8cf899afcc69643f63350bc9f9f92677bb8feabd Mon Sep 17 00:00:00 2001 From: Artur Satayev Date: Wed, 15 Apr 2020 17:29:42 +0100 Subject: [PATCH] Ensure APEX's Java deps use stable SDKs. Test: m Bug: 153333044 Change-Id: Ib1acf3073e96fe23c92d292ec0b1a91e2cd408db --- apex/apex.go | 20 +++++++- apex/apex_test.go | 119 ++++++++++++++++++++++++++++++++++++++++++++++ java/java.go | 8 ++++ java/sdk.go | 5 +- 4 files changed, 150 insertions(+), 2 deletions(-) diff --git a/apex/apex.go b/apex/apex.go index 39968abdc..b5af34254 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1856,6 +1856,8 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) { if String(a.properties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well") } + + a.checkJavaStableSdkVersion(ctx) } } @@ -1925,7 +1927,6 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.checkApexAvailability(ctx) a.checkUpdatable(ctx) - a.collectDepsInfo(ctx) handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case) @@ -2239,6 +2240,23 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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 c4ab0be64..ef1fe7490 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -1403,6 +1403,122 @@ func TestInvalidMinSdkVersion(t *testing.T) { `) } +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 { @@ -4441,6 +4557,7 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { java_library { name: "some-updatable-apex-lib", srcs: ["a.java"], + sdk_version: "current", apex_available: [ "some-updatable-apex", ], @@ -4457,12 +4574,14 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { 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 38f485e88..6739f69f3 100644 --- a/java/java.go +++ b/java/java.go @@ -86,6 +86,14 @@ func RegisterJavaBuildComponents(ctx android.RegistrationContext) { 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 92076f4b5..690451c60 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -169,9 +169,12 @@ func (s sdkSpec) stable() bool { 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))