From 437002d1898a343c1adcf511b3a7211c99d579df Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Sat, 12 Mar 2022 22:55:14 -0500 Subject: [PATCH] ConnectionService: handle disconnected state correctly onDisconnect() will only be called when the user manually requests a disconnect. When the call is disconnected by the rtp connection itself, the call won't be cleaned up and the system will be stuck in an in-call state. Handle this correctly by moving the clean-up code to a close() function, and calling that function instead when we disconnect. Note that we cannot call the cleanup routine destroy() from the onStateChanged() function, because it seems that this triggers a deadlock somewhere down the line, probably in the calling account-related telephony code. Doing a close() function mirrors what is done in the default TelephonyConnection implementation for RIL-based calls. --- .../cheogram/android/ConnectionService.java | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/cheogram/java/com/cheogram/android/ConnectionService.java b/src/cheogram/java/com/cheogram/android/ConnectionService.java index be497a8b8..08091e2d7 100644 --- a/src/cheogram/java/com/cheogram/android/ConnectionService.java +++ b/src/cheogram/java/com/cheogram/android/ConnectionService.java @@ -136,7 +136,7 @@ public class ConnectionService extends android.telecom.ConnectionService { @Override public void onPermissionDenied(DeniedPermissions deniedPermissions) { - connection.setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); + connection.close(new DisconnectCause(DisconnectCause.ERROR)); } }); @@ -237,13 +237,13 @@ public class ConnectionService extends android.telecom.ConnectionService { postDial(); } else if (state == RtpEndUserState.DECLINED_OR_BUSY) { - setDisconnected(new DisconnectCause(DisconnectCause.BUSY)); + close(new DisconnectCause(DisconnectCause.BUSY)); } else if (state == RtpEndUserState.ENDED) { - setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); + close(new DisconnectCause(DisconnectCause.LOCAL)); } else if (state == RtpEndUserState.RETRACTED) { - setDisconnected(new DisconnectCause(DisconnectCause.CANCELED)); + close(new DisconnectCause(DisconnectCause.CANCELED)); } else if (RtpSessionActivity.END_CARD.contains(state)) { - setDisconnected(new DisconnectCause(DisconnectCause.ERROR)); + close(new DisconnectCause(DisconnectCause.ERROR)); } } @@ -278,21 +278,27 @@ public class ConnectionService extends android.telecom.ConnectionService { public void onReject() { this.rtpConnection = xmppConnectionService.getJingleConnectionManager().findJingleRtpConnection(account, with, sessionId); rtpConnection.get().rejectCall(); - setDisconnected(new DisconnectCause(DisconnectCause.LOCAL)); + close(new DisconnectCause(DisconnectCause.LOCAL)); + } + + // Set the connection to the disconnected state and clean up the resources + // Note that we cannot do this from onStateChanged() because calling destroy + // there seems to trigger a deadlock somewhere in the telephony stack. + public void close(DisconnectCause reason) { + setDisconnected(reason); + destroy(); + xmppConnectionService.setDiallerIntegrationActive(false); + xmppConnectionService.removeRtpConnectionUpdateListener(this); } @Override public void onDisconnect() { if (rtpConnection == null || rtpConnection.get() == null) { xmppConnectionService.getJingleConnectionManager().retractSessionProposal(account, with.asBareJid()); + close(new DisconnectCause(DisconnectCause.LOCAL)); } else { rtpConnection.get().endCall(); } - destroy(); - xmppConnectionService.setDiallerIntegrationActive(false); - xmppConnectionService.removeRtpConnectionUpdateListener( - (XmppConnectionService.OnJingleRtpConnectionUpdate) this - ); } @Override