~singpolyma/cheogram-android

437002d1898a343c1adcf511b3a7211c99d579df — Peter Cai 1 year, 19 days ago d8d49e0
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.
1 files changed, 17 insertions(+), 11 deletions(-)

M src/cheogram/java/com/cheogram/android/ConnectionService.java
M src/cheogram/java/com/cheogram/android/ConnectionService.java => src/cheogram/java/com/cheogram/android/ConnectionService.java +17 -11
@@ 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