AnrTimer errors are now managed in a RingBuffer

This addresses comments from the previous CL:
 * AnrTimer is no longer an abstract class
 * The error list now uses a RingBuffer
 * The unused parameter 'when' in onExpired() is removed
 * A few variables/parameters are renamed.

Test: atest
 * FrameworksServicesTests:com.android.server.am
 * FrameworksMockingServicesTests:com.android.server.am
 * CtsAppTestCases
Bug: 282428924

Change-Id: Id3952003b0b31d845712cab07f3d796f39423f21
diff --git a/services/core/java/com/android/server/am/AnrTimer.java b/services/core/java/com/android/server/am/AnrTimer.java
index cd6f009..378a386 100644
--- a/services/core/java/com/android/server/am/AnrTimer.java
+++ b/services/core/java/com/android/server/am/AnrTimer.java
@@ -38,11 +38,13 @@
 import com.android.internal.annotations.Keep;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.util.RingBuffer;
 
 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;
 
@@ -75,7 +77,7 @@
  *
  * @hide
  */
-abstract class AnrTimer<V> {
+class AnrTimer<V> {
 
     /**
      * The log tag.
@@ -139,6 +141,8 @@
         final String tag;
         /** 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;
 
         Error(@NonNull String issue, @NonNull String operation, @NonNull String tag,
                 @NonNull StackTraceElement[] stack, @NonNull String arg) {
@@ -147,21 +151,17 @@
             this.tag = tag;
             this.stack = stack;
             this.arg = arg;
+            this.date = new Date().toString();
         }
     }
 
     /**
      * A list of errors detected during processing.  Errors correspond to "timer not found"
      * conditions.  The stack trace identifies the source of the call.  The list is
-     * first-in/first-out, and the size is limited to MAX_SAVED_ERROR_COUNT.
+     * first-in/first-out, and the size is limited to 20.
      */
     @GuardedBy("sErrors")
-    private static final ArrayList<Error> sErrors = new ArrayList<>();
-
-    /**
-     * The maximum number of errors that are saved in the sErrors list.
-     */
-    private static final int MAX_SAVED_ERROR_COUNT = 20;
+    private static final RingBuffer<Error> sErrors = new RingBuffer<>(Error.class, 20);
 
     /**
      * A record of a single anr timer.  The pid and uid are retained for reference but they do not
@@ -420,7 +420,7 @@
                 if (extension > 0) {
                     post(t, extension);
                 } else {
-                    onExpiredLocked(t, now());
+                    onExpiredLocked(t);
                 }
             }
             return true;
@@ -706,7 +706,7 @@
      * The notifier that a timer has fired.  The timer is not modified.
      */
     @GuardedBy("mLock")
-    private void onExpiredLocked(@NonNull Timer timer, long when) {
+    private void onExpiredLocked(@NonNull Timer timer) {
         if (DEBUG) report(timer, "expire");
         traceBegin(timer, "expired");
         mHandler.sendMessage(Message.obtain(mHandler, mWhat, timer.arg));
@@ -757,12 +757,7 @@
         // This should be enough to isolate the location of the call.
         StackTraceElement[] location = Arrays.copyOfRange(s, 6, 9);
         synchronized (sErrors) {
-            // Ensure the error list does not grow beyond the limit.
-            while (sErrors.size() >= MAX_SAVED_ERROR_COUNT) {
-                sErrors.remove(0);
-            }
-            // Add the new error to the list.
-            sErrors.add(new Error(errorMsg, operation, mLabel, location, what));
+            sErrors.append(new Error(errorMsg, operation, mLabel, location, what));
         }
         if (DEBUG) Log.w(TAG, operation + " " + errorMsg + " " + mLabel + " timer " + what);
         mTotalErrors++;
@@ -790,6 +785,7 @@
     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);
         ipw.increaseIndent();
         for (int i = 0; i < err.stack.length; i++) {
             ipw.println("    " + err.stack[i].toString());
@@ -801,15 +797,15 @@
      * Dump all errors to the output stream.
      */
     private static void dumpErrors(IndentingPrintWriter ipw) {
-        ArrayList<Error> errors;
+        Error errors[];
         synchronized (sErrors) {
             if (sErrors.size() == 0) return;
-            errors = (ArrayList<Error>) sErrors.clone();
+            errors = sErrors.toArray();
         }
         ipw.println("Errors");
         ipw.increaseIndent();
-        for (int i = 0; i < errors.size(); i++) {
-            dump(ipw, i, errors.get(i));
+        for (int i = 0; i < errors.length; i++) {
+            if (errors[i] != null) dump(ipw, i, errors[i]);
         }
         ipw.decreaseIndent();
     }
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index c35a3b2..5d31d15 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -1347,8 +1347,8 @@
      * Set the timeout flag to indicate that an ANR timer has been started.  A value of true means a
      * timer is running; a value of false means there is no timer running.
      */
-    void setTimeoutScheduled(boolean timeoutStarted) {
-        mTimeoutScheduled = timeoutStarted;
+    void setTimeoutScheduled(boolean timeoutScheduled) {
+        mTimeoutScheduled = timeoutScheduled;
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 5b71595..eb219a8 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -1172,7 +1172,7 @@
     }
 
     private class BroadcastAnrTimer extends AnrTimer<BroadcastProcessQueue> {
-        BroadcastAnrTimer(Handler handler) {
+        BroadcastAnrTimer(@NonNull Handler handler) {
             super(Objects.requireNonNull(handler),
                     MSG_DELIVERY_TIMEOUT, "BROADCAST_TIMEOUT", true);
         }