Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2a3daaa3 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

OomAdjuster: Give SDK sandbox the priority of the app it belongs to.

SDK sandbox processes are bound to by system_server, but system_server
binds on behalf of a regular application process. An earlier changed
stored this "attributed" process in the AppBindRecord; here, retrieve
it, and use that to compute the priority of the sandbox instead.

Additionally, keep track of started SDK sandboxes per UID, so that we
can retrieve them when computing the downstream dependencies of
applications in collectReachableProcessesLocked().

Bug: 253399592
Test: atest SdkSandboxLifecycleHostTest
Test: evaluate OOM adj scores
Change-Id: Ib0696c55e7c0c16c3ba2d19d861098bd2e3ebd21
parent 854a3d2d
Loading
Loading
Loading
Loading
+47 −2
Original line number Original line Diff line number Diff line
@@ -143,6 +143,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayDeque;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.List;


/**
/**
 * All of the code required to compute proc states and oom_adj values.
 * All of the code required to compute proc states and oom_adj values.
@@ -743,6 +744,45 @@ public class OomAdjuster {
                queue.offer(provider);
                queue.offer(provider);
                provider.mState.setReachable(true);
                provider.mState.setReachable(true);
            }
            }
            // See if this process has any corresponding SDK sandbox processes running, and if so
            // scan them as well.
            final List<ProcessRecord> 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<IBinder, ArrayList<ConnectionRecord>> serviceConnections =
                            s.getConnections();
                    for (int conni = serviceConnections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> 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();
        int size = processes.size();
@@ -2131,6 +2171,11 @@ public class OomAdjuster {
                    boolean trackedProcState = false;
                    boolean trackedProcState = false;


                    ProcessRecord client = cr.binding.client;
                    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;
                    final ProcessStateRecord cstate = client.mState;
                    if (computeClients) {
                    if (computeClients) {
                        computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
                        computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
@@ -2377,12 +2422,12 @@ public class OomAdjuster {
                            state.setAdjType(adjType);
                            state.setAdjType(adjType);
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                            state.setAdjTypeCode(ActivityManager.RunningAppProcessInfo
                                    .REASON_SERVICE_IN_USE);
                                    .REASON_SERVICE_IN_USE);
                            state.setAdjSource(cr.binding.client);
                            state.setAdjSource(client);
                            state.setAdjSourceProcState(clientProcState);
                            state.setAdjSourceProcState(clientProcState);
                            state.setAdjTarget(s.instanceName);
                            state.setAdjTarget(s.instanceName);
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                            if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
                                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                reportOomAdjMessageLocked(TAG_OOM_ADJ, "Raise to " + adjType
                                        + ": " + app + ", due to " + cr.binding.client
                                        + ": " + app + ", due to " + client
                                        + " adj=" + adj + " procState="
                                        + " adj=" + adj + " procState="
                                        + ProcessList.makeProcStateString(procState));
                                        + ProcessList.makeProcStateString(procState));
                            }
                            }
+37 −0
Original line number Original line Diff line number Diff line
@@ -484,6 +484,12 @@ public final class ProcessList {
    @GuardedBy("mService")
    @GuardedBy("mService")
    final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>();
    final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>();


    /**
     * The currently running SDK sandbox processes for a uid.
     */
    @GuardedBy("mService")
    final SparseArray<ArrayList<ProcessRecord>> mSdkSandboxes = new SparseArray<>();

    /**
    /**
     * Managees the {@link android.app.ApplicationExitInfo} records.
     * Managees the {@link android.app.ApplicationExitInfo} records.
     */
     */
@@ -2990,6 +2996,14 @@ public final class ProcessList {
        if (proc.isolated) {
        if (proc.isolated) {
            mIsolatedProcesses.put(proc.uid, proc);
            mIsolatedProcesses.put(proc.uid, proc);
        }
        }
        if (proc.isSdkSandbox) {
            ArrayList<ProcessRecord> sdkSandboxes = mSdkSandboxes.get(proc.uid);
            if (sdkSandboxes == null) {
                sdkSandboxes = new ArrayList<>();
            }
            sdkSandboxes.add(proc);
            mSdkSandboxes.put(Process.getAppUidForSdkSandboxUid(proc.uid), sdkSandboxes);
        }
    }
    }


    @GuardedBy("mService")
    @GuardedBy("mService")
@@ -3030,6 +3044,19 @@ public final class ProcessList {
        return ret;
        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<ProcessRecord> getSdkSandboxProcessesForAppLocked(int uid) {
        return mSdkSandboxes.get(uid);
    }

    @GuardedBy("mService")
    @GuardedBy("mService")
    ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
    ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
            boolean isolated, int isolatedUid, boolean isSdkSandbox, int sdkSandboxUid,
            boolean isolated, int isolatedUid, boolean isSdkSandbox, int sdkSandboxUid,
@@ -3135,6 +3162,16 @@ public final class ProcessList {
        if (record != null && record.appZygote) {
        if (record != null && record.appZygote) {
            removeProcessFromAppZygoteLocked(record);
            removeProcessFromAppZygoteLocked(record);
        }
        }
        if (record != null && record.isSdkSandbox) {
            final int appUid = Process.getAppUidForSdkSandboxUid(uid);
            final ArrayList<ProcessRecord> sdkSandboxesForUid = mSdkSandboxes.get(appUid);
            if (sdkSandboxesForUid != null) {
                sdkSandboxesForUid.remove(record);
                if (sdkSandboxesForUid.size() == 0) {
                    mSdkSandboxes.remove(appUid);
                }
            }
        }
        mAppsInBackgroundRestricted.remove(record);
        mAppsInBackgroundRestricted.remove(record);


        return old;
        return old;