Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2d24050 authored by Colin Cross's avatar Colin Cross
Browse files

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
parent 61b5e26f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -898,6 +898,13 @@ func (m *ModuleBase) SystemExtSpecific() bool {
	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 {
	partition := "system"
	if m.SocSpecific() {
+32 −15
Original line number Diff line number Diff line
@@ -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
		// 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) {
			variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
		}
@@ -584,7 +587,7 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {

	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)

	if ctx.Failed() {
@@ -622,12 +625,25 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
	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) {

	var jniLibs []jniLib
	var certificates []Certificate
	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 {
		otherName := ctx.OtherModuleName(module)
		tag := ctx.OtherModuleDependencyTag(module)
@@ -645,17 +661,10 @@ func collectAppDeps(ctx android.ModuleContext, shouldCollectRecursiveNativeDeps
				}
				seenModulePaths[path.String()] = true

				if checkNativeSdkVersion {
					if app, ok := ctx.Module().(interface{ sdkVersion() sdkSpec }); ok {
						if app.sdkVersion().specified() &&
							app.sdkVersion().kind != sdkCorePlatform &&
							dep.SdkVersion() == "" {
							ctx.PropertyErrorf("jni_libs",
								"JNI dependency %q uses platform APIs, but this module does not",
				if checkNativeSdkVersion && dep.SdkVersion() == "" {
					ctx.PropertyErrorf("jni_libs", "JNI dependency %q uses platform APIs, but this module does not",
						otherName)
				}
					}
				}

				if lib.Valid() {
					jniLibs = append(jniLibs, jniLib{
@@ -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")
	}

	_, certificates := collectAppDeps(ctx, false, false)
	_, certificates := collectAppDeps(ctx, a, false, false)

	// TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK
	// TODO: LOCAL_PACKAGE_SPLITS
@@ -1370,6 +1379,14 @@ func (a *AndroidAppImport) DepIsInSameApex(ctx android.BaseModuleContext, dep an
	return false
}

func (a *AndroidAppImport) sdkVersion() sdkSpec {
	return sdkSpecFrom("")
}

func (a *AndroidAppImport) minSdkVersion() sdkSpec {
	return sdkSpecFrom("")
}

func createVariantGroupType(variants []string, variantGroupName string) reflect.Type {
	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))

@@ -1555,7 +1572,7 @@ func (r *RuntimeResourceOverlay) GenerateAndroidBuildActions(ctx android.ModuleC
	r.aapt.buildActions(ctx, r, aaptLinkFlags...)

	// 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)
	signed := android.PathForModuleOut(ctx, "signed", r.Name()+".apk")
	SignAppPackage(ctx, signed, r.aapt.exportPackage, certificates)
+33 −10
Original line number Diff line number Diff line
@@ -1144,25 +1144,44 @@ func TestJNISDK(t *testing.T) {
			platform_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 {
		name      string
		sdkJNI    bool
		vendorJNI bool
	}{
		{"app_platform", false},
		{"app_sdk", true},
		{"app_force_platform", false},
		{"app_force_sdk", true},
		{name: "app_platform"},
		{name: "app_sdk", sdkJNI: true},
		{name: "app_force_platform"},
		{name: "app_force_sdk", sdkJNI: true},
		{name: "app_vendor", vendorJNI: true},
	}

	for _, test := range testCases {
		t.Run(test.name, func(t *testing.T) {
			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()
	vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
		Output("libvendorjni.so").Output.String()

	for _, test := range testCases {
		t.Run(test.name, func(t *testing.T) {
			app := ctx.ModuleForTests(test.name, "android_common")

			jniLibZip := app.MaybeOutput("jnilibs.zip")
			if len(jniLibZip.Implicits) != 1 {
@@ -1174,6 +1193,10 @@ func TestJNISDK(t *testing.T) {
				if gotJNI != sdkJNI {
					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 {
				if gotJNI != platformJNI {
					t.Errorf("expected platform JNI library %q, got %q", platformJNI, gotJNI)
+1 −2
Original line number Diff line number Diff line
@@ -95,8 +95,7 @@ func (j *Module) CheckStableSdkVersion() error {
}

func (j *Module) checkSdkVersions(ctx android.ModuleContext) {
	if j.SocSpecific() || j.DeviceSpecific() ||
		(j.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
	if j.RequiresStableAPIs(ctx) {
		if sc, ok := ctx.Module().(sdkContext); ok {
			if !sc.sdkVersion().specified() {
				ctx.PropertyErrorf("sdk_version",