diff options
| author | 2023-10-19 18:58:23 +0000 | |
|---|---|---|
| committer | 2023-10-19 22:41:02 +0000 | |
| commit | 56e6011d77f9b4b7a03e17c404046c682bef127c (patch) | |
| tree | d3361415b5ece67bd9c68bf51b2ceaa1440ccf53 | |
| parent | dcc15f09715287115bce1b24b391e3589355bd2a (diff) | |
Simplify the mechanism to extend the timeout of the watchdog handlers.
The current #setOneOffTimeoutForCurrentThread does not work because by setting the status of the checker to complete a new run will be scheduled quickly after with the previous timeout.
Instead we pause the thread for the given time. This is similar to the existing pause/resume mechanism.
Change-Id: I0f2977837342c66f58b3e58ff43ed164680238d5
Bug: 223256297
| -rw-r--r-- | services/core/java/com/android/server/Watchdog.java | 59 |
1 files changed, 28 insertions, 31 deletions
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 55aa7164a67b..003046ab884f 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -250,7 +250,7 @@ public class Watchdog implements Dumpable { private Monitor mCurrentMonitor; private long mStartTimeMillis; private int mPauseCount; - private long mOneOffTimeoutMillis; + private long mPauseEndTimeMillis; HandlerChecker(Handler handler, String name) { mHandler = handler; @@ -270,20 +270,19 @@ public class Watchdog implements Dumpable { * @param handlerCheckerTimeoutMillis the timeout to use for this run */ public void scheduleCheckLocked(long handlerCheckerTimeoutMillis) { - if (mOneOffTimeoutMillis > 0) { - mWaitMaxMillis = mOneOffTimeoutMillis; - mOneOffTimeoutMillis = 0; - } else { - mWaitMaxMillis = handlerCheckerTimeoutMillis; - } + mWaitMaxMillis = handlerCheckerTimeoutMillis; if (mCompleted) { // Safe to update monitors in queue, Handler is not in the middle of work mMonitors.addAll(mMonitorQueue); mMonitorQueue.clear(); } + + long nowMillis = SystemClock.uptimeMillis(); + boolean isPaused = mPauseCount > 0 + || (mPauseEndTimeMillis > 0 && mPauseEndTimeMillis < nowMillis); if ((mMonitors.size() == 0 && mHandler.getLooper().getQueue().isPolling()) - || (mPauseCount > 0)) { + || isPaused) { // Don't schedule until after resume OR // If the target looper has recently been polling, then // there is no reason to enqueue our checker on it since that @@ -301,7 +300,8 @@ public class Watchdog implements Dumpable { mCompleted = false; mCurrentMonitor = null; - mStartTimeMillis = SystemClock.uptimeMillis(); + mStartTimeMillis = nowMillis; + mPauseEndTimeMillis = 0; mHandler.postAtFrontOfQueue(this); } @@ -360,20 +360,19 @@ public class Watchdog implements Dumpable { } /** - * Sets the timeout of the HandlerChecker for one run. - * - * <p>The current run will be ignored and the next run will be set to this timeout. + * Pauses the checks for the given time. * - * <p>If a one off timeout is already set, the maximum timeout will be used. + * <p>The current run will be ignored and another run will be scheduled after + * the given time. */ - public void setOneOffTimeoutLocked(int temporaryTimeoutMillis, String reason) { - mOneOffTimeoutMillis = Math.max(temporaryTimeoutMillis, mOneOffTimeoutMillis); + public void pauseForLocked(int pauseMillis, String reason) { + mPauseEndTimeMillis = SystemClock.uptimeMillis() + pauseMillis; // Mark as completed, because there's a chance we called this after the watchog // thread loop called Object#wait after 'WAITED_HALF'. In that case we want to ensure // the next call to #getCompletionStateLocked for this checker returns 'COMPLETED' mCompleted = true; - Slog.i(TAG, "Extending timeout of HandlerChecker: " + mName + " for reason: " - + reason + ". New timeout: " + mOneOffTimeoutMillis); + Slog.i(TAG, "Pausing of HandlerChecker: " + mName + " for reason: " + + reason + ". Pause end time: " + mPauseEndTimeMillis); } /** Pause the HandlerChecker. */ @@ -623,34 +622,32 @@ public class Watchdog implements Dumpable { } /** - * Sets a one-off timeout for the next run of the watchdog for this thread. This is useful + * Pauses the checks of the watchdog for this thread. This is useful * to run a slow operation on one of the monitored thread. * - * <p>After the next run, the timeout will go back to the default value. - * - * <p>If the current thread has not been added to the Watchdog, this call is a no-op. - * - * <p>If a one-off timeout for the current thread is already, the max value will be used. + * <p>After the given time, the timeout will go back to the default value. + * <p>This method does not require resume to be called. */ - public void setOneOffTimeoutForCurrentThread(int oneOffTimeoutMillis, String reason) { + public void pauseWatchingCurrentThreadFor(int pauseMillis, String reason) { synchronized (mLock) { for (HandlerCheckerAndTimeout hc : mHandlerCheckers) { HandlerChecker checker = hc.checker(); if (Thread.currentThread().equals(checker.getThread())) { - checker.setOneOffTimeoutLocked(oneOffTimeoutMillis, reason); + checker.pauseForLocked(pauseMillis, reason); } } } } /** - * Sets a one-off timeout for the next run of the watchdog for the monitor thread. + * Pauses the checks of the watchdog for the monitor thread for the given time * - * <p>Simiar to {@link setOneOffTimeoutForCurrentThread} but used for monitors added through - * {@link #addMonitor} + * <p>Similar to {@link pauseWatchingCurrentThreadFor} but used for monitors added + * through {@link #addMonitor} + * <p>This method does not require resume to be called. */ - public void setOneOffTimeoutForMonitors(int oneOffTimeoutMillis, String reason) { - mMonitorChecker.setOneOffTimeoutLocked(oneOffTimeoutMillis, reason); + public void pauseWatchingMonitorsFor(int pauseMillis, String reason) { + mMonitorChecker.pauseForLocked(pauseMillis, reason); } /** @@ -664,7 +661,7 @@ public class Watchdog implements Dumpable { * adds another pause and will require an additional {@link #resumeCurrentThread} to resume. * * <p>Note: Use with care, as any deadlocks on the current thread will be undetected until all - * pauses have been resumed. Prefer to use #setOneOffTimeoutForCurrentThread. + * pauses have been resumed. Prefer to use #pauseWatchingCurrentThreadFor. */ public void pauseWatchingCurrentThread(String reason) { synchronized (mLock) { |