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

Commit 9db686db authored by Lee Shombert's avatar Lee Shombert Committed by Android (Google) Code Review
Browse files

Merge "Extend ANR timer to ActiveServices" into main

parents bb756a05 371a2550
Loading
Loading
Loading
Loading
+67 −28
Original line number Diff line number Diff line
@@ -409,6 +409,13 @@ public final class ActiveServices {

    AppWidgetManagerInternal mAppWidgetManagerInternal;

    /**
     * The available ANR timers.
     */
    private final ProcessAnrTimer mActiveServiceAnrTimer;
    private final ServiceAnrTimer mShortFGSAnrTimer;
    private final ServiceAnrTimer mServiceFGAnrTimer;

    // allowlisted packageName.
    ArraySet<String> mAllowListWhileInUsePermissionInFgs = new ArraySet<>();

@@ -663,6 +670,15 @@ public final class ActiveServices {

        final IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
        this.mFGSLogger = new ForegroundServiceTypeLoggerModule();
        this.mActiveServiceAnrTimer = new ProcessAnrTimer(service,
                ActivityManagerService.SERVICE_TIMEOUT_MSG,
                "SERVICE_TIMEOUT");
        this.mShortFGSAnrTimer = new ServiceAnrTimer(service,
                ActivityManagerService.SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG,
                "FGS_TIMEOUT");
        this.mServiceFGAnrTimer = new ServiceAnrTimer(service,
                ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG,
                "SERVICE_FOREGROUND_TIMEOUT");
    }

    void systemServicesReady() {
@@ -2083,8 +2099,7 @@ public final class ActiveServices {
                r.fgRequired = false;
                r.fgWaiting = false;
                alreadyStartedOp = stopProcStatsOp = true;
                mAm.mHandler.removeMessages(
                        ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
                mServiceFGAnrTimer.cancel(r);
            }

            final ProcessServiceRecord psr = r.app.mServices;
@@ -3313,7 +3328,7 @@ public final class ActiveServices {
    }

    void unscheduleShortFgsTimeoutLocked(ServiceRecord sr) {
        mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG, sr);
        mShortFGSAnrTimer.cancel(sr);
        mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_SHORT_FGS_PROCSTATE_TIMEOUT_MSG,
                sr);
        mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_SHORT_FGS_TIMEOUT_MSG, sr);
@@ -3387,9 +3402,11 @@ public final class ActiveServices {
                    Slog.d(TAG_SERVICE, "[STALE] Short FGS timed out: " + sr
                            + " " + sr.getShortFgsTimedEventDescription(nowUptime));
                }
                mShortFGSAnrTimer.discard(sr);
                return;
            }
            Slog.e(TAG_SERVICE, "Short FGS timed out: " + sr);
            mShortFGSAnrTimer.accept(sr);
            traceInstant("short FGS timeout: ", sr);

            logFGSStateChangeLocked(sr,
@@ -3413,11 +3430,10 @@ public final class ActiveServices {
                        msg, sr.getShortFgsInfo().getProcStateDemoteTime());
            }

            {
                final Message msg = mAm.mHandler.obtainMessage(
                        ActivityManagerService.SERVICE_SHORT_FGS_ANR_TIMEOUT_MSG, sr);
                mAm.mHandler.sendMessageAtTime(msg, sr.getShortFgsInfo().getAnrTime());
            }
            // ServiceRecord.getAnrTime() is an absolute time with a reference that is not "now".
            // Compute the time from "now" when starting the anr timer.
            mShortFGSAnrTimer.start(sr,
                    sr.getShortFgsInfo().getAnrTime() - SystemClock.uptimeMillis());
        }
    }

