Exception java.lang.IllegalStateException: Already resumed, but proposed with update false
Closed this issue · 8 comments
I've copied this from the Google Play Console. Not occurring often but we should fix it ;-)
Exception java.lang.IllegalStateException: Already resumed, but proposed with update false
at kotlinx.coroutines.CancellableContinuationImpl.alreadyResumedError (CancellableContinuationImpl.kt:559)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl (CancellableContinuationImpl.kt:524)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default (CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith (CancellableContinuationImpl.kt:368)
at at.bitfire.cert4android.UserDecisionRegistry.onUserDecision (UserDecisionRegistry.kt:113)
at at.bitfire.cert4android.TrustCertificateActivity$Model.registerDecision (TrustCertificateActivity.kt:312)
at at.bitfire.cert4android.TrustCertificateActivity$onCreate$2.handleOnBackPressed (TrustCertificateActivity.kt:77)
at androidx.activity.OnBackPressedDispatcher.onBackPressed (OnBackPressedDispatcher.kt:213)
at androidx.activity.ComponentActivity.onBackPressed (ComponentActivity.java:694)
at android.app.Activity.onKeyUp (Activity.java:3940)
at android.view.KeyEvent.dispatch (KeyEvent.java:3143)
at android.app.Activity.dispatchKeyEvent (Activity.java:4286)
at androidx.core.app.ComponentActivity.superDispatchKeyEvent (ComponentActivity.java:126)
at androidx.core.view.KeyEventDispatcher.dispatchKeyEvent (KeyEventDispatcher.java:86)
at androidx.core.app.ComponentActivity.dispatchKeyEvent (ComponentActivity.java:144)
at com.android.internal.policy.DecorView.dispatchKeyEvent (DecorView.java:415)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent (ViewRootImpl.java:6664)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:6530)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:5990)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:6047)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:6013)
at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:6178)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:6021)
at android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:6235)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:5994)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:6047)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:6013)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:6021)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:5994)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:6047)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:6013)
at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:6211)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent (ViewRootImpl.java:6391)
at android.view.inputmethod.InputMethodManager$PendingEvent.run (InputMethodManager.java:3667)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback (InputMethodManager.java:3187)
at android.view.inputmethod.InputMethodManager.finishedInputEvent (InputMethodManager.java:3178)
at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished (InputMethodManager.java:3644)
at android.view.InputEventSender.dispatchInputEventFinished (InputEventSender.java:154)
at android.os.MessageQueue.nativePollOnce
at android.os.MessageQueue.next (MessageQueue.java:335)
at android.os.Looper.loopOnce (Looper.java:185)
at android.os.Looper.loop (Looper.java:359)
at android.app.ActivityThread.main (ActivityThread.java:8127)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:942)
I'm trying everything that comes to my mind to reproduce this, with no success. It's clear from the error that it's thrown by pressing back after a certificate decision, which sends a second result, causing the error.
I've tried tapping reject and back as quick as possible, and it's not feasible that this is the issue. The other thing that I can think of is that the activity is not getting closed for some reason after accepting the certificate, and the user tries to tap back, which gives a second answer. However, I'm not able to force this behavior by any means.
Update: Not only happens on back press but also on tapping:
Exception java.lang.IllegalStateException: Already resumed, but proposed with update true
at kotlinx.coroutines.CancellableContinuationImpl.alreadyResumedError (CancellableContinuationImpl.kt:559)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl (CancellableContinuationImpl.kt:524)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default (CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith (CancellableContinuationImpl.kt:368)
at at.bitfire.cert4android.UserDecisionRegistry.onUserDecision (UserDecisionRegistry.kt:113)
at at.bitfire.cert4android.TrustCertificateActivity$Model.registerDecision (TrustCertificateActivity.kt:312)
at at.bitfire.cert4android.TrustCertificateActivity$CertificateCard$1$1$2$1.invoke (TrustCertificateActivity.kt:211)
at at.bitfire.cert4android.TrustCertificateActivity$CertificateCard$1$1$2$1.invoke (TrustCertificateActivity.kt:208)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke-k-4lQ0M (Clickable.kt:895)
at androidx.compose.foundation.ClickablePointerInputNode$pointerInput$3.invoke (Clickable.kt:889)
at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1.invokeSuspend (TapGestureDetector.kt:255)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume (DispatchedTask.kt:179)
at kotlinx.coroutines.CancellableContinuationImpl.takeState$kotlinx_coroutines_core (CancellableContinuationImpl.kt:168)
at kotlinx.coroutines.DispatchedTaskKt.dispatch (DispatchedTask.kt:168)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume (CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl (CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default (CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith (CancellableContinuationImpl.kt:368)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl$PointerEventHandlerCoroutine.offerPointerEvent (SuspendingPointerInputModifierNodeImpl.java:665)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.dispatchPointerEvent (SuspendingPointerInputFilter.kt:544)
at androidx.compose.ui.input.pointer.SuspendingPointerInputModifierNodeImpl.onPointerEvent-H0pRuoY (SuspendingPointerInputFilter.kt:566)
at androidx.compose.foundation.AbstractClickablePointerInputNode.onPointerEvent-H0pRuoY (AbstractClickablePointerInputNode.java:855)
at androidx.compose.foundation.AbstractClickableNode.onPointerEvent-H0pRuoY (Clickable.kt:703)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:317)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass (HitPathTracker.kt:303)
at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass (NodeParent.java:183)
at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges (HitPathTracker.kt:102)
at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog (PointerInputEventProcessor.kt:96)
at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc (AndroidComposeView.android.kt:1446)
at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc (AndroidComposeView.android.kt:1398)
at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent (AndroidComposeView.android.kt:1338)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3361)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3035)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3361)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3035)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3361)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3035)
at android.view.ViewGroup.dispatchTransformedTouchEvent (ViewGroup.java:3361)
at android.view.ViewGroup.dispatchTouchEvent (ViewGroup.java:3035)
at com.android.internal.policy.DecorView.superDispatchTouchEvent (DecorView.java:1127)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent (PhoneWindow.java:1971)
at android.app.Activity.dispatchTouchEvent (Activity.java:4410)
at com.android.internal.policy.DecorView.dispatchTouchEvent (DecorView.java:1079)
at android.view.View.dispatchPointerEvent (View.java:15866)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent (ViewRootImpl.java:8264)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess (ViewRootImpl.java:7955)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7291)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:7348)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:7314)
at android.view.ViewRootImpl$AsyncInputStage.forward (ViewRootImpl.java:7512)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:7322)
at android.view.ViewRootImpl$AsyncInputStage.apply (ViewRootImpl.java:7569)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7295)
at android.view.ViewRootImpl$InputStage.onDeliverToNext (ViewRootImpl.java:7348)
at android.view.ViewRootImpl$InputStage.forward (ViewRootImpl.java:7314)
at android.view.ViewRootImpl$InputStage.apply (ViewRootImpl.java:7322)
at android.view.ViewRootImpl$InputStage.deliver (ViewRootImpl.java:7295)
at android.view.ViewRootImpl.deliverInputEvent (ViewRootImpl.java:10971)
at android.view.ViewRootImpl.doProcessInputEvents (ViewRootImpl.java:10853)
at android.view.ViewRootImpl.enqueueInputEvent (ViewRootImpl.java:10809)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent (ViewRootImpl.java:11109)
at android.view.InputEventReceiver.dispatchInputEvent (InputEventReceiver.java:295)
at android.os.MessageQueue.nativePollOnce
at android.os.MessageQueue.next (MessageQueue.java:335)
at android.os.Looper.loopOnce (Looper.java:186)
at android.os.Looper.loop (Looper.java:313)
at android.app.ActivityThread.main (ActivityThread.java:8810)
at java.lang.reflect.Method.invoke
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:604)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1067)
I've only found it crashing on Android 13, so maybe something to take into consideration...
Maybe replacing the iterator call
with something like?
synchronized(pendingDecisions) {
pendingDecisions[cert]?.removeAll {
it.resume(trusted)
true
}
}
Or directly annontating onUserDecision
with @Synchronized
?
Tried things:
- Quickly tapping multiple options at the same time (eg back and reject, or reject and accept)
- Dismiss notification with decision activity open (activity just closes automatically)
I think this might be related to timeout. In fact, I think it doesn't even work at all. My thoughts are that timeout is giving an answer to the request, but not closing the activity, so whenever you press back, deny or whatever, you are giving an extra answer, which causes the error. I haven't been able to reproduce it yet, though.
Also no clue why it's only happening on Android 13.
Update: this is not the issue, but it's a new thing to fix. When the request times out, the Activity doesn't close. Something to look into.
Update 2: Timeout is not inside the suspendCancellableCoroutine
, not even inside the UserDecisionRegistry
, so it has nothing to do with the continuation. So not related to the issue, but something to take into account.
I think this might be related to timeout. In fact, I think it doesn't even work at all. My thoughts are that timeout is giving an answer to the request, but not closing the activity, so whenever you press back, deny or whatever, you are giving an extra answer, which causes the error. I haven't been able to reproduce it yet, though.
That's by intention (see #30), however accepting/denying shouldn't give an extra answer. I didn't see where this could happen by now…
Also no clue why it's only happening on Android 13.
This code is only executing in Android 13 (because the notification permission only exists since Android 13) and it contains a cont.resume()
… quite suspicious:
Found out how to reproduce it 😃
- Open cert4android demo in Android 13. Make sure that notification permissions are not granted.
- Uncheck App in foreground
- Access URL with self-signed certificate. The code cited above sends
cont.resume(false)
and the request fails. However, the request is still inpendingDecisions
. - Check App in foreground.
- Access URL with self-signed certificate again. The activity opens. Accept the certificate.
- The app crashes with
java.lang.IllegalStateException: Already resumed, but proposed with update false
because allpendingDecisions
are continued (including the one that has already been continued because the app was in background).