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

Commit 359263d1 authored by Varun Shah's avatar Varun Shah Committed by Android (Google) Code Review
Browse files

Merge "Optimize service restart logic."

parents d85c59c7 16522412
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -11244,6 +11244,8 @@ public final class Settings {
         * service_max_inactivity               (long)
         * service_bg_start_timeout             (long)
         * process_start_async                  (boolean)
         * use_mem_aware_service_restarts       (boolean)
         * service_restart_delay_duration       (long)
         * </pre>
         *
         * <p>
+85 −26
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import android.util.proto.ProtoOutputStream;
import android.webkit.WebViewZygote;

import com.android.internal.R;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ServiceState;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.notification.SystemNotificationChannels;
@@ -168,6 +169,8 @@ public final class ActiveServices {
    /** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */
    private ArrayList<ServiceRecord> mTmpCollectionResults = null;

    private int mNumServiceRestarts = 0;

    /**
     * For keeping ActiveForegroundApps retaining state while the screen is off.
     */
@@ -2327,6 +2330,8 @@ public final class ActiveServices {
                r.restartDelay = mAm.mConstants.BOUND_SERVICE_CRASH_RESTART_DURATION
                        * (r.crashCount - 1);
            } else {
                mNumServiceRestarts++;
                if (!mAm.mConstants.FLAG_USE_MEM_AWARE_SERVICE_RESTARTS) {
                    // If it has been a "reasonably long time" since the service
                    // was started, then reset our restart duration back to
                    // the beginning, so we don't infinitely increase the duration
@@ -2341,27 +2346,42 @@ public final class ActiveServices {
                            r.restartDelay = minDuration;
                        }
                    }
                } else {
                    // The service will be restarted based on the last known oom_adj value
                    // for the process when it was destroyed. A higher oom_adj value
                    // means that the service will be restarted quicker.
                    // If the service seems to keep crashing, the service restart counter will be
                    // incremented and the restart delay will have an exponential backoff.
                    final int lastOomAdj = r.app == null ? r.lastKnownOomAdj : r.app.setAdj;
                    if (r.restartCount > 1) {
                        r.restartDelay *= mAm.mConstants.SERVICE_RESTART_DURATION_FACTOR;
                        if (r.restartDelay < minDuration) {
                            r.restartDelay = minDuration;
                        }
                    } else {
                        if (lastOomAdj <= ProcessList.VISIBLE_APP_ADJ) {
                            r.restartDelay = 1 * 1000; // 1 second
                        } else if (lastOomAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                            r.restartDelay = 2 * 1000; // 2 seconds
                        } else if (lastOomAdj <= ProcessList.SERVICE_ADJ) {
                            r.restartDelay = 5 * 1000; // 5 seconds
                        } else if (lastOomAdj <= ProcessList.PREVIOUS_APP_ADJ) {
                            r.restartDelay = 10 * 1000; // 10 seconds
                        } else {
                            r.restartDelay = 20 * 1000; // 20 seconds
                        }
                    }
                    // If the last time the service restarted was more than a minute ago,
                    // reset the service restart count, otherwise increment by one.
                    r.restartCount = (now > (r.restartTime + resetTime)) ? 1 : (r.restartCount + 1);
                }
            }

            r.nextRestartTime = now + r.restartDelay;

            // Make sure that we don't end up restarting a bunch of services
            // all at the same time.
            boolean repeat;
            do {
                repeat = false;
                final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
                for (int i=mRestartingServices.size()-1; i>=0; i--) {
                    ServiceRecord r2 = mRestartingServices.get(i);
                    if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween)
                            && r.nextRestartTime < (r2.nextRestartTime+restartTimeBetween)) {
                        r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
                        r.restartDelay = r.nextRestartTime - now;
                        repeat = true;
                        break;
                    }
                }
            } while (repeat);
            ensureSpacedServiceRestarts(r, now);

        } else {
            // Persistent processes are immediately restarted, so there is no
@@ -2391,6 +2411,24 @@ public final class ActiveServices {
        return canceled;
    }

    private void ensureSpacedServiceRestarts(ServiceRecord r, long now) {
        boolean repeat;
        do {
            repeat = false;
            final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN;
            for (int i = mRestartingServices.size() - 1; i >= 0; i--) {
                ServiceRecord r2 = mRestartingServices.get(i);
                if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)
                        && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {
                    r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;
                    r.restartDelay = r.nextRestartTime - now;
                    repeat = true;
                    break;
                }
            }
        } while (repeat);
    }

    final void performServiceRestartLocked(ServiceRecord r) {
        if (!mRestartingServices.contains(r)) {
            return;
@@ -2465,6 +2503,26 @@ public final class ActiveServices {
            return null;
        }

        // If the service is restarting, check the memory pressure - if it's low or critical, then
        // further delay the restart because it will most likely get killed again; if the pressure
        // is not low or critical, continue restarting.
        if (mAm.mConstants.FLAG_USE_MEM_AWARE_SERVICE_RESTARTS && whileRestarting) {
            final int memLevel = mAm.getMemoryTrimLevel();
            if (memLevel >= ProcessStats.ADJ_MEM_FACTOR_LOW) {
                final long now = SystemClock.uptimeMillis();
                // Delay the restart based on the current memory pressure
                // Default delay duration is 5 seconds
                r.restartDelay = memLevel * mAm.mConstants.SERVICE_RESTART_DELAY_DURATION;
                r.nextRestartTime = now + r.restartDelay;
                ensureSpacedServiceRestarts(r, now);
                mAm.mHandler.removeCallbacks(r.restarter);
                mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime);
                Slog.w(TAG, "Delaying restart of crashed service " + r.shortInstanceName
                        + " in " + r.restartDelay + "ms due to continued memory pressure");
                return null;
            }
        }

        if (DEBUG_SERVICE) {
            Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent + " fg=" + r.fgRequired);
        }
