aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiyong Park <jiyong@google.com>2024-05-15 03:21:26 +0900
committerJiyong Park <jiyong@google.com>2024-05-16 19:40:00 +0900
commit4f487c5b565717f64c91dcdabb9233324bf9a6ba (patch)
treeb0116bd716abaf806d3ebf46238d13a3391d0827
parent162098358cb0b1fa90a8bdc4467c2b7eff9a2499 (diff)
downloadsoong-4f487c5b565717f64c91dcdabb9233324bf9a6ba.tar.gz
Install jni symlinks in Soong
The installation of the symlink (<partition>/app/MyApp/lib/<arch>/libfoo.so) and its target (/system/lib64/libfoo.so) are now done int Soong. I gave up the idea of always embedding jni libs to apps, due to a hard-to-fix regression in storage usage. Specifically, consider this case. app --(jni_lib)--> libfoo --(jni_lib)--> libbar libfoo --(shared_lib)--> libbar Ideally, with the embedding idea, both libfoo and libbar should be embedded into the app and there should be no libfoo or libbar outside of the apk, unless there's no dependency to any of them from outside of the apk. However, the previous implementation installed libbar to /system/lib64, leading two copies of the lib; one in /system/lib64, the other in the apk. This was happening because libbar was also considered as a transitive dep of libfoo, and therefore a dependency to its installation path is added to the apk. The problem here is that the app doesn't know that libfoo depends on libbar. We in theory can write a very delicate dependency traverse routine which filters libbar out of the transitive deps, but that looked too complicated. Bug: 339923078 Bug: 330276359 Test: Build and watch any bloatbuster warning Test: m aosp_cf_system_x86_64 The following three files are found * system/lib64/libnfc_nci_jni.so * system/etc/libnfc-nci.conf * system/priv-app/NfcNci/lib/arm64/libnfc_nci_jni.so Change-Id: I0930cb1ebb8ca8a6efd64b1ce2cdfd1c47fe19ef
-rw-r--r--java/androidmk.go18
-rw-r--r--java/androidmk_test.go149
-rw-r--r--java/app.go21
-rw-r--r--java/java.go1
4 files changed, 22 insertions, 167 deletions
diff --git a/java/androidmk.go b/java/androidmk.go
index 4f740b231..43160741b 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -17,7 +17,6 @@ package java
import (
"fmt"
"io"
- "strings"
"android/soong/android"
@@ -413,23 +412,6 @@ func (app *AndroidApp) AndroidMkEntries() []android.AndroidMkEntries {
if app.embeddedJniLibs {
jniSymbols := app.JNISymbolsInstalls(app.installPathForJNISymbols.String())
entries.SetString("LOCAL_SOONG_JNI_LIBS_SYMBOLS", jniSymbols.String())
- } else {
- 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)
- }
}
if len(app.jniCoverageOutputs) > 0 {
diff --git a/java/androidmk_test.go b/java/androidmk_test.go
index 2978a40aa..875e06f11 100644
--- a/java/androidmk_test.go
+++ b/java/androidmk_test.go
@@ -19,9 +19,6 @@ import (
"testing"
"android/soong/android"
- "android/soong/cc"
-
- "github.com/google/blueprint/proptools"
)
func TestRequired(t *testing.T) {
@@ -255,149 +252,3 @@ func TestGetOverriddenPackages(t *testing.T) {
android.AssertDeepEquals(t, "overrides property", expected.overrides, actual)
}
}
-
-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"],
- }
-
- android_app {
- name: "test_app_system_jni_system_ext",
- privileged: true,
- platform_apis: true,
- certificate: "platform",
- jni_libs: ["libjni_system_ext"],
- }
-
- android_app {
- name: "test_app_system_ext_jni_system",
- privileged: true,
- 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
- }
-
- android_app {
- name: "test_app_vendor_jni_odm",
- sdk_version: "core_platform",
- jni_libs: ["libjni_odm"],
- soc_specific: true
- }
-
- 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 {
- name string
- partitionNames []string
- partitionTags []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)
- }
- })
- }
-}
diff --git a/java/app.go b/java/app.go
index f05b8a7cd..22958e5c8 100644
--- a/java/app.go
+++ b/java/app.go
@@ -911,6 +911,26 @@ 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 target along with the app
+ extraInstalledPaths = append(extraInstalledPaths, installedLib)
+ ctx.PackageFile(installedLib, "", jniLib.path)
+
+ // 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...)
}
@@ -998,6 +1018,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})
diff --git a/java/java.go b/java/java.go
index 0df96a3a5..249480428 100644
--- a/java/java.go
+++ b/java/java.go
@@ -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) {