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

Commit 52b46b4b authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am de2d961f: am fbefe9bf: Merge "Fix issue #11168649: LRU logic for Chrome...

am de2d961f: am fbefe9bf: Merge "Fix issue #11168649: LRU logic for Chrome renderers seems..." into klp-dev

* commit 'de2d961f':
  Fix issue #11168649: LRU logic for Chrome renderers seems...
parents ee3b039a de2d961f
Loading
Loading
Loading
Loading
+53 −2
Original line number Diff line number Diff line
@@ -564,7 +564,7 @@ public final class ActiveServices {
                    if (r.isForeground) {
                        r.isForeground = false;
                        if (r.app != null) {
                            mAm.updateLruProcessLocked(r.app, false, false);
                            mAm.updateLruProcessLocked(r.app, false, null);
                            updateServiceForegroundLocked(r.app, true);
                        }
                    }
@@ -597,6 +597,42 @@ public final class ActiveServices {
        }
    }

    private boolean updateServiceClientActivitiesLocked(ProcessRecord proc,
            ConnectionRecord modCr) {
        if (modCr != null && modCr.binding.client != null) {
            if (modCr.binding.client.activities.size() <= 0) {
                // This connection is from a client without activities, so adding
                // and removing is not interesting.
                return false;
            }
        }

        boolean anyClientActivities = false;
        for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) {
            ServiceRecord sr = proc.services.valueAt(i);
            for (int conni=sr.connections.size()-1; conni>=0 && !anyClientActivities; conni--) {
                ArrayList<ConnectionRecord> clist = sr.connections.valueAt(conni);
                for (int cri=clist.size()-1; cri>=0; cri--) {
                    ConnectionRecord cr = clist.get(cri);
                    if (cr.binding.client == null || cr.binding.client == proc) {
                        // Binding to ourself is not interesting.
                        continue;
                    }
                    if (cr.binding.client.activities.size() > 0) {
                        anyClientActivities = true;
                        break;
                    }
                }
            }
        }
        if (anyClientActivities != proc.hasClientActivities) {
            proc.hasClientActivities = anyClientActivities;
            mAm.updateLruProcessLocked(proc, anyClientActivities, null);
            return true;
        }
        return false;
    }

    int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
@@ -698,6 +734,9 @@ public final class ActiveServices {
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c);
            }
            clist = mServiceConnections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
@@ -714,6 +753,7 @@ public final class ActiveServices {

            if (s.app != null) {
                // This could have made the service more important.
                mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities, b.client);
                mAm.updateOomAdjLocked(s.app);
            }