@@ -3579,6 +3637,7 @@ public final class ActiveServices {
                    || !mAm.mUserController.isUserRunning(sr.userId, 0)) {
                bringDownServiceLocked(sr);
            } else {
                sr.lastKnownOomAdj = app.setAdj;
                boolean canceled = scheduleServiceRestartLocked(sr, true);

                // Should the service remain running?  Note that in the
+18 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ final class ActivityManagerConstants extends ContentObserver {
    static final String KEY_COMPACT_THROTTLE_2 = "compact_throttle_2";
    static final String KEY_COMPACT_THROTTLE_3 = "compact_throttle_3";
    static final String KEY_COMPACT_THROTTLE_4 = "compact_throttle_4";
    static final String KEY_USE_MEM_AWARE_SERVICE_RESTARTS = "use_mem_aware_service_restarts";
    static final String KEY_SERVICE_RESTART_DELAY_DURATION = "service_restart_delay_duration";

    private static final int DEFAULT_MAX_CACHED_PROCESSES = 32;
    private static final long DEFAULT_BACKGROUND_SETTLE_TIME = 60*1000;
@@ -113,6 +115,8 @@ final class ActivityManagerConstants extends ContentObserver {
    public static final long DEFAULT_COMPACT_THROTTLE_2 = 10000;
    public static final long DEFAULT_COMPACT_THROTTLE_3 = 500;
    public static final long DEFAULT_COMPACT_THROTTLE_4 = 10000;
    private static final boolean DEFAULT_USE_MEM_AWARE_SERVICE_RESTARTS = true;
    private static final long DEFAULT_SERVICE_RESTART_DELAY_DURATION = 5 * 1000;

    // Maximum number of cached processes we will allow.
    public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;
@@ -249,6 +253,12 @@ final class ActivityManagerConstants extends ContentObserver {
    // How long we'll skip second compactAppFull after first compactAppFull
    public long COMPACT_THROTTLE_4 = DEFAULT_COMPACT_THROTTLE_4;

    // Use memory aware optimized logic to restart services
    public boolean FLAG_USE_MEM_AWARE_SERVICE_RESTARTS = DEFAULT_USE_MEM_AWARE_SERVICE_RESTARTS;

    // How long a service restart will be delayed by if there is memory pressure
    public long SERVICE_RESTART_DELAY_DURATION = DEFAULT_SERVICE_RESTART_DELAY_DURATION;

    // Indicates whether the activity starts logging is enabled.
    // Controlled by Settings.Global.ACTIVITY_STARTS_LOGGING_ENABLED
    volatile boolean mFlagActivityStartsLoggingEnabled;
@@ -413,6 +423,10 @@ final class ActivityManagerConstants extends ContentObserver {
            COMPACT_THROTTLE_2 = mParser.getLong(KEY_COMPACT_THROTTLE_2, DEFAULT_COMPACT_THROTTLE_2);
            COMPACT_THROTTLE_3 = mParser.getLong(KEY_COMPACT_THROTTLE_3, DEFAULT_COMPACT_THROTTLE_3);
            COMPACT_THROTTLE_4 = mParser.getLong(KEY_COMPACT_THROTTLE_4, DEFAULT_COMPACT_THROTTLE_4);
            FLAG_USE_MEM_AWARE_SERVICE_RESTARTS = mParser.getBoolean(
                    KEY_USE_MEM_AWARE_SERVICE_RESTARTS, DEFAULT_USE_MEM_AWARE_SERVICE_RESTARTS);
            SERVICE_RESTART_DELAY_DURATION = mParser.getLong(
                    KEY_SERVICE_RESTART_DELAY_DURATION, DEFAULT_SERVICE_RESTART_DELAY_DURATION);

            updateMaxCachedProcesses();
        }
@@ -505,6 +519,10 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.println(TOP_TO_FGS_GRACE_DURATION);
        pw.print("  "); pw.print(KEY_USE_COMPACTION); pw.print("=");
        pw.println(USE_COMPACTION);
        pw.print("  "); pw.print(KEY_USE_MEM_AWARE_SERVICE_RESTARTS); pw.print("=");
        pw.println(FLAG_USE_MEM_AWARE_SERVICE_RESTARTS);
        pw.print("  "); pw.print(KEY_SERVICE_RESTART_DELAY_DURATION); pw.print("=");
        pw.println(SERVICE_RESTART_DELAY_DURATION);

        pw.println();
        if (mOverrideMaxCachedProcesses >= 0) {
+8 −7
Original line number Diff line number Diff line
@@ -16,10 +16,8 @@

package com.android.server.am;

import com.android.internal.app.procstats.ServiceState;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

import android.app.INotificationManager;
import android.app.Notification;
@@ -44,6 +42,11 @@ import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;

import com.android.internal.app.procstats.ServiceState;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerInternal;
import com.android.server.uri.NeededUriGrants;
import com.android.server.uri.UriPermissionOwner;

@@ -52,9 +55,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

/**
 * A running application service.
 */
@@ -114,6 +114,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
    long executingStart;    // start time of last execute request.
    boolean createdFromFg;  // was this service last created due to a foreground process call?
    int crashCount;         // number of times proc has crashed with service running
    int lastKnownOomAdj;    // last known OOM adjustment for process (used if ProcessRecord is null)
    int totalRestartCount;  // number of times we have had to restart.
    int restartCount;       // number of restarts performed in a row.
    long restartDelay;      // delay until next restart attempt.