Add killing subreason for undelivered broadcast

Bug: 239419108
Test: atest ApplicationExitInfoTest
Test: atest BroadcastQueueTest
Test: use up async buffer, broadcast & dumpsys activity exit-info
Change-Id: I6a1b8c5a96963af624b8254753c8d8c364d0bc78
diff --git a/core/java/android/app/ApplicationExitInfo.java b/core/java/android/app/ApplicationExitInfo.java
index 5517c57..871d15e 100644
--- a/core/java/android/app/ApplicationExitInfo.java
+++ b/core/java/android/app/ApplicationExitInfo.java
@@ -407,6 +407,15 @@
      */
     public static final int SUBREASON_PACKAGE_UPDATE = 25;
 
+    /**
+     * The process was killed because of undelivered broadcasts; this would be set only when the
+     * reason is {@link #REASON_OTHER}.
+     *
+     * For internal use only.
+     * @hide
+     */
+    public static final int SUBREASON_UNDELIVERED_BROADCAST = 26;
+
     // If there is any OEM code which involves additional app kill reasons, it should
     // be categorized in {@link #REASON_OTHER}, with subreason code starting from 1000.
 
@@ -579,6 +588,7 @@
         SUBREASON_STOP_APP,
         SUBREASON_KILL_BACKGROUND,
         SUBREASON_PACKAGE_UPDATE,
+        SUBREASON_UNDELIVERED_BROADCAST,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface SubReason {}
@@ -1283,6 +1293,8 @@
                 return "KILL BACKGROUND";
             case SUBREASON_PACKAGE_UPDATE:
                 return "PACKAGE UPDATE";
+            case SUBREASON_UNDELIVERED_BROADCAST:
+                return "UNDELIVERED BROADCAST";
             default:
                 return "UNKNOWN";
         }
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 8ece180..1a72fef 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -735,7 +735,7 @@
                                 + " via " + app + ": " + ex;
                         Slog.w(TAG, msg);
                         app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
-                                true);
+                                ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
                     }
                     throw ex;
                 }
@@ -1388,7 +1388,8 @@
                 final String msg = "Failed to schedule " + r.intent + " to " + info
                         + " via " + app + ": " + e;
                 Slog.w(TAG, msg);
-                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER, true);
+                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
+                        ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
             } catch (RuntimeException e) {
                 Slog.wtf(TAG, "Failed sending broadcast to "
                         + r.curComponent + " with " + r.intent, e);
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index ad5aa87..5d5dbbb 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -831,7 +831,8 @@
                 final String msg = "Failed to schedule " + r + " to " + receiver
                         + " via " + app + ": " + e;
                 logw(msg);
-                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER, true);
+                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
+                        ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
                 enqueueFinishReceiver(queue, BroadcastRecord.DELIVERY_FAILURE, "remote app");
             }
         } else {
@@ -858,7 +859,8 @@
             } catch (RemoteException e) {
                 final String msg = "Failed to schedule result of " + r + " via " + app + ": " + e;
                 logw(msg);
-                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER, true);
+                app.killLocked("Can't deliver broadcast", ApplicationExitInfo.REASON_OTHER,
+                        ApplicationExitInfo.SUBREASON_UNDELIVERED_BROADCAST, true);
             }
         }
         // Clear so both local and remote references can be GC'ed