Loading java/app.go +31 −0 Original line number Diff line number Diff line Loading @@ -421,12 +421,43 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if String(a.deviceProperties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") } if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } } a.checkPlatformAPI(ctx) a.checkSdkVersions(ctx) } // If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. // This check is enforced for "updatable" APKs (including APK-in-APEX). // b/155209650: until min_sdk_version is properly supported, use sdk_version instead. // because, sdk_version is overridden by min_sdk_version (if set as smaller) // and linkType is checked with dependencies so we can be sure that the whole dependency tree // will meet the requirements. func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) { // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() ctx.VisitDirectDeps(func(m android.Module) { if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { return } dep, _ := m.(*cc.Module) // The domain of cc.sdk_version is "current" and <number> // We can rely on sdkSpec to convert it to <number> so that "current" is handled // properly regardless of sdk finalization. jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx) if err != nil || minSdkVersion < jniSdkVersion { ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", dep.SdkVersion(), minSdkVersion, ctx.ModuleName()) return } }) } // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { Loading java/app_test.go +121 −0 Original line number Diff line number Diff line Loading @@ -473,6 +473,127 @@ func TestUpdatableApps(t *testing.T) { } } func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "current", jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", system_shared_libs: [], sdk_version: "current", } `) } func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", system_shared_libs: [], sdk_version: "29", } ndk_prebuilt_object { name: "ndk_crtbegin_so.29", sdk_version: "29", } ndk_prebuilt_object { name: "ndk_crtend_so.29", sdk_version: "29", } ` fs := map[string][]byte{ "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil, } ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs)) inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits var crtbeginFound, crtendFound bool for _, input := range inputs { switch input.String() { case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": crtbeginFound = true case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": crtendFound = true } } if !crtbeginFound || !crtendFound { t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29") } } func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", // this APK should support 29 jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", sdk_version: "current", } ` testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp) } func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", // this APK should support 29 jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", shared_libs: ["libbar"], system_shared_libs: [], sdk_version: "27", } cc_library { name: "libbar", stl: "none", system_shared_libs: [], sdk_version: "current", } ` testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp) } func TestResourceDirs(t *testing.T) { testCases := []struct { name string Loading Loading
java/app.go +31 −0 Original line number Diff line number Diff line Loading @@ -421,12 +421,43 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) { if String(a.deviceProperties.Min_sdk_version) == "" { ctx.PropertyErrorf("updatable", "updatable apps must set min_sdk_version.") } if minSdkVersion, err := a.minSdkVersion().effectiveVersion(ctx); err == nil { a.checkJniLibsSdkVersion(ctx, minSdkVersion) } else { ctx.PropertyErrorf("min_sdk_version", "%s", err.Error()) } } a.checkPlatformAPI(ctx) a.checkSdkVersions(ctx) } // If an updatable APK sets min_sdk_version, min_sdk_vesion of JNI libs should match with it. // This check is enforced for "updatable" APKs (including APK-in-APEX). // b/155209650: until min_sdk_version is properly supported, use sdk_version instead. // because, sdk_version is overridden by min_sdk_version (if set as smaller) // and linkType is checked with dependencies so we can be sure that the whole dependency tree // will meet the requirements. func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion sdkVersion) { // It's enough to check direct JNI deps' sdk_version because all transitive deps from JNI deps are checked in cc.checkLinkType() ctx.VisitDirectDeps(func(m android.Module) { if !IsJniDepTag(ctx.OtherModuleDependencyTag(m)) { return } dep, _ := m.(*cc.Module) // The domain of cc.sdk_version is "current" and <number> // We can rely on sdkSpec to convert it to <number> so that "current" is handled // properly regardless of sdk finalization. jniSdkVersion, err := sdkSpecFrom(dep.SdkVersion()).effectiveVersion(ctx) if err != nil || minSdkVersion < jniSdkVersion { ctx.OtherModuleErrorf(dep, "sdk_version(%v) is higher than min_sdk_version(%v) of the containing android_app(%v)", dep.SdkVersion(), minSdkVersion, ctx.ModuleName()) return } }) } // Returns true if the native libraries should be stored in the APK uncompressed and the // extractNativeLibs application flag should be set to false in the manifest. func (a *AndroidApp) useEmbeddedNativeLibs(ctx android.ModuleContext) bool { Loading
java/app_test.go +121 −0 Original line number Diff line number Diff line Loading @@ -473,6 +473,127 @@ func TestUpdatableApps(t *testing.T) { } } func TestUpdatableApps_JniLibsShouldShouldSupportMinSdkVersion(t *testing.T) { testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "current", jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", system_shared_libs: [], sdk_version: "current", } `) } func TestUpdatableApps_JniLibShouldBeBuiltAgainstMinSdkVersion(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", system_shared_libs: [], sdk_version: "29", } ndk_prebuilt_object { name: "ndk_crtbegin_so.29", sdk_version: "29", } ndk_prebuilt_object { name: "ndk_crtend_so.29", sdk_version: "29", } ` fs := map[string][]byte{ "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtbegin_so.o": nil, "prebuilts/ndk/current/platforms/android-29/arch-arm/usr/lib/crtend_so.o": nil, } ctx, _ := testJavaWithConfig(t, testConfig(nil, bp, fs)) inputs := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").Description("link").Implicits var crtbeginFound, crtendFound bool for _, input := range inputs { switch input.String() { case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtbegin_so.o": crtbeginFound = true case "prebuilts/ndk/current/platforms/android-29/arch-arm64/usr/lib/crtend_so.o": crtendFound = true } } if !crtbeginFound || !crtendFound { t.Error("should link with ndk_crtbegin_so.29 and ndk_crtend_so.29") } } func TestUpdatableApps_ErrorIfJniLibDoesntSupportMinSdkVersion(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", // this APK should support 29 jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", sdk_version: "current", } ` testJavaError(t, `"libjni" .*: sdk_version\(current\) is higher than min_sdk_version\(29\)`, bp) } func TestUpdatableApps_ErrorIfDepSdkVersionIsHigher(t *testing.T) { bp := cc.GatherRequiredDepsForTest(android.Android) + ` android_app { name: "foo", srcs: ["a.java"], updatable: true, sdk_version: "current", min_sdk_version: "29", // this APK should support 29 jni_libs: ["libjni"], } cc_library { name: "libjni", stl: "none", shared_libs: ["libbar"], system_shared_libs: [], sdk_version: "27", } cc_library { name: "libbar", stl: "none", system_shared_libs: [], sdk_version: "current", } ` testJavaError(t, `"libjni" .*: links "libbar" built against newer API version "current"`, bp) } func TestResourceDirs(t *testing.T) { testCases := []struct { name string Loading