Currently getting the following stacktrace for multiple different device models and makers (so far on Android 8.1.0 and Android 11) with small variations only in the app internal calls:
Fatal Exception: java.lang.RuntimeException: android.os.DeadSystemException
at android.app.NotificationManager.getNotificationChannels(NotificationManager.java:892)
at appinternalcalls(...).getNotificationChannel
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Note: app internal calls omitted due to IP.
I have been trying to understand why this is happening and so far I can only conclude that the Context being used to instantiate the NotificationManager is somehow the wrong one in this scenario.
Problem is I have not been able to recreate this scenario at all, nor am I able to come up with a reliable way to ensure the context is the right one (by casting/contextWrapping it).
The app has 3 possible context entry points, as far as I can tell:
- From the app itself, when the app is launched/initiated on its own accord
- Via a
BroadcastReceiver - Via a
ContentProvider
Unfortunately I have already tested as much as I could, even checking the context from the BroadcastReceiver for the automatic app launch after restarting the device and still nothing, everything worked well.
The source code for that single method documents the following:
/**
* Returns all notification channels belonging to the calling package.
*
* <p>Approved notification delegates (see {@link #canNotifyAsPackage(String)}) can query
* notification channels belonging to packages they are the delegate for. To do so, call this
* method from a context created for that package (see
* {@link Context#createPackageContext(String, int)}).</p>
*/
public List<NotificationChannel> getNotificationChannels() {
INotificationManager service = getService();
try {
return service.getNotificationChannels(mContext.getOpPackageName(),
mContext.getPackageName(), mContext.getUserId()).getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
And when following rethrowFromSystemServer leads to this:
/**
* Rethrow this exception when we know it came from the system server. This
* gives us an opportunity to throw a nice clean
* {@link DeadSystemRuntimeException} signal to avoid spamming logs with
* misleading stack traces.
* <p>
* Apps making calls into the system server may end up persisting internal
* state or making security decisions based on the perceived success or
* failure of a call, or any default values returned. For this reason, we
* want to strongly throw when there was trouble with the transaction.
*
* @throws RuntimeException
*/
@NonNull
public RuntimeException rethrowFromSystemServer() {
if (this instanceof DeadObjectException) {
throw new DeadSystemRuntimeException();
} else {
throw new RuntimeException(this);
}
}
Which is the only clue that lead me to believe somehow, under some unknown circumstance, the app is being launched with a context that is not its own, thus leading to the mentioned DeadSystemException crash which made me believe for a while it meant the device had crashed and was restarting, until I noticed it was always happening, and only happening, when accessing that exact same method and no other.
I cannot find any clear explanation as to why this is happening, nor a clear way to fix it other than to surround it in a try...catch, so I am hoping someone might have come across this before and knows what is going on, or at the very least might be able to provide a way to recreate the issue in order to come up with a proper fix.
Does anyone know why this is happening and how to fix it? Or at the very least how to recreate this crash?