Don't use SDK variant for vendor JNI libraries

Vendor JNI libraries already have stable APIs enforced by the VNDK,
they shouldn't use SDK variants.

Bug: 156225490
Test: TestJNISDK
Change-Id: I21ba67e8e9fb05016caf5888129adc1a939545c2
This commit is contained in:
Colin Cross 2020-05-13 11:05:02 -07:00
parent 61b5e26f27
commit c2d24050c5
4 changed files with 73 additions and 27 deletions

View File

@ -898,6 +898,13 @@ func (m *ModuleBase) SystemExtSpecific() bool {
return Bool(m.commonProperties.System_ext_specific) return Bool(m.commonProperties.System_ext_specific)
} }
// RequiresStableAPIs returns true if the module will be installed to a partition that may
// be updated separately from the system image.
func (m *ModuleBase) RequiresStableAPIs(ctx BaseModuleContext) bool {
return m.SocSpecific() || m.DeviceSpecific() ||
(m.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface())
}
func (m *ModuleBase) PartitionTag(config DeviceConfig) string { func (m *ModuleBase) PartitionTag(config DeviceConfig) string {
partition := "system" partition := "system"
if m.SocSpecific() { if m.SocSpecific() {

View File

@ -249,7 +249,10 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
// If the app builds against an Android SDK use the SDK variant of JNI dependencies // If the app builds against an Android SDK use the SDK variant of JNI dependencies
// unless jni_uses_platform_apis is set. // unless jni_uses_platform_apis is set.
if (usesSDK && !Bool(a.appProperties.Jni_uses_platform_apis)) || // Don't require the SDK variant for apps that are shipped on vendor, etc., as they already
// have stable APIs through the VNDK.
if (usesSDK && !a.RequiresStableAPIs(ctx) &&
!Bool(a.appProperties.Jni_uses_platform_apis)) ||
Bool(a.appProperties.Jni_uses_sdk_apis) { Bool(a.appProperties.Jni_uses_sdk_apis) {
variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"}) variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
} }
@ -584,7 +587,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
dexJarFile := a.dexBuildActions(ctx) dexJarFile := a.dexBuildActions(ctx)
jniLibs, certificateDeps := collectAppDeps(ctx, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis)) jniLibs, certificateDeps := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, ctx) jniJarFile := a.jniBuildActions(jniLibs, ctx)
if ctx.Failed() { if ctx.Failed() {
@ -622,12 +625,25 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
a.buildAppDependencyInfo(ctx) a.buildAppDependencyInfo(ctx)
} }
func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps bool, type appDepsInterface interface {
sdkVersion() sdkSpec
minSdkVersion() sdkSpec
RequiresStableAPIs(ctx android.BaseModuleContext) bool
}
func collectAppDeps(ctx android.ModuleContext, app appDepsInterface,
shouldCollectRecursiveNativeDeps bool,
checkNativeSdkVersion bool) ([]jniLib, []Certificate) { checkNativeSdkVersion bool) ([]jniLib, []Certificate) {
var jniLibs []jniLib var jniLibs []jniLib
var certificates []Certificate var certificates []Certificate
seenModulePaths := make(map[string]bool) seenModulePaths := make(map[string]bool)
if checkNativeSdkVersion {
checkNativeSdkVersion = app.sdkVersion().specified() &&
app.sdkVersion().kind != sdkCorePlatform && !app.RequiresStableAPIs(ctx)
}
ctx.WalkDeps(func(module android.Module, parent android.Module) bool { ctx.WalkDeps(func(module android.Module, parent android.Module) bool {
otherName := ctx.OtherModuleName(module) otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module) tag := ctx.OtherModuleDependencyTag(module)
@ -645,16 +661,9 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps
} }
seenModulePaths[path.String()] = true seenModulePaths[path.String()] = true
if checkNativeSdkVersion { if checkNativeSdkVersion && dep.SdkVersion() == "" {
if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok { ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
if app.sdkVersion().specified() && otherName)
app.sdkVersion().kind != sdkCorePlatform &&
dep.SdkVersion() == "" {
ctx.PropertyErrorf("jni_libs",
"JNI dependency %q uses platform APIs, but this module does not",
otherName)
}
}
} }
if lib.Valid() { if lib.Valid() {
@ -1244,7 +1253,7 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set") ctx.ModuleErrorf("One and only one of certficate, presigned, and default_dev_cert properties must be set")
} }
_, certificates := collectAppDeps(ctx, false, false) _, certificates := collectAppDeps(ctx, a, false, false)
// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
// TODO: LOCAL_PACKAGE_SPLITS // TODO: LOCAL_PACKAGE_SPLITS
@ -1370,6 +1379,14 @@ func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep an
return false return false
} }
func (a *AndroidAppImport) sdkVersion() sdkSpec {
return sdkSpecFrom("")
}
func (a *AndroidAppImport) minSdkVersion() sdkSpec {
return sdkSpecFrom("")
}
func createVariantGroupType(variants []string, variantGroupName string) reflect.Type { func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
props := reflect.TypeOf((*AndroidAppImportProperties)(nil)) props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
@ -1555,7 +1572,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
r.aapt.buildActions(ctx, r, aaptLinkFlags...) r.aapt.buildActions(ctx, r, aaptLinkFlags...)
// Sign the built package // Sign the built package
_, certificates := collectAppDeps(ctx, false, false) _, certificates := collectAppDeps(ctx, r, false, false)
certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx) certificates = processMainCert(r.ModuleBase, String(r.properties.Certificate), certificates, ctx)
signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk") signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates) SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)

View File

@ -1144,25 +1144,44 @@ func TestJNISDK(t *testing.T) {
platform_apis: true, platform_apis: true,
jni_uses_sdk_apis: true, jni_uses_sdk_apis: true,
} }
cc_library {
name: "libvendorjni",
system_shared_libs: [],
stl: "none",
vendor: true,
}
android_test {
name: "app_vendor",
jni_libs: ["libvendorjni"],
sdk_version: "current",
vendor: true,
}
`) `)
testCases := []struct { testCases := []struct {
name string name string
sdkJNI bool sdkJNI bool
vendorJNI bool
}{ }{
{"app_platform", false}, {name: "app_platform"},
{"app_sdk", true}, {name: "app_sdk", sdkJNI: true},
{"app_force_platform", false}, {name: "app_force_platform"},
{"app_force_sdk", true}, {name: "app_force_sdk", sdkJNI: true},
{name: "app_vendor", vendorJNI: true},
} }
platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
Output("libjni.so").Output.String()
sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
Output("libjni.so").Output.String()
vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
Output("libvendorjni.so").Output.String()
for _, test := range testCases { for _, test := range testCases {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
app := ctx.ModuleForTests(test.name, "android_common") app := ctx.ModuleForTests(test.name, "android_common")
platformJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_shared").
Output("libjni.so").Output.String()
sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
Output("libjni.so").Output.String()
jniLibZip := app.MaybeOutput("jnilibs.zip") jniLibZip := app.MaybeOutput("jnilibs.zip")
if len(jniLibZip.Implicits) != 1 { if len(jniLibZip.Implicits) != 1 {
@ -1174,6 +1193,10 @@ func TestJNISDK(t *testing.T) {
if gotJNI != sdkJNI { if gotJNI != sdkJNI {
t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI) t.Errorf("expected SDK JNI library %q, got %q", sdkJNI, gotJNI)
} }
} else if test.vendorJNI {
if gotJNI != vendorJNI {
t.Errorf("expected platform JNI library %q, got %q", vendorJNI, gotJNI)
}
} else { } else {
if gotJNI != platformJNI { if gotJNI != platformJNI {
t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI) t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)

View File

@ -95,8 +95,7 @@ func (j *Module) CheckStableSdkVersion() error {
} }
func (j *Module) checkSdkVersions(ctx android.ModuleContext) { func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
if j.SocSpecific() || j.DeviceSpecific() || if j.RequiresStableAPIs(ctx) {
(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
if sc, ok := ctx.Module().(sdkContext); ok { if sc, ok := ctx.Module().(sdkContext); ok {
if !sc.sdkVersion().specified() { if !sc.sdkVersion().specified() {
ctx.PropertyErrorf("sdk_version", ctx.PropertyErrorf("sdk_version",