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.
This commit is contained in:
Peter Cai 2022-03-12 22:55:14 -05:00
parent d8d49e03a0
commit 437002d189
1 changed files with 17 additions and 11 deletions

View File

@ -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