diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 81655cf33fa8d..114e2c1397943 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -143,6 +143,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** * All of the code required to compute proc states and oom_adj values. @@ -743,6 +744,45 @@ public class OomAdjuster { queue.offer(provider); provider.mState.setReachable(true); } + // See if this process has any corresponding SDK sandbox processes running, and if so + // scan them as well. + final List sdkSandboxes = + mProcessList.getSdkSandboxProcessesForAppLocked(pr.uid); + final int numSdkSandboxes = sdkSandboxes != null ? sdkSandboxes.size() : 0; + for (int i = numSdkSandboxes - 1; i >= 0; i--) { + ProcessRecord sdkSandbox = sdkSandboxes.get(i); + containsCycle |= sdkSandbox.mState.isReachable(); + if (sdkSandbox.mState.isReachable()) { + continue; + } + queue.offer(sdkSandbox); + sdkSandbox.mState.setReachable(true); + } + // If this process is a sandbox itself, also scan the app on whose behalf its running + if (pr.isSdkSandbox) { + for (int is = psr.numberOfRunningServices() - 1; is >= 0; is--) { + ServiceRecord s = psr.getRunningServiceAt(is); + ArrayMap> serviceConnections = + s.getConnections(); + for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) { + ArrayList clist = serviceConnections.valueAt(conni); + for (int i = clist.size() - 1; i >= 0; i--) { + ConnectionRecord cr = clist.get(i); + ProcessRecord attributedApp = cr.binding.attributedClient; + if (attributedApp == null || attributedApp == pr + || ((attributedApp.mState.getMaxAdj() >= ProcessList.SYSTEM_ADJ) + && (attributedApp.mState.getMaxAdj() < FOREGROUND_APP_ADJ))) { + continue; + } + if (attributedApp.mState.isReachable()) { + continue; + } + queue.offer(attributedApp); + attributedApp.mState.setReachable(true); + } + } + } + } } int size = processes.size(); @@ -2131,6 +2171,11 @@ public class OomAdjuster { boolean trackedProcState = false; ProcessRecord client = cr.binding.client; + if (app.isSdkSandbox && cr.binding.attributedClient != null) { + // For SDK sandboxes, use the attributed client (eg the app that + // requested the sandbox) + client = cr.binding.attributedClient; + } final ProcessStateRecord cstate = client.mState; if (computeClients) { computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, @@ -2377,12 +2422,12 @@ public class OomAdjuster { state.setAdjType(adjType); state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE); - state.setAdjSource(cr.binding.client); + state.setAdjSource(client); state.setAdjSourceProcState(clientProcState); state.setAdjTarget(s.instanceName); if (DEBUG_OOM_ADJ_REASON || logUid == appUid) { reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType - + ": " + app + ", due to " + cr.binding.client + + ": " + app + ", due to " + client + " adj=" + adj + " procState=" + ProcessList.makeProcStateString(procState)); } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 3a40fc7199f39..04c0d64e42a1c 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -484,6 +484,12 @@ public final class ProcessList { @GuardedBy("mService") final ProcessMap mAppZygotes = new ProcessMap(); + /** + * The currently running SDK sandbox processes for a uid. + */ + @GuardedBy("mService") + final SparseArray> mSdkSandboxes = new SparseArray<>(); + /** * Managees the {@link android.app.ApplicationExitInfo} records. */ @@ -2990,6 +2996,14 @@ public final class ProcessList { if (proc.isolated) { mIsolatedProcesses.put(proc.uid, proc); } + if (proc.isSdkSandbox) { + ArrayList sdkSandboxes = mSdkSandboxes.get(proc.uid); + if (sdkSandboxes == null) { + sdkSandboxes = new ArrayList<>(); + } + sdkSandboxes.add(proc); + mSdkSandboxes.put(Process.getAppUidForSdkSandboxUid(proc.uid), sdkSandboxes); + } } @GuardedBy("mService") @@ -3030,6 +3044,19 @@ public final class ProcessList { return ret; } + /** + * Returns the associated SDK sandbox processes for a UID. Note that this does + * NOT return a copy, so callers should not modify the result, or use it outside + * of the lock scope. + * + * @param uid UID to return sansdbox processes for + */ + @Nullable + @GuardedBy("mService") + List getSdkSandboxProcessesForAppLocked(int uid) { + return mSdkSandboxes.get(uid); + } + @GuardedBy("mService") ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid, boolean isSdkSandbox, int sdkSandboxUid, @@ -3135,6 +3162,16 @@ public final class ProcessList { if (record != null && record.appZygote) { removeProcessFromAppZygoteLocked(record); } + if (record != null && record.isSdkSandbox) { + final int appUid = Process.getAppUidForSdkSandboxUid(uid); + final ArrayList sdkSandboxesForUid = mSdkSandboxes.get(appUid); + if (sdkSandboxesForUid != null) { + sdkSandboxesForUid.remove(record); + if (sdkSandboxesForUid.size() == 0) { + mSdkSandboxes.remove(appUid); + } + } + } mAppsInBackgroundRestricted.remove(record); return old;