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

Commit 01fd7ccb authored by Colin Cross's avatar Colin Cross
Browse files

Add sdk mutator for native modules

Compiling native modules against the NDK disables platform features
like ASAN.  For anything shipped on the system image there is no
reason to compile against the NDK.  Add a new mutator to Soong that
creates a platform and an SDK variant for modules that set
sdk_version, and ignore sdk_version for the platform variant.  The
SDK variant will be used for embedding in APKs that may be installed
on older platforms.  Apexes use their own variants that enforce
backwards compatibility.

Test: sdk_test.go
Test: TestJNIPackaging
Bug: 149591340
Change-Id: I7d72934aaee2e1326cc0ba5f29f51f14feec4521
Merged-In: I7d72934aaee2e1326cc0ba5f29f51f14feec4521
(cherry picked from commit 82e192c3)
parent 1c93c299
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ bootstrap_go_package {
        "cc/rs.go",
        "cc/sanitize.go",
        "cc/sabi.go",
        "cc/sdk.go",
        "cc/snapshot_utils.go",
        "cc/stl.go",
        "cc/strip.go",
+44 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ func init() {
	AddNeverAllowRules(createLibcoreRules()...)
	AddNeverAllowRules(createMediaRules()...)
	AddNeverAllowRules(createJavaDeviceForHostRules()...)
	AddNeverAllowRules(createCcSdkVariantRules()...)
}

// Add a NeverAllow rule to the set of rules to apply.
@@ -177,6 +178,37 @@ func createJavaDeviceForHostRules() []Rule {
	}
}

func createCcSdkVariantRules() []Rule {
	sdkVersionOnlyWhitelist := []string{
		// derive_sdk_prefer32 has stem: "derive_sdk" which conflicts with the derive_sdk.
		// This sometimes works because the APEX modules that contain derive_sdk and
		// derive_sdk_prefer32 suppress the platform installation rules, but fails when
		// the APEX modules contain the SDK variant and the platform variant still exists.
		"frameworks/base/apex/sdkextensions/derive_sdk",
	}

	platformVariantPropertiesWhitelist := []string{
		// android_native_app_glue and libRSSupport use native_window.h but target old
		// sdk versions (minimum and 9 respectively) where libnativewindow didn't exist,
		// so they can't add libnativewindow to shared_libs to get the header directory
		// for the platform variant.  Allow them to use the platform variant
		// property to set shared_libs.
		"prebuilts/ndk",
		"frameworks/rs",
	}

	return []Rule{
		NeverAllow().
			NotIn(sdkVersionOnlyWhitelist...).
			WithMatcher("sdk_variant_only", isSetMatcherInstance).
			Because("sdk_variant_only can only be used in whitelisted projects"),
		NeverAllow().
			NotIn(platformVariantPropertiesWhitelist...).
			WithMatcher("platform.shared_libs", isSetMatcherInstance).
			Because("platform variant properties can only be used in whitelisted projects"),
	}
}

func neverallowMutator(ctx BottomUpMutatorContext) {
	m, ok := ctx.Module().(Module)
	if !ok {
@@ -268,6 +300,18 @@ func (m *regexMatcher) String() string {
	return ".regexp(" + m.re.String() + ")"
}

type isSetMatcher struct{}

func (m *isSetMatcher) Test(value string) bool {
	return value != ""
}

func (m *isSetMatcher) String() string {
	return ".is-set"
}

var isSetMatcherInstance = &isSetMatcher{}

type ruleProperty struct {
	fields  []string // e.x.: Vndk.Enabled
	matcher ValueMatcher
+50 −0
Original line number Diff line number Diff line
@@ -259,6 +259,50 @@ var neverallowTests = []struct {
				}`),
		},
	},
	// CC sdk rule tests
	{
		name: `"sdk_variant_only" outside whitelist`,
		fs: map[string][]byte{
			"Android.bp": []byte(`
				cc_library {
					name: "outside_whitelist",
					sdk_version: "current",
					sdk_variant_only: true,
				}`),
		},
		expectedErrors: []string{
			`module "outside_whitelist": violates neverallow`,
		},
	},
	{
		name: `"sdk_variant_only: false" outside whitelist`,
		fs: map[string][]byte{
			"Android.bp": []byte(`
				cc_library {
					name: "outside_whitelist",
					sdk_version: "current",
					sdk_variant_only: false,
				}`),
		},
		expectedErrors: []string{
			`module "outside_whitelist": violates neverallow`,
		},
	},
	{
		name: `"platform" outside whitelist`,
		fs: map[string][]byte{
			"Android.bp": []byte(`
				cc_library {
					name: "outside_whitelist",
					platform: {
						shared_libs: ["libfoo"],
					},
				}`),
		},
		expectedErrors: []string{
			`module "outside_whitelist": violates neverallow`,
		},
	},
}

func TestNeverallow(t *testing.T) {
@@ -299,6 +343,8 @@ type mockCcLibraryProperties struct {
	Include_dirs     []string
	Vendor_available *bool
	Static_libs      []string
	Sdk_version      *string
	Sdk_variant_only *bool

	Vndk struct {
		Enabled                *bool
@@ -315,6 +361,10 @@ type mockCcLibraryProperties struct {
			Cflags []string
		}
	}

	Platform struct {
		Shared_libs []string
	}
}

type mockCcLibraryModule struct {
+1 −1
Original line number Diff line number Diff line
@@ -3373,7 +3373,7 @@ func TestApexWithApps(t *testing.T) {
	}
	// JNI libraries including transitive deps are
	for _, jni := range []string{"libjni", "libfoo"} {
		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_shared_myapex").Module().(*cc.Module).OutputFile()
		jniOutput := ctx.ModuleForTests(jni, "android_arm64_armv8-a_sdk_shared_myapex").Module().(*cc.Module).OutputFile()
		// ... embedded inside APK (jnilibs.zip)
		ensureListContains(t, appZipRule.Implicits.Strings(), jniOutput.String())
		// ... and not directly inside the APEX
+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
				system_shared_libs: [],
				stl: "none",
				notice: "custom_notice",
				sdk_version: "current",
			}
			cc_library {
				name: "libprofile-clang-extras_ndk",
@@ -151,6 +152,7 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
				system_shared_libs: [],
				stl: "none",
				notice: "custom_notice",
				sdk_version: "current",
			}
		`, func(fs map[string][]byte, config android.Config) {
			config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
Loading