@@ -1316,7 +1356,8 @@ public final class ActiveServices {

        app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, true, false);
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
@@ -1601,6 +1642,9 @@ public final class ActiveServices {
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.updateHasAboveClientLocked();
            }
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c);
            }
        }
        clist = mServiceConnections.get(binder);
        if (clist != null) {
@@ -1621,6 +1665,13 @@ public final class ActiveServices {
                    && b.intent.hasBound) {
                try {
                    bumpServiceExecutingLocked(s, false, "unbind");
                    if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0
                            && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) {
                        // If this service's process is not already in the cached list,
                        // then update it in the LRU list here because this may be causing
                        // it to go down there and we want it to start out near the top.
                        mAm.updateLruProcessLocked(s.app, false, null);
                    }
                    mAm.updateOomAdjLocked(s.app);
                    b.intent.hasBound = false;
                    // Assume the client doesn't want to know about a rebind;
+161 −69
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.ProcessStats;
import com.android.internal.app.ResolverActivity;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
@@ -218,6 +217,7 @@ public final class ActivityManagerService extends ActivityManagerNative
    static final boolean DEBUG_IMMERSIVE = localLOGV || false;
    static final boolean DEBUG_MU = localLOGV || false;
    static final boolean DEBUG_OOM_ADJ = localLOGV || false;
    static final boolean DEBUG_LRU = localLOGV || false;
    static final boolean DEBUG_PAUSE = localLOGV || false;
    static final boolean DEBUG_POWER = localLOGV || false;
    static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
@@ -1743,7 +1743,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                synchronized (mSelf.mPidsSelfLocked) {
                    mSelf.mPidsSelfLocked.put(app.pid, app);
                }
                mSelf.updateLruProcessLocked(app, true, false);
                mSelf.updateLruProcessLocked(app, false, null);
                mSelf.updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
@@ -2269,7 +2270,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        int lrui = mLruProcesses.lastIndexOf(app);
        if (lrui < 0) {
            Log.wtf(TAG, "Adding dependent process " + app + " not on LRU list: "
            Slog.wtf(TAG, "Adding dependent process " + app + " not on LRU list: "
                    + what + " " + obj + " from " + srcApp);
            return index;
        }
@@ -2289,6 +2290,8 @@ public final class ActivityManagerService extends ActivityManagerNative
        if (index > 0) {
            index--;
        }
        if (DEBUG_LRU) Slog.d(TAG, "Moving dep from " + lrui + " to " + index
                + " in LRU list: " + app);
        mLruProcesses.add(index, app);
        return index;
    }
@@ -2306,8 +2309,9 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
    }
    final void updateLruProcessLocked(ProcessRecord app, boolean oomAdj, boolean activityChange) {
        final boolean hasActivity = app.activities.size() > 0;
    final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
            ProcessRecord client) {
        final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities;
        final boolean hasService = false; // not impl yet. app.services.size() > 0;
        if (!activityChange && hasActivity) {
            // The process has activties, so we are only going to allow activity-based
@@ -2321,8 +2325,65 @@ public final class ActivityManagerService extends ActivityManagerNative
        final long now = SystemClock.uptimeMillis();
        app.lastActivityTime = now;
        // First a quick reject: if the app is already at the position we will
        // put it, then there is nothing to do.
        if (hasActivity) {
            final int N = mLruProcesses.size();
            if (N > 0 && mLruProcesses.get(N-1) == app) {
                if (DEBUG_LRU) Slog.d(TAG, "Not moving, already top activity: " + app);
                return;
            }
        } else {
            if (mLruProcessServiceStart > 0
                    && mLruProcesses.get(mLruProcessServiceStart-1) == app) {
                if (DEBUG_LRU) Slog.d(TAG, "Not moving, already top other: " + app);
                return;
            }
        }
        int lrui = mLruProcesses.lastIndexOf(app);
        if (app.persistent && lrui >= 0) {
            // We don't care about the position of persistent processes, as long as
            // they are in the list.
            if (DEBUG_LRU) Slog.d(TAG, "Not moving, persistent: " + app);
            return;
        }
        /* In progress: compute new position first, so we can avoid doing work
           if the process is not actually going to move.  Not yet working.
        int addIndex;
        int nextIndex;
        boolean inActivity = false, inService = false;
        if (hasActivity) {
            // Process has activities, put it at the very tipsy-top.
            addIndex = mLruProcesses.size();
            nextIndex = mLruProcessServiceStart;
            inActivity = true;
        } else if (hasService) {
            // Process has services, put it at the top of the service list.
            addIndex = mLruProcessActivityStart;
            nextIndex = mLruProcessServiceStart;
            inActivity = true;
            inService = true;
        } else  {
            // Process not otherwise of interest, it goes to the top of the non-service area.
            addIndex = mLruProcessServiceStart;
            if (client != null) {
                int clientIndex = mLruProcesses.lastIndexOf(client);
                if (clientIndex < 0) Slog.d(TAG, "Unknown client " + client + " when updating "
                        + app);
                if (clientIndex >= 0 && addIndex > clientIndex) {
                    addIndex = clientIndex;
                }
            }
            nextIndex = addIndex > 0 ? addIndex-1 : addIndex;
        }
        Slog.d(TAG, "Update LRU at " + lrui + " to " + addIndex + " (act="
                + mLruProcessActivityStart + "): " + app);
        */
        if (lrui >= 0) {
            if (lrui < mLruProcessActivityStart) {
                mLruProcessActivityStart--;
@@ -2330,23 +2391,91 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (lrui < mLruProcessServiceStart) {
                mLruProcessServiceStart--;
            }
            /*
            if (addIndex > lrui) {
                addIndex--;
            }
            if (nextIndex > lrui) {
                nextIndex--;
            }
            */
            mLruProcesses.remove(lrui);
        }
        /*
        mLruProcesses.add(addIndex, app);
        if (inActivity) {
            mLruProcessActivityStart++;
        }
        if (inService) {
            mLruProcessActivityStart++;
        }
        */
        int nextIndex;
        if (hasActivity) {
            final int N = mLruProcesses.size();
            if (app.activities.size() == 0 && mLruProcessActivityStart < (N-1)) {
                // Process doesn't have activities, but has clients with
                // activities...  move it up, but one below the top (the top
                // should always have a real activity).
                if (DEBUG_LRU) Slog.d(TAG, "Adding to second-top of LRU activity list: " + app);
                mLruProcesses.add(N-1, app);
                // To keep it from spamming the LRU list (by making a bunch of clients),
                // we will push down any other entries owned by the app.
                final int uid = app.info.uid;
                for (int i=N-2; i>mLruProcessActivityStart; i--) {
                    ProcessRecord subProc = mLruProcesses.get(i);
                    if (subProc.info.uid == uid) {
                        // We want to push this one down the list.  If the process after
                        // it is for the same uid, however, don't do so, because we don't
                        // want them internally to be re-ordered.
                        if (mLruProcesses.get(i-1).info.uid != uid) {
                            if (DEBUG_LRU) Slog.d(TAG, "Pushing uid " + uid + " swapping at " + i
                                    + ": " + mLruProcesses.get(i) + " : " + mLruProcesses.get(i-1));
                            ProcessRecord tmp = mLruProcesses.get(i);
                            mLruProcesses.set(i, mLruProcesses.get(i-1));
                            mLruProcesses.set(i-1, tmp);
                            i--;
                        }
                    } else {
                        // A gap, we can stop here.
                        break;
                    }
                }
            } else {
                // Process has activities, put it at the very tipsy-top.
                if (DEBUG_LRU) Slog.d(TAG, "Adding to top of LRU activity list: " + app);
                mLruProcesses.add(app);
            nextIndex = mLruProcessActivityStart;
            }
            nextIndex = mLruProcessServiceStart;
        } else if (hasService) {
            // Process has services, put it at the top of the service list.
            if (DEBUG_LRU) Slog.d(TAG, "Adding to top of LRU service list: " + app);
            mLruProcesses.add(mLruProcessActivityStart, app);
            nextIndex = mLruProcessServiceStart;
            mLruProcessActivityStart++;
        } else  {
            // Process not otherwise of interest, it goes to the top of the non-service area.
            mLruProcesses.add(mLruProcessServiceStart, app);
            nextIndex = mLruProcessServiceStart-1;
            int index = mLruProcessServiceStart;
            if (client != null) {
                // If there is a client, don't allow the process to be moved up higher
                // in the list than that client.
                int clientIndex = mLruProcesses.lastIndexOf(client);
                if (DEBUG_LRU && clientIndex < 0) Slog.d(TAG, "Unknown client " + client
                        + " when updating " + app);
                if (clientIndex <= lrui) {
                    // Don't allow the client index restriction to push it down farther in the
                    // list than it already is.
                    clientIndex = lrui;
                }
                if (clientIndex >= 0 && index > clientIndex) {
                    index = clientIndex;
                }
            }
            if (DEBUG_LRU) Slog.d(TAG, "Adding at " + index + " of LRU list: " + app);
            mLruProcesses.add(index, app);
            nextIndex = index-1;
            mLruProcessActivityStart++;
            mLruProcessServiceStart++;
        }
@@ -2357,23 +2486,19 @@ public final class ActivityManagerService extends ActivityManagerNative
            ConnectionRecord cr = app.connections.valueAt(j);
            if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
                    && cr.binding.service.app != null
                    && cr.binding.service.app.lruSeq != mLruSeq) {
                    && cr.binding.service.app.lruSeq != mLruSeq
                    && !cr.binding.service.app.persistent) {
                nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
                        "service connection", cr, app);
            }
        }
        for (int j=app.conProviders.size()-1; j>=0; j--) {
            ContentProviderRecord cpr = app.conProviders.get(j).provider;
            if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq) {
            if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) {
                nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
                        "provider reference", cpr, app);
            }
        }
        //Slog.i(TAG, "Putting proc to front: " + app.processName);
        if (oomAdj) {
            updateOomAdjLocked();
        }
    }
    final ProcessRecord getProcessRecordLocked(String processName, int uid, boolean keepIfLarge) {
@@ -4831,7 +4956,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            updateLruProcessLocked(app, false, false);
            updateLruProcessLocked(app, false, null);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            // todo: Yikes!  What should we do?  For now we will try to
@@ -7419,7 +7544,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                        // make sure to count it as being accessed and thus
                        // back up on the LRU list.  This is good because
                        // content providers are often expensive to start.
                        updateLruProcessLocked(cpr.proc, false, false);
                        updateLruProcessLocked(cpr.proc, false, null);
                    }
                }
