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

Commit 7258ae54 authored by Jing Ji's avatar Jing Ji
Browse files

Add extra delays to service restarts in case of low memory pressure

When the system is on low memory pressure, service restarts could make
the performance worse. Now addinng extra delays in this case; while
when the memory pressure drops, the delays will be decreased too.

BYPASS_INCLUSIVE_LANGUAGE_REASON=legacy API name

Bug: 170309420
Test: atest FrameworksServicesTests:ServiceRestarterTest
Test: atest FrameworksMockingServicesTests:ActiveServicesTest
Change-Id: Ic55276775950316bde199ab017916e8efbee7a73
parent b5fa3eaa
Loading
Loading
Loading
Loading
+233 −28
Original line number Diff line number Diff line
@@ -153,7 +153,6 @@ import android.webkit.WebViewZygote;

import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ServiceState;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.notification.SystemNotificationChannels;
@@ -165,6 +164,7 @@ import com.android.server.AppStateTracker;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.am.ActivityManagerService.ItemMatcher;
import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.uri.NeededUriGrants;
import com.android.server.wm.ActivityServiceConnectionsHolder;

@@ -174,6 +174,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
@@ -3487,6 +3488,8 @@ public final class ActiveServices {
        final long now = SystemClock.uptimeMillis();

        final String reason;
        final int oldPosInRestarting = mRestartingServices.indexOf(r);
        boolean inRestarting = oldPosInRestarting != -1;
        if ((r.serviceInfo.applicationInfo.flags
                &ApplicationInfo.FLAG_PERSISTENT) == 0) {
            long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION;
@@ -3554,58 +3557,89 @@ public final class ActiveServices {
            }

            if (isServiceRestartBackoffEnabledLocked(r.packageName)) {
                r.nextRestartTime = now + r.restartDelay;
                r.nextRestartTime = r.mEarliestRestartTime = now + r.restartDelay;

                if (inRestarting) {
                    // Take it out of the list temporarily for easier maintenance of the list.
                    mRestartingServices.remove(oldPosInRestarting);
                    inRestarting = false;
                }
                if (mRestartingServices.isEmpty()) {
                    // Apply the extra delay even if it's the only one in the list.
                    final long extraDelay = getExtraRestartTimeInBetweenLocked();
                    r.nextRestartTime = Math.max(now + extraDelay, r.nextRestartTime);
                    r.restartDelay = r.nextRestartTime - now;
                } else {
                    // Make sure that we don't end up restarting a bunch of services
                    // all at the same time.
                    boolean repeat;
                final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
                    final long restartTimeBetween = getExtraRestartTimeInBetweenLocked()
                            + mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
                    do {
                        repeat = false;
                        final long nextRestartTime = r.nextRestartTime;
                        // mRestartingServices is sorted by nextRestartTime.
                        for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
                            final ServiceRecord r2 = mRestartingServices.get(i);
                        if (r2 != r
                                && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)
                                && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {
                            r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
                            final long nextRestartTime2 = r2.nextRestartTime;
                            if (nextRestartTime >= (nextRestartTime2 - restartTimeBetween)
                                    && nextRestartTime < (nextRestartTime2 + restartTimeBetween)) {
                                r.nextRestartTime = nextRestartTime2 + restartTimeBetween;
                                r.restartDelay = r.nextRestartTime - now;
                                repeat = true;
                                break;
                            } else if (nextRestartTime >= nextRestartTime2 + restartTimeBetween) {
                                // This spot fulfills our needs, bail out.
                                break;
                            }
                        }
                    } while (repeat);
                }
            } else {
                // It's been forced to ignore the restart backoff, fix the delay here.
                r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;
                r.nextRestartTime = now + r.restartDelay;
            }

        } else {
            // Persistent processes are immediately restarted, so there is no
            // reason to hold of on restarting their services.
            r.totalRestartCount++;
            r.restartCount = 0;
            r.restartDelay = 0;
            r.mEarliestRestartTime = 0;
            r.nextRestartTime = now;
            reason = "persistent";
        }

        if (!mRestartingServices.contains(r)) {
        r.mRestartSchedulingTime = now;
        if (!inRestarting) {
            if (oldPosInRestarting == -1) {
                r.createdFromFg = false;
            mRestartingServices.add(r);
                synchronized (mAm.mProcessStats.mLock) {
                    r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
                }
            }
            boolean added = false;
            for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
                final ServiceRecord r2 = mRestartingServices.get(i);
                if (r2.nextRestartTime > r.nextRestartTime) {
                    mRestartingServices.add(i, r);
                    added = true;
                    break;
                }
            }
            if (!added) {
                mRestartingServices.add(r);
            }
        }

        cancelForegroundNotificationLocked(r);

        performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis());
        performScheduleRestartLocked(r, "Scheduling", reason, now);

        return true;
    }

    @VisibleForTesting
    @GuardedBy("mAm")
    void performScheduleRestartLocked(ServiceRecord r, @NonNull String scheduling,
            @NonNull String reason, @UptimeMillisLong long now) {
@@ -3618,6 +3652,161 @@ public final class ActiveServices {
                r.userId, r.shortInstanceName, r.restartDelay);
    }

    /**
     * Reschedule service restarts based on the given memory pressure.
     *
     * @param prevMemFactor The previous memory factor.
     * @param curMemFactor The current memory factor.
     * @param reason The human-readable text about why we're doing rescheduling.
     * @param now The uptimeMillis
     */
    @GuardedBy("mAm")
    void rescheduleServiceRestartOnMemoryPressureIfNeededLocked(@MemFactor int prevMemFactor,
            @MemFactor int curMemFactor, @NonNull String reason, @UptimeMillisLong long now) {
        final boolean enabled = mAm.mConstants.mEnableExtraServiceRestartDelayOnMemPressure;
        if (!enabled) {
            return;
        }
        performRescheduleServiceRestartOnMemoryPressureLocked(
                mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[prevMemFactor],
                mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[curMemFactor], reason, now);
    }

    /**
     * Reschedule service restarts based on if the extra delays are enabled or not.
     *
     * @param prevEnable The previous state of whether or not it's enabled.
     * @param curEnabled The current state of whether or not it's enabled.
     * @param now The uptimeMillis
     */
    @GuardedBy("mAm")
    void rescheduleServiceRestartOnMemoryPressureIfNeededLocked(boolean prevEnabled,
            boolean curEnabled, @UptimeMillisLong long now) {
        if (prevEnabled == curEnabled) {
            return;
        }
        final @MemFactor int memFactor = mAm.mAppProfiler.getLastMemoryLevelLocked();
        final long delay = mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
        performRescheduleServiceRestartOnMemoryPressureLocked(prevEnabled ? delay : 0,
                curEnabled ? delay : 0, "config", now);
    }

    /**
     * Rescan the list of pending restarts, reschedule them if needed.
     *
     * @param extraRestartTimeBetween The extra interval between restarts.
     * @param minRestartTimeBetween The minimal interval between restarts.
     * @param reason The human-readable text about why we're doing rescheduling.
     * @param now The uptimeMillis
     */
    @GuardedBy("mAm")
    void rescheduleServiceRestartIfPossibleLocked(long extraRestartTimeBetween,
            long minRestartTimeBetween, @NonNull String reason, @UptimeMillisLong long now) {
        final long restartTimeBetween = extraRestartTimeBetween + minRestartTimeBetween;
        final long spanForInsertOne = restartTimeBetween * 2; // Min space to insert a restart.

        long lastRestartTime = now;
        int lastRestartTimePos = -1; // The list index where the "lastRestartTime" comes from.
        for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
            final ServiceRecord r = mRestartingServices.get(i);
            if ((r.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
                    || !isServiceRestartBackoffEnabledLocked(r.packageName)) {
                lastRestartTime = r.nextRestartTime;
                lastRestartTimePos = i;
                continue;
            }
            if (lastRestartTime + restartTimeBetween <= r.mEarliestRestartTime) {
                // Bounded by the earliest restart time, honor it; but we also need to
                // check if the interval between the earlist and its prior one is enough or not.
                r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime, i > 0
                        ? mRestartingServices.get(i - 1).nextRestartTime + restartTimeBetween
                        : 0));
            } else {
                if (lastRestartTime <= now) {
                    // It hasn't moved, this is the first one (besides persistent process),
                    // we don't need to insert the minRestartTimeBetween for it, but need
                    // the extraRestartTimeBetween still.
                    r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime,
                            r.mRestartSchedulingTime + extraRestartTimeBetween));
                } else {
                    r.nextRestartTime = Math.max(now, lastRestartTime + restartTimeBetween);
                }
                if (i > lastRestartTimePos + 1) {
                    // Move the current service record ahead in the list.
                    mRestartingServices.remove(i);
                    mRestartingServices.add(lastRestartTimePos + 1, r);
                }
            }
            // Find the next available slot to insert one if there is any
            for (int j = lastRestartTimePos + 1; j <= i; j++) {
                final ServiceRecord r2 = mRestartingServices.get(j);
                final long timeInBetween = r2.nextRestartTime - (j == 0 ? lastRestartTime
                        : mRestartingServices.get(j - 1).nextRestartTime);
                if (timeInBetween >= spanForInsertOne) {
                    break;
                }
                lastRestartTime = r2.nextRestartTime;
                lastRestartTimePos = j;
            }
            r.restartDelay = r.nextRestartTime - now;
            performScheduleRestartLocked(r, "Rescheduling", reason, now);
        }
    }

    @GuardedBy("mAm")
    void performRescheduleServiceRestartOnMemoryPressureLocked(long oldExtraDelay,
            long newExtraDelay, @NonNull String reason, @UptimeMillisLong long now) {
        final long delta = newExtraDelay - oldExtraDelay;
        if (delta == 0) {
            return;
        }
        if (delta > 0) {
            final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN
                    + newExtraDelay;
            long lastRestartTime = now;
            // Make the delay in between longer.
            for (int i = 0, size = mRestartingServices.size(); i < size; i++) {
                final ServiceRecord r = mRestartingServices.get(i);
                if ((r.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0
                        || !isServiceRestartBackoffEnabledLocked(r.packageName)) {
                    lastRestartTime = r.nextRestartTime;
                    continue;
                }
                boolean reschedule = false;
                if (lastRestartTime <= now) {
                    // It hasn't moved, this is the first one (besides persistent process),
                    // we don't need to insert the minRestartTimeBetween for it, but need
                    // the newExtraDelay still.
                    final long oldVal = r.nextRestartTime;
                    r.nextRestartTime = Math.max(now, Math.max(r.mEarliestRestartTime,
                            r.mRestartSchedulingTime + newExtraDelay));
                    reschedule = r.nextRestartTime != oldVal;
                } else if (r.nextRestartTime - lastRestartTime < restartTimeBetween) {
                    r.nextRestartTime = Math.max(lastRestartTime + restartTimeBetween, now);
                    reschedule = true;
                }
                r.restartDelay = r.nextRestartTime - now;
                lastRestartTime = r.nextRestartTime;
                if (reschedule) {
                    performScheduleRestartLocked(r, "Rescheduling", reason, now);
                }
            }
        } else if (delta < 0) {
            // Make the delay in between shorter, we'd do a rescan and reschedule.
            rescheduleServiceRestartIfPossibleLocked(newExtraDelay,
                    mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN, reason, now);
        }
    }

    @GuardedBy("mAm")
    long getExtraRestartTimeInBetweenLocked() {
        if (!mAm.mConstants.mEnableExtraServiceRestartDelayOnMemPressure) {
            return 0;
        }
        final @MemFactor int memFactor = mAm.mAppProfiler.getLastMemoryLevelLocked();
        return mAm.mConstants.mExtraServiceRestartDelayOnMemPressure[memFactor];
    }

    final void performServiceRestartLocked(ServiceRecord r) {
        if (!mRestartingServices.contains(r)) {
            return;
@@ -3706,6 +3895,9 @@ public final class ActiveServices {
                        performScheduleRestartLocked(r, "Rescheduling", reason, now);
                    }
                }
                // mRestartingServices is sorted by nextRestartTime.
                Collections.sort(mRestartingServices,
                        (a, b) -> (int) (a.nextRestartTime - b.nextRestartTime));
            }
        } else {
            removeServiceRestartBackoffEnabledLocked(packageName);
@@ -4683,6 +4875,7 @@ public final class ActiveServices {
        // run at this point just because their restart time hasn't come up.
        if (mRestartingServices.size() > 0) {
            ServiceRecord sr;
            boolean didImmediateRestart = false;
            for (int i=0; i<mRestartingServices.size(); i++) {
                sr = mRestartingServices.get(i);
                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
@@ -4691,6 +4884,18 @@ public final class ActiveServices {
                }
                mAm.mHandler.removeCallbacks(sr.restarter);
                mAm.mHandler.post(sr.restarter);
                didImmediateRestart = true;
            }
            if (didImmediateRestart) {
                // Since we kicked off all its pending restarts, there could be some open slots
                // in the pending restarts list, schedule a check on it. We are posting to the same
                // handler, so by the time of the check, those immediate restarts should be done.
                mAm.mHandler.post(() ->
                        rescheduleServiceRestartIfPossibleLocked(
                                getExtraRestartTimeInBetweenLocked(),
                                mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN,
                                "other", SystemClock.uptimeMillis())
                );
            }
        }
        return didSomething;
+92 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;

import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;

import android.annotation.NonNull;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -31,6 +32,7 @@ import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.PowerExemptionManager;
import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DeviceConfig.Properties;
@@ -40,6 +42,8 @@ import android.util.ArraySet;
import android.util.KeyValueListParser;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;

import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
@@ -109,6 +113,10 @@ final class ActivityManagerConstants extends ContentObserver {
    static final String KEY_FGS_START_FOREGROUND_TIMEOUT = "fgs_start_foreground_timeout";
    static final String KEY_FGS_ATOM_SAMPLE_RATE = "fgs_atom_sample_rate";
    static final String KEY_FGS_ALLOW_OPT_OUT = "fgs_allow_opt_out";
    static final String KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE =
            "extra_delay_svc_restart_mem_pressure";
    static final String KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE =
            "enable_extra_delay_svc_restart_mem_pressure";

    private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
    private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -159,6 +167,25 @@ final class ActivityManagerConstants extends ContentObserver {
            DEFAULT_PUSH_MESSAGING_OVER_QUOTA_BEHAVIOR = 1;
    private static final boolean DEFAULT_FGS_ALLOW_OPT_OUT = false;

    /**
     * The extra delays we're putting to service restarts, based on current memory pressure.
     */
    private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_NORMAL_MEM = 0; // ms
    private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MODERATE_MEM = 10000; // ms
    private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_LOW_MEM = 20000; // ms
    private static final long DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_CRITICAL_MEM = 30000; // ms
    private static final long[] DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE  = {
        DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_NORMAL_MEM,
        DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MODERATE_MEM,
        DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_LOW_MEM,
        DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_CRITICAL_MEM,
    };

    /**
     * Whether or not to enable the extra delays to service restarts on memory pressure.
     */
    private static final boolean DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE = true;

    // Flag stored in the DeviceConfig API.
    /**
     * Maximum number of cached processes.
@@ -501,6 +528,20 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    volatile boolean mFgsAllowOptOut = DEFAULT_FGS_ALLOW_OPT_OUT;

    /*
     * The extra delays we're putting to service restarts, based on current memory pressure.
     */
    @GuardedBy("mService")
    long[] mExtraServiceRestartDelayOnMemPressure =
            DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;

    /**
     * Whether or not to enable the extra delays to service restarts on memory pressure.
     */
    @GuardedBy("mService")
    boolean mEnableExtraServiceRestartDelayOnMemPressure =
            DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE;

    private final ActivityManagerService mService;
    private ContentResolver mResolver;
    private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -714,6 +755,12 @@ final class ActivityManagerConstants extends ContentObserver {
                            case KEY_FGS_ALLOW_OPT_OUT:
                                updateFgsAllowOptOut();
                                break;
                            case KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE:
                                updateExtraServiceRestartDelayOnMemPressure();
                                break;
                            case KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE:
                                updateEnableExtraServiceRestartDelayOnMemPressure();
                                break;
                            default:
                                break;
                        }
@@ -1064,6 +1111,51 @@ final class ActivityManagerConstants extends ContentObserver {
                DEFAULT_FGS_ALLOW_OPT_OUT);
    }

    private void updateExtraServiceRestartDelayOnMemPressure() {
        synchronized (mService) {
            final int memFactor = mService.mAppProfiler.getLastMemoryLevelLocked();
            final long[] prevDelays = mExtraServiceRestartDelayOnMemPressure;
            mExtraServiceRestartDelayOnMemPressure = parseLongArray(
                    KEY_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
                    DEFAULT_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE);
            mService.mServices.performRescheduleServiceRestartOnMemoryPressureLocked(
                    mExtraServiceRestartDelayOnMemPressure[memFactor],
                    prevDelays[memFactor], "config", SystemClock.uptimeMillis());
        }
    }

    private void updateEnableExtraServiceRestartDelayOnMemPressure() {
        synchronized (mService) {
            final boolean prevEnabled = mEnableExtraServiceRestartDelayOnMemPressure;
            mEnableExtraServiceRestartDelayOnMemPressure = DeviceConfig.getBoolean(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE,
                    DEFAULT_ENABLE_EXTRA_SERVICE_RESTART_DELAY_ON_MEM_PRESSURE);
            mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
                    prevEnabled, mEnableExtraServiceRestartDelayOnMemPressure,
                    SystemClock.uptimeMillis());
        }
    }

    private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
        final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                key, null);
        if (!TextUtils.isEmpty(val)) {
            final String[] ss = val.split(",");
            if (ss.length == def.length) {
                final long[] tmp = new long[ss.length];
                try {
                    for (int i = 0; i < ss.length; i++) {
                        tmp[i] = Long.parseLong(ss[i]);
                    }
                    return tmp;
                } catch (NumberFormatException e) {
                }
            }
        }
        return def;
    }

    private void updateImperceptibleKillExemptions() {
        IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.clear();
        IMPERCEPTIBLE_KILL_EXEMPT_PACKAGES.addAll(mDefaultImperceptibleKillExemptPackages);
+22 −1
Original line number Diff line number Diff line
@@ -393,6 +393,7 @@ public class AppProfiler {
        static final int COLLECT_PSS_BG_MSG = 1;
        static final int DEFER_PSS_MSG = 2;
        static final int STOP_DEFERRING_PSS_MSG = 3;
        static final int MEMORY_PRESSURE_CHANGED = 4;
        BgHandler(Looper looper) {
            super(looper);
        }
@@ -409,6 +410,11 @@ public class AppProfiler {
                case STOP_DEFERRING_PSS_MSG:
                    stopDeferPss();
                    break;
                case MEMORY_PRESSURE_CHANGED:
                    synchronized (mService) {
                        handleMemoryPressureChangedLocked(msg.arg1, msg.arg2);
                    }
                    break;
            }
        }
    }
