Omit icons from bulk SessionInfo calls.

Calls that return List<SessionInfo> 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
This commit is contained in:
Jeff Sharkey
2017-06-08 14:13:29 -06:00
parent 6ef238a51c
commit da1247a076
3 changed files with 20 additions and 3 deletions

View File

@@ -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;
}

View File

@@ -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));
}
}
}

View File

@@ -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;