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

Commit 652824c8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes from topic "revert-3094658-revert-3088867-QEHDREAABY-IOPVAUIKWL" into main

* changes:
  Revert^2 "Refactor how jni_libs dependencies are added"
  Revert^2 "Add make java.dependencyTag installable or not"
  Revert "Revert "APK-in-APEX should set use_embedded_native_libs:..."
  Revert^2 "Install jni symlinks in Soong"
parents 39b3b1f7 92d8404b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5922,6 +5922,7 @@ func TestApexWithApps(t *testing.T) {
			srcs: ["foo/bar/MyClass.java"],
			sdk_version: "current",
			system_modules: "none",
			use_embedded_native_libs: true,
			jni_libs: ["libjni"],
			stl: "none",
			apex_available: [ "myapex" ],
+3 −15
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package java
import (
	"fmt"
	"io"
	"strings"

	"android/soong/android"

@@ -414,22 +413,11 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
					jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
					entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
				} else {
					var names []string
					for _, jniLib := range app.jniLibs {
						entries.AddStrings("LOCAL_SOONG_JNI_LIBS_"+jniLib.target.Arch.ArchType.String(), jniLib.name)
						var partitionTag string

						// Mimic the creation of partition_tag in build/make,
						// which defaults to an empty string when the partition is system.
						// Otherwise, capitalize with a leading _
						if jniLib.partition == "system" {
							partitionTag = ""
						} else {
							split := strings.Split(jniLib.partition, "/")
							partitionTag = "_" + strings.ToUpper(split[len(split)-1])
						}
						entries.AddStrings("LOCAL_SOONG_JNI_LIBS_PARTITION_"+jniLib.target.Arch.ArchType.String(),
							jniLib.name+":"+partitionTag)
						names = append(names, jniLib.name)
					}
					entries.AddStrings("LOCAL_REQUIRED_MODULES", names...)
				}

				if len(app.jniCoverageOutputs) > 0 {
+32 −132
Original line number Diff line number Diff line
@@ -20,8 +20,6 @@ import (

	"android/soong/android"
	"android/soong/cc"

	"github.com/google/blueprint/proptools"
)

func TestRequired(t *testing.T) {
@@ -256,148 +254,50 @@ func TestGetOverriddenPackages(t *testing.T) {
	}
}

func TestJniPartition(t *testing.T) {
	bp := `
		cc_library {
			name: "libjni_system",
			system_shared_libs: [],
			sdk_version: "current",
			stl: "none",
		}

		cc_library {
			name: "libjni_system_ext",
			system_shared_libs: [],
			sdk_version: "current",
			stl: "none",
			system_ext_specific: true,
		}

		cc_library {
			name: "libjni_odm",
			system_shared_libs: [],
			sdk_version: "current",
			stl: "none",
			device_specific: true,
		}

		cc_library {
			name: "libjni_product",
			system_shared_libs: [],
			sdk_version: "current",
			stl: "none",
			product_specific: true,
		}

		cc_library {
			name: "libjni_vendor",
			system_shared_libs: [],
			sdk_version: "current",
			stl: "none",
			soc_specific: true,
		}

		android_app {
			name: "test_app_system_jni_system",
			privileged: true,
			platform_apis: true,
			certificate: "platform",
			jni_libs: ["libjni_system"],
		}

func TestJniAsRequiredDeps(t *testing.T) {
	ctx := android.GroupFixturePreparers(
		PrepareForTestWithJavaDefaultModules,
		cc.PrepareForTestWithCcDefaultModules,
		android.PrepareForTestWithAndroidMk,
	).RunTestWithBp(t, `
		android_app {
			name: "test_app_system_jni_system_ext",
			privileged: true,
			name: "app",
			jni_libs: ["libjni"],
			platform_apis: true,
			certificate: "platform",
			jni_libs: ["libjni_system_ext"],
		}

		android_app {
			name: "test_app_system_ext_jni_system",
			privileged: true,
			name: "app_embedded",
			jni_libs: ["libjni"],
			platform_apis: true,
			certificate: "platform",
			jni_libs: ["libjni_system"],
			system_ext_specific: true
		}

		android_app {
			name: "test_app_system_ext_jni_system_ext",
			sdk_version: "core_platform",
			jni_libs: ["libjni_system_ext"],
			system_ext_specific: true
		}

		android_app {
			name: "test_app_product_jni_product",
			sdk_version: "core_platform",
			jni_libs: ["libjni_product"],
			product_specific: true
			use_embedded_native_libs: true,
		}

		android_app {
			name: "test_app_vendor_jni_odm",
			sdk_version: "core_platform",
			jni_libs: ["libjni_odm"],
			soc_specific: true
		cc_library {
			name: "libjni",
			system_shared_libs: [],
			stl: "none",
		}
		`)

		android_app {
			name: "test_app_odm_jni_vendor",
			sdk_version: "core_platform",
			jni_libs: ["libjni_vendor"],
			device_specific: true
		}
		android_app {
			name: "test_app_system_jni_multiple",
			privileged: true,
			platform_apis: true,
			certificate: "platform",
			jni_libs: ["libjni_system", "libjni_system_ext"],
		}
		android_app {
			name: "test_app_vendor_jni_multiple",
			sdk_version: "core_platform",
			jni_libs: ["libjni_odm", "libjni_vendor"],
			soc_specific: true
		}
		`
	arch := "arm64"
	ctx := android.GroupFixturePreparers(
		PrepareForTestWithJavaDefaultModules,
		cc.PrepareForTestWithCcDefaultModules,
		android.PrepareForTestWithAndroidMk,
		android.FixtureModifyConfig(func(config android.Config) {
			config.TestProductVariables.DeviceArch = proptools.StringPtr(arch)
		}),
	).
		RunTestWithBp(t, bp)
	testCases := []struct {
	testcases := []struct {
		name     string
		partitionNames []string
		partitionTags  []string
		expected []string
	}{
		{"test_app_system_jni_system", []string{"libjni_system"}, []string{""}},
		{"test_app_system_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
		{"test_app_system_ext_jni_system", []string{"libjni_system"}, []string{""}},
		{"test_app_system_ext_jni_system_ext", []string{"libjni_system_ext"}, []string{"_SYSTEM_EXT"}},
		{"test_app_product_jni_product", []string{"libjni_product"}, []string{"_PRODUCT"}},
		{"test_app_vendor_jni_odm", []string{"libjni_odm"}, []string{"_ODM"}},
		{"test_app_odm_jni_vendor", []string{"libjni_vendor"}, []string{"_VENDOR"}},
		{"test_app_system_jni_multiple", []string{"libjni_system", "libjni_system_ext"}, []string{"", "_SYSTEM_EXT"}},
		{"test_app_vendor_jni_multiple", []string{"libjni_odm", "libjni_vendor"}, []string{"_ODM", "_VENDOR"}},
	}

	for _, test := range testCases {
		t.Run(test.name, func(t *testing.T) {
			mod := ctx.ModuleForTests(test.name, "android_common").Module()
			entry := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
			for i := range test.partitionNames {
				actual := entry.EntryMap["LOCAL_SOONG_JNI_LIBS_PARTITION_"+arch][i]
				expected := test.partitionNames[i] + ":" + test.partitionTags[i]
				android.AssertStringEquals(t, "Expected and actual differ", expected, actual)
			}
		})
		{
			name:     "app",
			expected: []string{"libjni"},
		},
		{
			name:     "app_embedded",
			expected: nil,
		},
	}

	for _, tc := range testcases {
		mod := ctx.ModuleForTests(tc.name, "android_common").Module()
		entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, mod)[0]
		required := entries.EntryMap["LOCAL_REQUIRED_MODULES"]
		android.AssertDeepEquals(t, "unexpected required deps", tc.expected, required)
	}
}
+63 −11
Original line number Diff line number Diff line
@@ -274,16 +274,37 @@ func (a *AndroidApp) DepsMutator(ctx android.BottomUpMutatorContext) {
		variation := append(jniTarget.Variations(),
			blueprint.Variation{Mutator: "link", Variation: "shared"})

		// If the app builds against an Android SDK use the SDK variant of JNI dependencies
		// unless jni_uses_platform_apis is set.
		// 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) {
		// Test whether to use the SDK variant or the non-SDK variant of JNI dependencies.
		// Many factors are considered here.
		// 1. Basically, the selection follows whether the app has sdk_version set or not.
		jniUsesSdkVariant := usesSDK
		// 2. However, jni_uses_platform_apis and jni_uses_sdk_apis can override it
		if Bool(a.appProperties.Jni_uses_sdk_apis) {
			jniUsesSdkVariant = true
		}
		if Bool(a.appProperties.Jni_uses_platform_apis) {
			jniUsesSdkVariant = false
		}
		// 3. Then the use of SDK variant is again prohibited for the following cases:
		// 3.1. the app is shipped on unbundled partitions like vendor. Since the entire
		// partition (not only the app) is considered unbudled, there's no need to use the
		// SDK variant.
		// 3.2. the app doesn't support embedding the JNI libs
		if a.RequiresStableAPIs(ctx) || !a.shouldEmbedJnis(ctx) {
			jniUsesSdkVariant = false
		}
		if jniUsesSdkVariant {
			variation = append(variation, blueprint.Variation{Mutator: "sdk", Variation: "sdk"})
		}
		ctx.AddFarVariationDependencies(variation, jniLibTag, a.appProperties.Jni_libs...)

		// Use the installable dep tag when the JNIs are not embedded
		var tag dependencyTag
		if a.shouldEmbedJnis(ctx) {
			tag = jniLibTag
		} else {
			tag = jniInstallTag
		}
		ctx.AddFarVariationDependencies(variation, tag, a.appProperties.Jni_libs...)
	}
	for _, aconfig_declaration := range a.aaptProperties.Flags_packages {
		ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
@@ -334,6 +355,7 @@ func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleCon

func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	a.checkAppSdkVersions(ctx)
	a.checkEmbedJnis(ctx)
	a.generateAndroidBuildActions(ctx)
	a.generateJavaUsedByApex(ctx)
}
@@ -367,6 +389,17 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
	a.checkSdkVersions(ctx)
}

// Ensures that use_embedded_native_libs are set for apk-in-apex
func (a *AndroidApp) checkEmbedJnis(ctx android.BaseModuleContext) {
	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
	apkInApex := !apexInfo.IsForPlatform()
	hasJnis := len(a.appProperties.Jni_libs) > 0

	if apkInApex && hasJnis && !Bool(a.appProperties.Use_embedded_native_libs) {
		ctx.ModuleErrorf("APK in APEX should have use_embedded_native_libs: true")
	}
}

// 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).
func (a *AndroidApp) checkJniLibsSdkVersion(ctx android.ModuleContext, minSdkVersion android.ApiLevel) {
@@ -422,9 +455,9 @@ func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
}

func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
	apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
	return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
		!apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
		Bool(a.appProperties.Updatable) ||
		a.appProperties.AlwaysPackageNativeLibs
}

func generateAaptRenamePackageFlags(packageName string, renameResourcesPackage bool) []string {
@@ -818,7 +851,9 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {

	dexJarFile, packageResources := a.dexBuildActions(ctx)

	jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
	// No need to check the SDK version of the JNI deps unless we embed them
	checkNativeSdkVersion := a.shouldEmbedJnis(ctx) && !Bool(a.appProperties.Jni_uses_platform_apis)
	jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), checkNativeSdkVersion)
	jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)

	if ctx.Failed() {
@@ -900,6 +935,22 @@ func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
			installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
			extraInstalledPaths = append(extraInstalledPaths, installed)
		}
		// If we don't embed jni libs, make sure that those are installed along with the
		// app, and also place symlinks to the installed paths under the lib/<arch>
		// directory of the app installation directory. ex:
		// /system/app/MyApp/lib/arm64/libfoo.so -> /system/lib64/libfoo.so
		if !a.embeddedJniLibs {
			for _, jniLib := range jniLibs {
				archStr := jniLib.target.Arch.ArchType.String()
				symlinkDir := a.installDir.Join(ctx, "lib", archStr)
				for _, installedLib := range jniLib.installPaths {
					// install the symlink itself
					symlinkName := installedLib.Base()
					symlinkTarget := android.InstallPathToOnDevicePath(ctx, installedLib)
					ctx.InstallAbsoluteSymlink(symlinkDir, symlinkName, symlinkTarget)
				}
			}
		}
		ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
	}