@@ -912,12 +918,18 @@ public class AppProfiler {
    }

    @GuardedBy("mService")
    int getLastMemoryLevelLocked() {
    @MemFactor int getLastMemoryLevelLocked() {
        if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) {
            return mMemFactorOverride;
        }
        return mLastMemoryLevel;
    }

    @GuardedBy("mService")
    boolean isLastMemoryLevelNormal() {
        if (mMemFactorOverride != ADJ_MEM_FACTOR_NOTHING) {
            return mMemFactorOverride <= ADJ_MEM_FACTOR_NORMAL;
        }
        return mLastMemoryLevel <= ADJ_MEM_FACTOR_NORMAL;
    }

@@ -989,6 +1001,8 @@ public class AppProfiler {
        if (memFactor != mLastMemoryLevel) {
            EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
            FrameworkStatsLog.write(FrameworkStatsLog.MEMORY_FACTOR_STATE_CHANGED, memFactor);
            mBgHandler.obtainMessage(BgHandler.MEMORY_PRESSURE_CHANGED, mLastMemoryLevel, memFactor)
                    .sendToTarget();
        }
        mLastMemoryLevel = memFactor;
        mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
@@ -1636,6 +1650,13 @@ public class AppProfiler {
        }
    }

    @GuardedBy("mService")
    private void handleMemoryPressureChangedLocked(@MemFactor int oldMemFactor,
            @MemFactor int newMemFactor) {
        mService.mServices.rescheduleServiceRestartOnMemoryPressureIfNeededLocked(
                oldMemFactor, newMemFactor, "mem-pressure-event", SystemClock.uptimeMillis());
    }

    @GuardedBy("mProfilerLock")
    private void stopProfilerLPf(ProcessRecord proc, int profileType) {
        if (proc == null || proc == mProfileData.getProfileProc()) {
+24 −4

File changed.

Preview size limit exceeded, changes collapsed.

+284 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading