ForegroundServiceDidNotStartInTimeException now has...

an inner exception that captures the stacktrace where
Context.startForegroundService() was called last time,
from the same process.

Bug: 124137635
Test: Manual test with a tesapp. 1: when startForegroundService() is called by
the same process:
```
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: FATAL EXCEPTION: main
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: Process: com.google.omakoto.testapp, PID: 9545
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{e7674af u0 com.google.omakoto.testapp/.MyFgs3}
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:1965)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1934)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.access$2700(ActivityThread.java:255)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:201)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:288)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7839)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: Caused by: android.app.StackTrace: Last startServiceCommon() call for this service was made here
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1868)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ContextImpl.startForegroundService(ContextImpl.java:1823)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.content.ContextWrapper.startForegroundService(ContextWrapper.java:779)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at com.google.omakoto.testapp.MyReceiver.onReceive(MyReceiver.java:53)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.handleReceiver(ActivityThread.java:4345)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread.access$1600(ActivityThread.java:255)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2102)
11-17 17:00:12.483 10241  9545  9545 E AndroidRuntime: 	... 7 more
```

Test: Manual test with a tesapp. 1: when startForegroundService() is called by
another process:
```
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: FATAL EXCEPTION: main
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: Process: com.google.omakoto.testapp:second, PID: 9432
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: android.app.RemoteServiceException$ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{dcaa127 u0 com.google.omakoto.testapp/.MyFgs3}
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.generateForegroundServiceDidNotStartInTimeException(ActivityThread.java:1965)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:1934)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.access$2700(ActivityThread.java:255)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2190)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:106)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Looper.loopOnce(Looper.java:201)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:288)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7839)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
11-17 16:59:34.456 10241  9432  9432 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
```

Change-Id: I2dd8ec76213d53728eaa8fcc3760813d82a328a5
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 17bb797..5edced1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1293,8 +1293,11 @@
         }
 
         @Override
-        public void scheduleCrash(String msg, int typeId) {
-            sendMessage(H.SCHEDULE_CRASH, msg, typeId);
+        public void scheduleCrash(String msg, int typeId, @Nullable Bundle extras) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = msg;
+            args.arg2 = extras;
+            sendMessage(H.SCHEDULE_CRASH, args, typeId);
         }
 
         public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
@@ -1924,11 +1927,11 @@
         }
     }
 
-    private void throwRemoteServiceException(String message, int typeId) {
+    private void throwRemoteServiceException(String message, int typeId, @Nullable Bundle extras) {
         // Use a switch to ensure all the type IDs are unique.
         switch (typeId) {
             case ForegroundServiceDidNotStartInTimeException.TYPE_ID:
-                throw new ForegroundServiceDidNotStartInTimeException(message);
+                throw generateForegroundServiceDidNotStartInTimeException(message, extras);
 
             case CannotDeliverBroadcastException.TYPE_ID:
                 throw new CannotDeliverBroadcastException(message);
@@ -1951,6 +1954,15 @@
         }
     }
 
+    private ForegroundServiceDidNotStartInTimeException
+            generateForegroundServiceDidNotStartInTimeException(String message, Bundle extras) {
+        final String serviceClassName =
+                ForegroundServiceDidNotStartInTimeException.getServiceClassNameFromExtras(extras);
+        final Exception inner = (serviceClassName == null) ? null
+                : Service.getStartForegroundServiceStackTrace(serviceClassName);
+        throw new ForegroundServiceDidNotStartInTimeException(message, inner);
+    }
+
     class H extends Handler {
         public static final int BIND_APPLICATION        = 110;
         @UnsupportedAppUsage
@@ -2168,9 +2180,14 @@
                     handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
-                case SCHEDULE_CRASH:
-                    throwRemoteServiceException((String) msg.obj, msg.arg1);
+                case SCHEDULE_CRASH: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    String message = (String) args.arg1;
+                    Bundle extras = (Bundle) args.arg2;
+                    args.recycle();
+                    throwRemoteServiceException(message, msg.arg1, extras);
                     break;
+                }
                 case DUMP_HEAP:
                     handleDumpHeap((DumpHeapData) msg.obj);
                     break;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index b5ed171..22df35d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1862,6 +1862,14 @@
                             "Not allowed to start service " + service + ": " + cn.getClassName());
                 }
             }
+            // If we started a foreground service in the same package, remember the stack trace.
+            if (cn != null && requireForeground) {
+                if (cn.getPackageName().equals(getOpPackageName())) {
+                    Service.setStartForegroundServiceStackTrace(cn.getClassName(),
+                            new StackTrace("Last startServiceCommon() call for this service was "
+                                    + "made here"));
+                }
+            }
             return cn;
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 9e9e28b..dcc9085 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -321,6 +321,8 @@
     boolean isTopActivityImmersive();
     void crashApplicationWithType(int uid, int initialPid, in String packageName, int userId,
             in String message, boolean force, int exceptionTypeId);
+    void crashApplicationWithTypeWithExtras(int uid, int initialPid, in String packageName,
+            int userId, in String message, boolean force, int exceptionTypeId, in Bundle extras);
     /** @deprecated -- use getProviderMimeTypeAsync */
     @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
             "Use {@link android.content.ContentResolver#getType} public API instead.")
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index d6ff6d3..448c3cf 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -107,7 +107,7 @@
     void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
     void scheduleSuicide();
     void dispatchPackageBroadcast(int cmd, in String[] packages);
-    void scheduleCrash(in String msg, int typeId);
+    void scheduleCrash(in String msg, int typeId, in Bundle extras);
     void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, in String path,
             in ParcelFileDescriptor fd, in RemoteCallback finishCallback);
     void dumpActivity(in ParcelFileDescriptor fd, IBinder servicetoken, in String prefix,
diff --git a/core/java/android/app/RemoteServiceException.java b/core/java/android/app/RemoteServiceException.java
index 1038530..e220627 100644
--- a/core/java/android/app/RemoteServiceException.java
+++ b/core/java/android/app/RemoteServiceException.java
@@ -16,6 +16,10 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Bundle;
 import android.util.AndroidRuntimeException;
 
 /**
@@ -33,6 +37,10 @@
         super(msg);
     }
 
+    public RemoteServiceException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
     /**
      * Exception used to crash an app process when it didn't call {@link Service#startForeground}
      * in time after the service was started with
@@ -44,8 +52,21 @@
         /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
         public static final int TYPE_ID = 1;
 
-        public ForegroundServiceDidNotStartInTimeException(String msg) {
-            super(msg);
+        private static final String KEY_SERVICE_CLASS_NAME = "serviceclassname";
+
+        public ForegroundServiceDidNotStartInTimeException(String msg, Throwable cause) {
+            super(msg, cause);
+        }
+
+        public static Bundle createExtrasForService(@NonNull ComponentName service) {
+            Bundle b = new Bundle();
+            b.putString(KEY_SERVICE_CLASS_NAME, service.getClassName());
+            return b;
+        }
+
+        @Nullable
+        public static String getServiceClassNameFromExtras(@Nullable Bundle extras) {
+            return (extras == null) ? null : extras.getString(KEY_SERVICE_CLASS_NAME);
         }
     }
 
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 3363872..5a5ccb5 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -33,9 +33,12 @@
 import android.os.Build;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.util.ArrayMap;
 import android.util.Log;
 import android.view.contentcapture.ContentCaptureManager;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -733,6 +736,7 @@
             mActivityManager.setServiceForeground(
                     new ComponentName(this, mClassName), mToken, id,
                     notification, 0, FOREGROUND_SERVICE_TYPE_MANIFEST);
+            clearStartForegroundServiceStackTrace();
         } catch (RemoteException ex) {
         }
     }
@@ -786,6 +790,7 @@
             mActivityManager.setServiceForeground(
                     new ComponentName(this, mClassName), mToken, id,
                     notification, 0, foregroundServiceType);
+            clearStartForegroundServiceStackTrace();
         } catch (RemoteException ex) {
         }
     }
@@ -941,4 +946,34 @@
     private IActivityManager mActivityManager = null;
     @UnsupportedAppUsage
     private boolean mStartCompatibility = false;
+
+    /**
+     * This keeps track of the stacktrace where Context.startForegroundService() was called
+     * for each service class. We use that when we crash the app for not calling
+     * {@link #startForeground} in time, in {@link ActivityThread#throwRemoteServiceException}.
+     */
+    @GuardedBy("sStartForegroundServiceStackTraces")
+    private static final ArrayMap<String, StackTrace> sStartForegroundServiceStackTraces =
+            new ArrayMap<>();
+
+    /** @hide */
+    public static void setStartForegroundServiceStackTrace(
+            @NonNull String className, @NonNull StackTrace stacktrace) {
+        synchronized (sStartForegroundServiceStackTraces) {
+            sStartForegroundServiceStackTraces.put(className, stacktrace);
+        }
+    }
+
+    private void clearStartForegroundServiceStackTrace() {
+        synchronized (sStartForegroundServiceStackTraces) {
+            sStartForegroundServiceStackTraces.remove(this.getClassName());
+        }
+    }
+
+    /** @hide */
+    public static StackTrace getStartForegroundServiceStackTrace(@NonNull String className) {
+        synchronized (sStartForegroundServiceStackTraces) {
+            return sStartForegroundServiceStackTraces.get(className);
+        }
+    }
 }