@@ -987,6 +1038,7 @@ func collectJniDeps(ctx android.ModuleContext,
						coverageFile:   dep.CoverageOutputFile(),
						unstrippedFile: dep.UnstrippedOutputFile(),
						partition:      dep.Partition(),
						installPaths:   dep.FilesToInstall(),
					})
				} else if ctx.Config().AllowMissingDependencies() {
					ctx.AddMissingDependencies([]string{otherName})
+10 −9
Original line number Diff line number Diff line
@@ -366,14 +366,14 @@ type dependencyTag struct {
	toolchain bool

	static bool

	installable bool
}

// installDependencyTag is a dependency tag that is annotated to cause the installed files of the
// dependency to be installed when the parent module is installed.
type installDependencyTag struct {
	blueprint.BaseDependencyTag
	android.InstallAlwaysNeededDependencyTag
	name string
var _ android.InstallNeededDependencyTag = (*dependencyTag)(nil)

func (d dependencyTag) InstallDepNeeded() bool {
	return d.installable
}

func (d dependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
@@ -405,7 +405,7 @@ func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDepe
}

func IsJniDepTag(depTag blueprint.DependencyTag) bool {
	return depTag == jniLibTag
	return depTag == jniLibTag || depTag == jniInstallTag
}

var (
@@ -434,8 +434,8 @@ var (
	javaApiContributionTag  = dependencyTag{name: "java-api-contribution"}
	depApiSrcsTag           = dependencyTag{name: "dep-api-srcs"}
	aconfigDeclarationTag   = dependencyTag{name: "aconfig-declaration"}
	jniInstallTag           = installDependencyTag{name: "jni install"}
	binaryInstallTag        = installDependencyTag{name: "binary install"}
	jniInstallTag           = dependencyTag{name: "jni install", runtimeLinked: true, installable: true}
	binaryInstallTag        = dependencyTag{name: "binary install", runtimeLinked: true, installable: true}
	usesLibReqTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
	usesLibOptTag           = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
	usesLibCompat28OptTag   = makeUsesLibraryDependencyTag(28, true)
@@ -491,6 +491,7 @@ type jniLib struct {
	coverageFile   android.OptionalPath
	unstrippedFile android.Path
	partition      string
	installPaths   android.InstallPaths
}

func sdkDeps(ctx android.BottomUpMutatorContext, sdkContext android.SdkContext, d dexer) {