From da1247a0769b184938d0afe9ca3b69ecab14654f Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Thu, 8 Jun 2017 14:13:29 -0600 Subject: [PATCH] Omit icons from bulk SessionInfo calls. Calls that return List can end up returning hundreds of sessions, each of which include a "Bitmap appIcon" object. Since we quickly smash the entire list through a ParceledListSlice, we risk exhausting FDs for all the ashmem regions. To mitigate this, we omit these icons from the bulk calls, and then fetch individual icons on-demand when explicitly requested. Test: create 2k sessions and verify system doesn't croak Bug: 38021844 Change-Id: I932073defe5b9b34a636818a69009d49060215fb --- core/java/android/content/pm/PackageInstaller.java | 11 +++++++++++ .../android/server/pm/PackageInstallerService.java | 4 ++-- .../android/server/pm/PackageInstallerSession.java | 8 +++++++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 7f3f35ffd4f3f..5eca57b29ea8f 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -24,6 +24,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.app.ActivityManager; +import android.app.AppGlobals; import android.content.Intent; import android.content.IntentSender; import android.content.pm.PackageManager.InstallReason; @@ -1355,6 +1356,16 @@ public class PackageInstaller { * if unavailable. */ public @Nullable Bitmap getAppIcon() { + if (appIcon == null) { + // Icon may have been omitted for calls that return bulk session + // lists, so try fetching the specific icon. + try { + appIcon = AppGlobals.getPackageManager().getPackageInstaller() + .getSessionInfo(sessionId).appIcon; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } return appIcon; } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 75e7a1ebe816c..6f07973962bb7 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -848,7 +848,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { for (int i = 0; i < mSessions.size(); i++) { final PackageInstallerSession session = mSessions.valueAt(i); if (session.userId == userId) { - result.add(session.generateInfo()); + result.add(session.generateInfo(false)); } } } @@ -866,7 +866,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { final PackageInstallerSession session = mSessions.valueAt(i); if (Objects.equals(session.installerPackageName, installerPackageName) && session.userId == userId) { - result.add(session.generateInfo()); + result.add(session.generateInfo(false)); } } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 4540d2dfd6927..f5808affdb9e4 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -288,6 +288,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } public SessionInfo generateInfo() { + return generateInfo(true); + } + + public SessionInfo generateInfo(boolean includeIcon) { final SessionInfo info = new SessionInfo(); synchronized (mLock) { info.sessionId = sessionId; @@ -302,7 +306,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { info.installReason = params.installReason; info.sizeBytes = params.sizeBytes; info.appPackageName = params.appPackageName; - info.appIcon = params.appIcon; + if (includeIcon) { + info.appIcon = params.appIcon; + } info.appLabel = params.appLabel; } return info;