From 46f914563178110ceefb0626fe376403642965d5 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Fri, 25 Oct 2024 20:41:57 +0200 Subject: [PATCH] [java-runtime] Simplify and fix split configs detection (#9378) We use [`ApplicationInfo.splitSourceDirs`][0] to detect whether the application uses [split config `.apk` files][1]. Those files are created by Android when an `.aab` is used to deploy application, e.g. via the Google Play Store or manually: % dotnet new android % dotnet build -c Release % java -jar /usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/34.0.94/tools/bundletool.jar \ build-apks --bundle bin/Release/net8.0-android/*-Signed.aab \ --output=app.apks --connected-device \ --aapt2 /usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/34.0.94/tools/Darwin/aapt2 # app.apks contains the "split" apk files. # can manually install app.apks by using `bundletool.jar install-apks`: % java -jar /usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/34.0.94/tools/bundletool.jar \ install-apks --apks=app.apks When they are present, the "base" `.apk` file in `splits/base-master.apk` doesn't contain any `lib/` directories and we can simply skip scanning it for those entries, thus saving on startup time. (The `splits/base-.apk` file contains the native libraries of interest to us.) We used to check whether there are more than one entry in `splitSourceDirs`, which used to be the case, but it seems that recent Android versions (at least API-33 and newer) can have just a single entry in the array. Because of that, we were scanning all the `.apk` files on those Android versions, wasting time at startup. Fix the check by probing whether the array exists and contains at least a single entry. Additionally, remove API-21 checks, since this is our lowest supported API level. [0]: https://developer.android.com/reference/android/content/pm/ApplicationInfo#splitSourceDirs [1]: https://developer.android.com/guide/app-bundle --- .../Resources/MonoRuntimeProvider.Bundled.java | 16 ++++++---------- .../java/mono/android/MonoPackageManager.java | 8 +------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java index 9fb0f4f636b..2af2fef566b 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java +++ b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java @@ -21,15 +21,12 @@ public void attachInfo (android.content.Context context, android.content.pm.Prov // Mono Runtime Initialization {{{ android.content.pm.ApplicationInfo applicationInfo = context.getApplicationInfo (); String[] apks = null; - if (android.os.Build.VERSION.SDK_INT >= 21) { - String[] splitApks = applicationInfo.splitPublicSourceDirs; - if (splitApks != null && splitApks.length > 0) { - apks = new String[splitApks.length + 1]; - apks [0] = applicationInfo.sourceDir; - System.arraycopy (splitApks, 0, apks, 1, splitApks.length); - } - } - if (apks == null) { + String[] splitApks = applicationInfo.splitSourceDirs; + if (splitApks != null && splitApks.length > 0) { + apks = new String[splitApks.length + 1]; + apks [0] = applicationInfo.sourceDir; + System.arraycopy (splitApks, 0, apks, 1, splitApks.length); + } else { apks = new String[] { applicationInfo.sourceDir }; } mono.MonoPackageManager.LoadApplication (context, applicationInfo, apks); @@ -67,4 +64,3 @@ public int update (android.net.Uri uri, android.content.ContentValues values, St throw new RuntimeException ("This operation is not supported."); } } - diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java index 89f43542529..fa6ed7be7fc 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager.java @@ -58,13 +58,7 @@ public static void LoadApplication (Context context, ApplicationInfo runtimePack // Should the order change here, src/monodroid/jni/SharedConstants.hh must be updated accordingly // String[] appDirs = new String[] {filesDir, cacheDir, dataDir}; - boolean haveSplitApks = false; - - if (android.os.Build.VERSION.SDK_INT >= 21) { - if (runtimePackage.splitSourceDirs != null) { - haveSplitApks = runtimePackage.splitSourceDirs.length > 1; - } - } + boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0; // // Preload DSOs libmonodroid.so depends on so that the dynamic