From 2a5fcbde13193b02c67fbfe6f6b02e2596026d18 Mon Sep 17 00:00:00 2001 From: Hajime Morrita Date: Mon, 11 Jan 2021 13:42:30 -0800 Subject: [PATCH] PinnerService Pin split APKs (behind a flag). This CL lets PinnerService pin the split APKs, in addition to the base APK. This matters when the APK is built as AAB. This behavior is hidden behind "pin_split_apks" DeviceConfig flag, which is false for now: This is becaue AAB-built apps have broken pinlist for the base APK and is missing the list for split APKs, ending up pinning too much. The flag should be flipped once the these APKs get proper pinlists. Bug: 174698005 Test: Ran following commands and inspected the output: $ adb shell device_config put runtime_native_boot pin_camera true && \ adb shell device_config put runtime_native_boot pin_split_apks true $ adb shell cmd pinner repin && adb shell dumpsys pinner $ adb shell device_config put runtime_native_boot pin_camera true && \ adb shell device_config put runtime_native_boot pin_split_apks false $ adb shell cmd pinner repin && adb shell dumpsys pinner Change-Id: Ic9c82b2538095e53daf9c1ef6557f487e8fac0a4 --- .../com/android/server/PinnerService.java | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index ce8863cc99939..871de0dc28bf8 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -521,6 +521,13 @@ public final class PinnerService extends SystemService { return pinKeys; } + private static boolean shouldPinSplitApks() { + // For now this is disabled by default bcause the pinlist support for split APKs are + // missing in the toolchain. This flag should be removed once it is ready. b/174697187. + return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, + "pin_split_apks", false); + } + private synchronized ArraySet getPinKeys() { return mPinKeys; } @@ -672,19 +679,40 @@ public final class PinnerService extends SystemService { mPinnedApps.put(key, pinnedApp); } + // pin APK - int pinSizeLimit = getSizeLimitForKey(key); - String apk = appInfo.sourceDir; - PinnedFile pf = pinFile(apk, pinSizeLimit, /*attemptPinIntrospection=*/true); - if (pf == null) { - Slog.e(TAG, "Failed to pin " + apk); - return; + final int pinSizeLimit = getSizeLimitForKey(key); + List apks = new ArrayList<>(); + apks.add(appInfo.sourceDir); + + if (shouldPinSplitApks() && appInfo.splitSourceDirs != null) { + for (String splitApk : appInfo.splitSourceDirs) { + apks.add(splitApk); + } } - if (DEBUG) { - Slog.i(TAG, "Pinned " + pf.fileName); - } - synchronized (this) { - pinnedApp.mFiles.add(pf); + + int apkPinSizeLimit = pinSizeLimit; + for (String apk: apks) { + if (apkPinSizeLimit <= 0) { + Slog.w(TAG, "Reached to the pin size limit. Skipping: " + apk); + // Continue instead of break to print all skipped APK names. + continue; + } + + PinnedFile pf = pinFile(apk, apkPinSizeLimit, /*attemptPinIntrospection=*/true); + if (pf == null) { + Slog.e(TAG, "Failed to pin " + apk); + continue; + } + + if (DEBUG) { + Slog.i(TAG, "Pinned " + pf.fileName); + } + synchronized (this) { + pinnedApp.mFiles.add(pf); + } + + apkPinSizeLimit -= pf.bytesPinned; } // determine the ABI from either ApplicationInfo or Build @@ -703,7 +731,7 @@ public final class PinnerService extends SystemService { //not pinning the oat/odex is not a fatal error for (String file : files) { - pf = pinFile(file, pinSizeLimit, /*attemptPinIntrospection=*/false); + PinnedFile pf = pinFile(file, pinSizeLimit, /*attemptPinIntrospection=*/false); if (pf != null) { synchronized (this) { if (PROP_PIN_ODEX) {