@@ -8028,7 +8153,8 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (isolated) {
                mIsolatedProcesses.put(app.uid, app);
            }
            updateLruProcessLocked(app, true, false);
            updateLruProcessLocked(app, false, null);
            updateOomAdjLocked();
        }
        // This package really, really can not be stopped.
@@ -10101,7 +10227,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        if (app.persistent) {
            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
        }
        if (app.hasActivities) {
        if (app.activities.size() > 0) {
            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_HAS_ACTIVITIES;
        }
        outInfo.lastTrimLevel = app.trimMemoryLevel;
@@ -11857,7 +11983,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                thread = r.thread;
                pid = r.pid;
                oomAdj = r.getSetAdjWithServices();
                hasActivities = r.hasActivities;
                hasActivities = r.activities.size() > 0;
            }
            if (thread != null) {
                if (!isCheckinRequest && dumpDetails) {
@@ -14079,7 +14205,6 @@ public final class ActivityManagerService extends ActivityManagerNative
        app.adjTarget = null;
        app.empty = false;
        app.cached = false;
        app.hasClientActivities = false;
        final int activitiesSize = app.activities.size();
@@ -14089,7 +14214,6 @@ public final class ActivityManagerService extends ActivityManagerNative
            app.adjType = "fixed";
            app.adjSeq = mAdjSeq;
            app.curRawAdj = app.maxAdj;
            app.hasActivities = false;
            app.foregroundActivities = false;
            app.keeping = true;
            app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
@@ -14101,16 +14225,12 @@ public final class ActivityManagerService extends ActivityManagerNative
            app.systemNoUi = true;
            if (app == TOP_APP) {
                app.systemNoUi = false;
                app.hasActivities = true;
            } else if (activitiesSize > 0) {
                for (int j = 0; j < activitiesSize; j++) {
                    final ActivityRecord r = app.activities.get(j);
                    if (r.visible) {
                        app.systemNoUi = false;
                    }
                    if (r.app == app) {
                        app.hasActivities = true;
                    }
                }
            }
            if (!app.systemNoUi) {
@@ -14121,7 +14241,6 @@ public final class ActivityManagerService extends ActivityManagerNative
        app.keeping = false;
        app.systemNoUi = false;
        app.hasActivities = false;
        // Determine the importance of the process, starting with most
        // important to least, and assign an appropriate OOM adjustment.
@@ -14138,7 +14257,6 @@ public final class ActivityManagerService extends ActivityManagerNative
            app.adjType = "top-activity";
            foregroundActivities = true;
            interesting = true;
            app.hasActivities = true;
            procState = ActivityManager.PROCESS_STATE_TOP;
        } else if (app.instrumentationClass != null) {
            // Don't want to kill running instrumentation.
@@ -14187,7 +14305,6 @@ public final class ActivityManagerService extends ActivityManagerNative
                            + app + "?!?");
                    continue;
                }
                app.hasActivities = true;
                if (r.visible) {
                    // App has a visible activity; only upgrade adjustment.
                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
@@ -14436,27 +14553,6 @@ public final class ActivityManagerService extends ActivityManagerNative
                                    clientAdj = adj;
                                }
                            }
                        } else if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
                            if ((cr.flags&Context.BIND_NOT_VISIBLE) == 0) {
                                // If this connection is keeping the service
                                // created, then we want to try to better follow
                                // its memory management semantics for activities.
                                // That is, if it is sitting in the background
                                // LRU list as a cached process (with activities),
                                // we don't want the service it is connected to
                                // to go into the empty LRU and quickly get killed,
                                // because all we'll do is just end up restarting
                                // the service.
                                if (client.hasActivities) {
                                    if (procState >
                                            ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT) {
                                        procState =
                                                ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
                                        app.adjType = "cch-client-act";
                                    }
                                    app.hasClientActivities = true;
                                }
                            }
                        }
                        if (adj > clientAdj) {
                            // If this process has recently shown UI, and
@@ -14674,6 +14770,12 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
        }
        if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY && app.hasClientActivities) {
            // This is a cached process, but with client activities.  Mark it so.
            procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
            app.adjType = "cch-client-act";
        }
        if (adj == ProcessList.SERVICE_ADJ) {
            if (doingAll) {
                app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
@@ -15302,7 +15404,6 @@ public final class ActivityManagerService extends ActivityManagerNative
        // application processes based on their current state.
        int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextCachedAdj = curCachedAdj+1;
        int curClientCachedAdj = curCachedAdj+1;
        int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
        int nextEmptyAdj = curEmptyAdj+2;
        for (int i=N-1; i>=0; i--) {
@@ -15317,11 +15418,15 @@ public final class ActivityManagerService extends ActivityManagerNative
                if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
                    switch (app.curProcState) {
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                            // This process is a cached process holding activities...
                            // assign it the next cached value for that type, and then
                            // step that cached level.
                            app.curRawAdj = curCachedAdj;
                            app.curAdj = app.modifyRawOomAdj(curCachedAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG, "Assigning activity LRU #" + i
                                    + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
                                    + ")");
                            if (curCachedAdj != nextCachedAdj) {
                                stepCached++;
                                if (stepCached >= cachedFactor) {
@@ -15331,24 +15436,8 @@ public final class ActivityManagerService extends ActivityManagerNative
                                    if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                        nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                    }
                                    if (curClientCachedAdj <= curCachedAdj) {
                                        curClientCachedAdj = curCachedAdj + 1;
                                        if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                            curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                                        }
                                }
                            }
                            }
                            break;
                        case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
                            // Special case for cached client processes...  just step
                            // down from after regular cached processes.
                            app.curRawAdj = curClientCachedAdj;
                            app.curAdj = app.modifyRawOomAdj(curClientCachedAdj);
                            curClientCachedAdj++;
                            if (curClientCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
                                curClientCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
                            }
                            break;
                        default:
                            // For everything else, assign next empty cached process
@@ -15358,6 +15447,9 @@ public final class ActivityManagerService extends ActivityManagerNative
                            // state is still as a service), which is what we want.
                            app.curRawAdj = curEmptyAdj;
                            app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
                            if (DEBUG_LRU && false) Slog.d(TAG, "Assigning empty LRU #" + i
                                    + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
                                    + ")");
                            if (curEmptyAdj != nextEmptyAdj) {
                                stepEmpty++;
                                if (stepEmpty >= emptyFactor) {
Loading