diff --git a/core/java/android/app/StackTrace.java b/core/java/android/app/StackTrace.java
new file mode 100644
index 0000000..ec058f8
--- /dev/null
+++ b/core/java/android/app/StackTrace.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+/**
+ * An Exception subclass that's used only for logging stacktraces.
+ * @hide
+ */
+public class StackTrace extends Exception {
+    public StackTrace(String message) {
+        super(message);
+    }
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index df0c64c..9f48c06 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -532,7 +532,7 @@
         }
 
         @Override
-        public void scheduleCrash(String s, int i) throws RemoteException {
+        public void scheduleCrash(String s, int i, Bundle extras) throws RemoteException {
         }
 
         @Override
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df2ae98..9a371f3 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -157,6 +157,7 @@
 import com.android.internal.app.procstats.ServiceState;
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastPrintWriter;
@@ -4209,9 +4210,12 @@
             if (r.app != null) {
                 Message msg = mAm.mHandler.obtainMessage(
                         ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG);
-                msg.obj = r.app;
-                msg.getData().putCharSequence(
-                    ActivityManagerService.SERVICE_RECORD_KEY, r.toString());
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = r.app;
+                args.arg2 = r.toString();
+                args.arg3 = r.getComponentName();
+
+                msg.obj = args;
                 mAm.mHandler.sendMessage(msg);
             }
         }
@@ -5272,11 +5276,14 @@
         }
     }
 
-    void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
-        mAm.crashApplicationWithType(app.uid, app.getPid(), app.info.packageName, app.userId,
+    void serviceForegroundCrash(ProcessRecord app, String serviceRecord,
+            ComponentName service) {
+        mAm.crashApplicationWithTypeWithExtras(
+                app.uid, app.getPid(), app.info.packageName, app.userId,
                 "Context.startForegroundService() did not then call Service.startForeground(): "
                     + serviceRecord, false /*force*/,
-                ForegroundServiceDidNotStartInTimeException.TYPE_ID);
+                ForegroundServiceDidNotStartInTimeException.TYPE_ID,
+                ForegroundServiceDidNotStartInTimeException.createExtrasForService(service));
     }
 
     void scheduleServiceTimeoutLocked(ProcessRecord proc) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5cd66aa..3998af5 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -338,6 +338,7 @@
 import com.android.internal.os.ByteTransferPipe;
 import com.android.internal.os.IResultReceiver;
 import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.os.TransferPipe;
 import com.android.internal.os.Zygote;
 import com.android.internal.policy.AttributeCache;