@@ -4847,8 +4863,7 @@ public final class ActiveServices {
        // a new SERVICE_FOREGROUND_TIMEOUT_MSG is scheduled in SERVICE_START_FOREGROUND_TIMEOUT
        // again.
        if (r.fgRequired && r.fgWaiting) {
            mAm.mHandler.removeMessages(
                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
            mServiceFGAnrTimer.cancel(r);
            r.fgWaiting = false;
        }

@@ -5691,8 +5706,7 @@ public final class ActiveServices {
            }
            mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
                    AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null);
            mAm.mHandler.removeMessages(
                    ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r);
            mServiceFGAnrTimer.cancel(r);
            if (r.app != null) {
                Message msg = mAm.mHandler.obtainMessage(
                        ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
@@ -6128,7 +6142,7 @@ public final class ActiveServices {
                if (psr.numberOfExecutingServices() == 0) {
                    if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING,
                            "No more executingServices of " + r.shortInstanceName);
                    mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);
                    if (r.app.mPid != 0) mActiveServiceAnrTimer.cancel(r.app);
                } else if (r.executeFg) {
                    // Need to re-evaluate whether the app still needs to be in the foreground.
                    for (int i = psr.numberOfExecutingServices() - 1; i >= 0; i--) {
@@ -6816,13 +6830,16 @@ public final class ActiveServices {
            synchronized (mAm) {
                if (proc.isDebugging()) {
                    // The app's being debugged, ignore timeout.
                    mActiveServiceAnrTimer.discard(proc);
                    return;
                }
                final ProcessServiceRecord psr = proc.mServices;
                if (psr.numberOfExecutingServices() == 0 || proc.getThread() == null
                        || proc.isKilled()) {
                    mActiveServiceAnrTimer.discard(proc);
                    return;
                }
                mActiveServiceAnrTimer.accept(proc);
                final long now = SystemClock.uptimeMillis();
                final long maxTime =  now
                        - (psr.shouldExecServicesFg()
@@ -6855,12 +6872,11 @@ public final class ActiveServices {
                    timeoutRecord = TimeoutRecord.forServiceExec(timeout.shortInstanceName,
                            waitedMillis);
                } else {
                    Message msg = mAm.mHandler.obtainMessage(
                            ActivityManagerService.SERVICE_TIMEOUT_MSG);
                    msg.obj = proc;
                    mAm.mHandler.sendMessageAtTime(msg, psr.shouldExecServicesFg()
                    final long delay = psr.shouldExecServicesFg()
                                       ? (nextTime + mAm.mConstants.SERVICE_TIMEOUT) :
                            (nextTime + mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT));
                                       (nextTime + mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT)
                                       - SystemClock.uptimeMillis();
                    mActiveServiceAnrTimer.start(proc, delay);
                }
            }

@@ -6886,12 +6902,15 @@ public final class ActiveServices {
            synchronized (mAm) {
                timeoutRecord.mLatencyTracker.waitingOnAMSLockEnded();
                if (!r.fgRequired || !r.fgWaiting || r.destroying) {
                    mServiceFGAnrTimer.discard(r);
                    return;
                }

                mServiceFGAnrTimer.accept(r);
                app = r.app;
                if (app != null && app.isDebugging()) {
                    // The app's being debugged; let it ride
                    mServiceFGAnrTimer.discard(r);
                    return;
                }

@@ -6948,26 +6967,46 @@ public final class ActiveServices {
                ForegroundServiceDidNotStartInTimeException.createExtrasForService(service));
    }

    private static class ProcessAnrTimer extends AnrTimer<ProcessRecord> {

        ProcessAnrTimer(ActivityManagerService am, int msg, String label) {
            super(Objects.requireNonNull(am).mHandler, msg, label);
        }

        void start(@NonNull ProcessRecord proc, long millis) {
            start(proc, proc.getPid(), proc.uid, millis);
        }
    }

    private static class ServiceAnrTimer extends AnrTimer<ServiceRecord> {

        ServiceAnrTimer(ActivityManagerService am, int msg, String label) {
            super(Objects.requireNonNull(am).mHandler, msg, label);
        }

        void start(@NonNull ServiceRecord service, long millis) {
            start(service,
                    (service.app != null) ? service.app.getPid() : 0,
                    service.appInfo.uid,
                    millis);
        }
    }

    void scheduleServiceTimeoutLocked(ProcessRecord proc) {
        if (proc.mServices.numberOfExecutingServices() == 0 || proc.getThread() == null) {
            return;
        }
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_TIMEOUT_MSG);
        msg.obj = proc;
        mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg()
                ? mAm.mConstants.SERVICE_TIMEOUT : mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT);
        final long delay = proc.mServices.shouldExecServicesFg()
                ? mAm.mConstants.SERVICE_TIMEOUT : mAm.mConstants.SERVICE_BACKGROUND_TIMEOUT;
        mActiveServiceAnrTimer.start(proc, delay);
    }

    void scheduleServiceForegroundTransitionTimeoutLocked(ServiceRecord r) {
        if (r.app.mServices.numberOfExecutingServices() == 0 || r.app.getThread() == null) {
            return;
        }
        Message msg = mAm.mHandler.obtainMessage(
                ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG);
        msg.obj = r;
        r.fgWaiting = true;
        mAm.mHandler.sendMessageDelayed(msg, mAm.mConstants.mServiceStartForegroundTimeoutMs);
        mServiceFGAnrTimer.start(r, mAm.mConstants.mServiceStartForegroundTimeoutMs);
    }

    final class ServiceDumper {
+99 −30
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.Process;
import android.os.SystemClock;
import android.os.Trace;
import android.text.TextUtils;
import android.text.format.TimeMigrationUtils;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.Log;
@@ -44,7 +45,6 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

@@ -150,7 +150,7 @@ class AnrTimer<V> {
        /** A partial stack that localizes the caller of the operation. */
        final StackTraceElement[] stack;
        /** The date, in local time, the error was created. */
        final String date;
        final long timestamp;

        Error(@NonNull String issue, @NonNull String operation, @NonNull String tag,
                @NonNull StackTraceElement[] stack, @NonNull String arg) {
@@ -159,7 +159,7 @@ class AnrTimer<V> {
            this.tag = tag;
            this.stack = stack;
            this.arg = arg;
            this.date = new Date().toString();
            this.timestamp = SystemClock.elapsedRealtime();
        }
    }

@@ -347,20 +347,23 @@ class AnrTimer<V> {
         * main Looper.
         */
        @NonNull
        Handler getHandler(@NonNull Handler.Callback callback) {
        Handler newHandler(@NonNull Handler.Callback callback) {
            Looper looper = mReferenceHandler.getLooper();
            if (looper == null) looper = Looper.getMainLooper();
            return new Handler(looper, callback);
        };
        }

        /** Return a CpuTracker. */
        /**
         * Return a CpuTracker. The default behavior is to create a new CpuTracker but this changes
         * for unit tests.
         **/
        @NonNull
        CpuTracker getTracker() {
        CpuTracker newTracker() {
            return new CpuTracker();
        }

        /** Return true if the feature is enabled. */
        boolean getFeatureEnabled() {
        boolean isFeatureEnabled() {
            return anrTimerServiceEnabled();
        }
    }
@@ -401,8 +404,8 @@ class AnrTimer<V> {
        /** Create a HandlerTimerService that directly uses the supplied handler and tracker. */
        @VisibleForTesting
        HandlerTimerService(@NonNull Injector injector) {
            mHandler = injector.getHandler(this::expires);
            mCpu = injector.getTracker();
            mHandler = injector.newHandler(this::expires);
            mCpu = injector.newTracker();
        }

        /** Post a message with the specified timeout.  The timer is not modified. */
@@ -513,7 +516,26 @@ class AnrTimer<V> {
    private final FeatureSwitch mFeature;

    /**
     * The common constructor.  A null injector results in a normal, production timer.
     * Create one AnrTimer instance.  The instance is given a handler and a "what".  Individual
     * timers are started with {@link #start}.  If a timer expires, then a {@link Message} is sent
     * immediately to the handler with {@link Message.what} set to what and {@link Message.obj} set
     * to the timer key.
     *
     * AnrTimer instances have a label, which must be unique.  The label is used for reporting and
     * debug.
     *
     * If an individual timer expires internally, and the "extend" parameter is true, then the
     * AnrTimer may extend the individual timer rather than immediately delivering the timeout to
     * the client.  The extension policy is not part of the instance.
     *
     * This method accepts an {@link #Injector} to tune behavior for testing.  This method should
     * not be called directly by regular clients.
     *
     * @param handler The handler to which the expiration message will be delivered.
     * @param what The "what" parameter for the expiration message.
     * @param label A name for this instance.
     * @param extend A flag to indicate if expired timers can be granted extensions.
     * @param injector An {@link #Injector} to tune behavior for testing.
     */
    @VisibleForTesting
    AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend,
@@ -522,7 +544,7 @@ class AnrTimer<V> {
        mWhat = what;
        mLabel = label;
        mExtend = extend;
        boolean enabled = injector.getFeatureEnabled();
        boolean enabled = injector.isFeatureEnabled();
        if (!enabled) {
            mFeature = new FeatureDisabled();
            mTimerService = null;
@@ -538,14 +560,25 @@ class AnrTimer<V> {
    }

    /**
     * Create one timer instance for production.  The client can ask for extensible timeouts.
     * Create an AnrTimer instance with the default {@link #Injector}.  See {@link AnrTimer(Handler,
     * int, String, boolean, Injector} for a functional description.
     *
     * @param handler The handler to which the expiration message will be delivered.
     * @param what The "what" parameter for the expiration message.
     * @param label A name for this instance.
     * @param extend A flag to indicate if expired timers can be granted extensions.
     */
    AnrTimer(@NonNull Handler handler, int what, @NonNull String label, boolean extend) {
        this(handler, what, label, extend, new Injector(handler));
    }

    /**
     * Create one timer instance for production.  There are no extensible timeouts.
     * Create an AnrTimer instance with the default {@link #Injector} and with extensions disabled.
     * See {@link AnrTimer(Handler, int, String, boolean, Injector} for a functional description.
     *
     * @param handler The handler to which the expiration message will be delivered.
     * @param what The "what" parameter for the expiration message.
     * @param label A name for this instance.
     */
    AnrTimer(@NonNull Handler handler, int what, @NonNull String label) {
        this(handler, what, label, false);
@@ -555,6 +588,8 @@ class AnrTimer<V> {
     * Return true if the service is enabled on this instance.  Clients should use this method to
     * decide if the feature is enabled, and not read the flags directly.  This method should be
     * deleted if and when the feature is enabled permanently.
     *
     * @return true if the service is flag-enabled.
     */
    boolean serviceEnabled() {
        return mFeature.enabled();
@@ -642,7 +677,7 @@ class AnrTimer<V> {
    }

    /**
     * Report something about a timer.
     * Generate a log message for a timer.
     */
    private void report(@NonNull Timer timer, @NonNull String msg) {
        Log.i(TAG, msg + " " + timer + " " + Objects.toString(timer.arg));
@@ -654,9 +689,13 @@ class AnrTimer<V> {
     */
    private abstract class FeatureSwitch {
        abstract boolean start(@NonNull V arg, int pid, int uid, long timeoutMs);

        abstract boolean cancel(@NonNull V arg);

        abstract boolean accept(@NonNull V arg);

        abstract boolean discard(@NonNull V arg);

        abstract boolean enabled();
    }

@@ -666,6 +705,7 @@ class AnrTimer<V> {
     */
    private class FeatureDisabled extends FeatureSwitch {
        /** Start a timer by sending a message to the client's handler. */
        @Override
        boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
            final Message msg = mHandler.obtainMessage(mWhat, arg);
            mHandler.sendMessageDelayed(msg, timeoutMs);
@@ -673,22 +713,26 @@ class AnrTimer<V> {
        }

        /** Cancel a timer by removing the message from the client's handler. */
        @Override
        boolean cancel(@NonNull V arg) {
            mHandler.removeMessages(mWhat, arg);
            return true;
        }

        /** accept() is a no-op when the feature is disabled. */
        @Override
        boolean accept(@NonNull V arg) {
            return true;
        }

        /** discard() is a no-op when the feature is disabled. */
        @Override
        boolean discard(@NonNull V arg) {
            return true;
        }

        /** The feature is not enabled. */
        @Override
        boolean enabled() {
            return false;
        }
@@ -703,16 +747,17 @@ class AnrTimer<V> {
        /**
         * Start a timer.
         */
        @Override
        boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
            final Timer timer = Timer.obtain(pid, uid, arg, timeoutMs, AnrTimer.this);
            synchronized (mLock) {
                Timer old = mTimerMap.get(arg);
                // There is an existing timer.  If the timer was running, then cancel the running
                // timer and restart it.  If the timer was expired record a protocol error and
                // discard the expired timer.
                if (old != null) {
                    // There is an existing timer.  This is a protocol error in the client.
                    // Record the error and then clean up by canceling running timers and
                    // discarding expired timers.
                    restartedLocked(old.status, arg);
                    if (old.status == TIMER_EXPIRED) {
                      restartedLocked(old.status, arg);
                        discard(arg);
                    } else {
                        cancel(arg);
@@ -735,6 +780,7 @@ class AnrTimer<V> {
        /**
         * Cancel a timer.  Return false if the timer was not found.
         */
        @Override
        boolean cancel(@NonNull V arg) {
            synchronized (mLock) {
                Timer timer = removeLocked(arg);
@@ -755,6 +801,7 @@ class AnrTimer<V> {
         * Accept a timer in the framework-level handler.  The timeout has been accepted and the
         * timeout handler is executing.  Return false if the timer was not found.
         */
        @Override
        boolean accept(@NonNull V arg) {
            synchronized (mLock) {
                Timer timer = removeLocked(arg);
@@ -775,6 +822,7 @@ class AnrTimer<V> {
         * longer interesting.  No statistics are collected.  Return false if the time was not
         * found.
         */
        @Override
        boolean discard(@NonNull V arg) {
            synchronized (mLock) {
                Timer timer = removeLocked(arg);
@@ -791,40 +839,58 @@ class AnrTimer<V> {
        }

        /** The feature is enabled. */
        @Override
        boolean enabled() {
            return true;
        }
    }

    /**
     * Start a timer associated with arg.  If a timer already exists with the same arg, then that
     * timer is canceled and a new timer is created.  This returns false if the timer cannot be
     * created.
     * Start a timer associated with arg.  The same object must be used to cancel, accept, or
     * discard a timer later.  If a timer already exists with the same arg, then the existing timer
     * is canceled and a new timer is created.
     *
     * @param arg The key by which the timer is known.  This is never examined or modified.
     * @param pid The Linux process ID of the target being timed.
     * @param uid The Linux user ID of the target being timed.
     * @param timeoutMs The timer timeout, in milliseconds.
     * @return true if the timer was successfully created.
     */
    boolean start(@NonNull V arg, int pid, int uid, long timeoutMs) {
        return mFeature.start(arg, pid, uid, timeoutMs);
    }

    /**
     * Cancel a running timer and remove it from any list.  This returns true if the timer was
     * found and false otherwise.  It is not an error to cancel a non-existent timer.  It is also
     * not an error to cancel an expired timer.
     * Cancel the running timer associated with arg.  The timer is forgotten.  If the timer has
     * expired, the call is treated as a discard.  No errors are reported if the timer does not
     * exist or if the timer has expired.
     *
     * @return true if the timer was found and was running.
     */
    boolean cancel(@NonNull V arg) {
        return mFeature.cancel(arg);
    }

    /**
     * Accept an expired timer.  This returns false if the timer was not found or if the timer was
     * not expired.
     * Accept the expired timer associated with arg.  This indicates that the caller considers the
     * timer expiration to be a true ANR.  (See {@link #discard} for an alternate response.)  It is
     * an error to accept a running timer, however the running timer will be canceled.
     *
     * @return true if the timer was found and was expired.
     */
    boolean accept(@NonNull V arg) {
        return mFeature.accept(arg);
    }

    /**
     * Discard an expired timer.  This returns false if the timer was not found or if the timer was
     * not expired.
     * Discard the expired timer associated with arg.  This indicates that the caller considers the
     * timer expiration to be a false ANR.  ((See {@link #accept} for an alternate response.)  One
     * reason to discard an expired timer is if the process being timed was also being debugged:
     * such a process could be stopped at a breakpoint and its failure to respond would not be an
     * error.  It is an error to discard a running timer, however the running timer will be
     * canceled.
     *
     * @return true if the timer was found and was expired.
     */
    boolean discard(@NonNull V arg) {
        return mFeature.discard(arg);
@@ -913,7 +979,10 @@ class AnrTimer<V> {
    private static void dump(IndentingPrintWriter ipw, int seq, Error err) {
        ipw.format("%2d: op:%s tag:%s issue:%s arg:%s\n", seq, err.operation, err.tag,
                err.issue, err.arg);
        ipw.format("    date:%s\n", err.date);

        final long offset = System.currentTimeMillis() - SystemClock.elapsedRealtime();
        final long etime = offset + err.timestamp;
        ipw.println("    date:" + TimeMigrationUtils.formatMillisWithFixedFormat(etime));
        ipw.increaseIndent();
        for (int i = 0; i < err.stack.length; i++) {
            ipw.println("    " + err.stack[i].toString());
+10 −5
Original line number Diff line number Diff line
@@ -258,7 +258,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    private static final int MSG_PROCESS_FREEZABLE_CHANGED = 6;
    private static final int MSG_UID_STATE_CHANGED = 7;

    // Required when Flags.anrTimerServiceEnabled is false.
    // Required when Flags.anrTimerServiceEnabled is false.  This constant should be deleted if and
    // when the flag is fused on.
    private static final int MSG_DELIVERY_TIMEOUT_SOFT = 8;

    private void enqueueUpdateRunningList() {
@@ -274,7 +275,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                updateRunningList();
                return true;
            }
            // Required when Flags.anrTimerServiceEnabled is false.
            // Required when Flags.anrTimerServiceEnabled is false.  This case should be deleted if
            // and when the flag is fused on.
            case MSG_DELIVERY_TIMEOUT_SOFT: {
                synchronized (mService) {
                    deliveryTimeoutSoftLocked((BroadcastProcessQueue) msg.obj, msg.arg1);
@@ -1169,7 +1171,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        r.resultTo = null;
    }

    // Required when Flags.anrTimerServiceEnabled is false.
    // Required when Flags.anrTimerServiceEnabled is false.  This function can be replaced with a
    // single call to {@code mAnrTimer.start()} if and when the flag is fused on.
    private void startDeliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue,
            int softTimeoutMillis) {
        if (mAnrTimer.serviceEnabled()) {
@@ -1181,7 +1184,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        }
    }

    // Required when Flags.anrTimerServiceEnabled is false.
    // Required when Flags.anrTimerServiceEnabled is false. This function can be replaced with a
    // single call to {@code mAnrTimer.cancel()} if and when the flag is fused on.
    private void cancelDeliveryTimeoutLocked(@NonNull BroadcastProcessQueue queue) {
        mAnrTimer.cancel(queue);
        if (!mAnrTimer.serviceEnabled()) {
@@ -1189,7 +1193,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        }
    }

    // Required when Flags.anrTimerServiceEnabled is false.
    // Required when Flags.anrTimerServiceEnabled is false.  This function can be deleted entirely
    // if and when the flag is fused on.
    private void deliveryTimeoutSoftLocked(@NonNull BroadcastProcessQueue queue,
            int softTimeoutMillis) {
        if (queue.app != null) {
+7 −3

File changed.

Preview size limit exceeded, changes collapsed.