@@ -1472,8 +1473,6 @@
 
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
 
-    static final String SERVICE_RECORD_KEY = "servicerecord";
-
     /**
      * Flag whether the current user is a "monkey", i.e. whether
      * the UI is driven by a UI automation tool.
@@ -1652,8 +1651,12 @@
                 mServices.serviceForegroundTimeout((ServiceRecord) msg.obj);
             } break;
             case SERVICE_FOREGROUND_CRASH_MSG: {
-                mServices.serviceForegroundCrash((ProcessRecord) msg.obj,
-                        msg.getData().getCharSequence(SERVICE_RECORD_KEY));
+                SomeArgs args = (SomeArgs) msg.obj;
+                mServices.serviceForegroundCrash(
+                        (ProcessRecord) args.arg1,
+                        (String) args.arg2,
+                        (ComponentName) args.arg3);
+                args.recycle();
             } break;
             case UPDATE_TIME_ZONE: {
                 synchronized (mProcLock) {
@@ -3001,6 +3004,14 @@
     @Override
     public void crashApplicationWithType(int uid, int initialPid, String packageName, int userId,
             String message, boolean force, int exceptionTypeId) {
+        crashApplicationWithTypeWithExtras(uid, initialPid, packageName, userId, message,
+                force, exceptionTypeId, null);
+    }
+
+    @Override
+    public void crashApplicationWithTypeWithExtras(int uid, int initialPid, String packageName,
+            int userId, String message, boolean force, int exceptionTypeId,
+            @Nullable Bundle extras) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: crashApplication() from pid="
@@ -3013,7 +3024,7 @@
 
         synchronized(this) {
             mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId,
-                    message, force, exceptionTypeId);
+                    message, force, exceptionTypeId, extras);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index bcb42bb..0bf0fe2 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -27,6 +27,7 @@
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
 
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.AnrController;
@@ -40,6 +41,7 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Message;
 import android.os.Process;
 import android.os.SystemClock;
@@ -489,7 +491,7 @@
      * @param message
      */
     void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
-            String message, boolean force, int exceptionTypeId) {
+            String message, boolean force, int exceptionTypeId, @Nullable Bundle extras) {
         ProcessRecord proc = null;
 
         // Figure out which process to kill.  We don't trust that initialPid
@@ -521,7 +523,7 @@
             return;
         }
 
-        proc.scheduleCrashLocked(message, exceptionTypeId);
+        proc.scheduleCrashLocked(message, exceptionTypeId, extras);
         if (force) {
             // If the app is responsive, the scheduled crash will happen as expected
             // and then the delayed summary kill will be a no-op.
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 487101b..2da4107 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -611,7 +611,7 @@
                         Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                 + " (pid " + app.getPid() + "). Crashing it.");
                         app.scheduleCrashLocked("can't deliver broadcast",
-                                CannotDeliverBroadcastException.TYPE_ID);
+                                CannotDeliverBroadcastException.TYPE_ID, /* extras=*/ null);
                     }
                     throw ex;
                 }
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 14ba716..b9d7917 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -31,6 +31,7 @@
 import android.content.pm.VersionedPackage;
 import android.content.res.CompatibilityInfo;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
@@ -958,7 +959,7 @@
      *                        of its subclasses.
      */
     @GuardedBy("mService")
-    void scheduleCrashLocked(String message, int exceptionTypeId) {
+    void scheduleCrashLocked(String message, int exceptionTypeId, @Nullable Bundle extras) {
         // Checking killedbyAm should keep it from showing the crash dialog if the process
         // was already dead for a good / normal reason.
         if (!mKilledByAm) {
@@ -969,7 +970,7 @@
                 }
                 final long ident = Binder.clearCallingIdentity();
                 try {
-                    mThread.scheduleCrash(message, exceptionTypeId);
+                    mThread.scheduleCrash(message, exceptionTypeId, extras);
                 } catch (RemoteException e) {
                     // If it's already dead our work is done. If it's wedged just kill it.
                     // We won't get the crash dialog or the error reporting.