hook into onAnswer/onReject of CallIntegration

the Operating System shows a notification on our behalf if there is currently
a call going on that can not be put on hold (For example a Quicksy call is going
on while a Conversations call is coming on)
This commit is contained in:
Daniel Gultsch 2024-01-15 13:20:39 +01:00
parent f119c36bff
commit 6975299a28
No known key found for this signature in database
GPG key ID: F43D18AD2A0982C2
3 changed files with 78 additions and 22 deletions

View file

@ -60,7 +60,7 @@ public class CallIntegration extends Connection {
@Override
public void onAnswer() {
Log.d(Config.LOGTAG, "onAnswer()");
this.callback.onCallIntegrationAnswer();
}
@Override
@ -71,12 +71,13 @@ public class CallIntegration extends Connection {
@Override
public void onReject() {
Log.d(Config.LOGTAG, "onReject()");
this.callback.onCallIntegrationReject();
}
@Override
public void onReject(final String replyMessage) {
Log.d(Config.LOGTAG, "onReject(" + replyMessage + ")");
this.callback.onCallIntegrationReject();
}
@RequiresApi(api = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
@ -404,5 +405,9 @@ public class CallIntegration extends Connection {
void onAudioDeviceChanged(
CallIntegration.AudioDevice selectedAudioDevice,
Set<CallIntegration.AudioDevice> availableAudioDevices);
void onCallIntegrationReject();
void onCallIntegrationAnswer();
}
}

View file

@ -1109,5 +1109,15 @@ public class JingleConnectionManager extends AbstractConnectionManager {
public void onAudioDeviceChanged(
CallIntegration.AudioDevice selectedAudioDevice,
Set<CallIntegration.AudioDevice> availableAudioDevices) {}
@Override
public void onCallIntegrationReject() {
}
@Override
public void onCallIntegrationAnswer() {
}
}
}

View file

@ -1,6 +1,6 @@
package eu.siacs.conversations.xmpp.jingle;
import android.telecom.Call;
import android.content.Intent;
import android.telecom.TelecomManager;
import android.util.Log;
@ -35,6 +35,7 @@ import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.RtpSessionStatus;
import eu.siacs.conversations.services.AppRTCAudioManager;
import eu.siacs.conversations.services.CallIntegration;
import eu.siacs.conversations.ui.RtpSessionActivity;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.Jid;
@ -75,7 +76,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
private static final long BUSY_TIME_OUT = 30;
private final WebRTCWrapper webRTCWrapper = new WebRTCWrapper(this);
private final Queue<Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>>>
private final Queue<
Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>>>
pendingIceCandidates = new LinkedList<>();
private final OmemoVerification omemoVerification = new OmemoVerification();
private final CallIntegration callIntegration;
@ -91,13 +93,28 @@ public class JingleRtpConnection extends AbstractJingleConnection
private final Queue<PeerConnection.PeerConnectionState> stateHistory = new LinkedList<>();
private ScheduledFuture<?> ringingTimeoutFuture;
JingleRtpConnection(final JingleConnectionManager jingleConnectionManager, final Id id, final Jid initiator) {
this(jingleConnectionManager, id, initiator, new CallIntegration(jingleConnectionManager.getXmppConnectionService().getApplicationContext()));
this.callIntegration.setAddress(CallIntegration.address(id.with.asBareJid()), TelecomManager.PRESENTATION_ALLOWED);
JingleRtpConnection(
final JingleConnectionManager jingleConnectionManager,
final Id id,
final Jid initiator) {
this(
jingleConnectionManager,
id,
initiator,
new CallIntegration(
jingleConnectionManager
.getXmppConnectionService()
.getApplicationContext()));
this.callIntegration.setAddress(
CallIntegration.address(id.with.asBareJid()), TelecomManager.PRESENTATION_ALLOWED);
this.callIntegration.setInitialized();
}
JingleRtpConnection(final JingleConnectionManager jingleConnectionManager, final Id id, final Jid initiator, final CallIntegration callIntegration) {
JingleRtpConnection(
final JingleConnectionManager jingleConnectionManager,
final Id id,
final Jid initiator,
final CallIntegration callIntegration) {
super(jingleConnectionManager, id, initiator);
final Conversation conversation =
jingleConnectionManager
@ -231,8 +248,8 @@ public class JingleRtpConnection extends AbstractJingleConnection
private void receiveTransportInfo(
final JinglePacket jinglePacket, final RtpContentMap contentMap) {
final Set<Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>>> candidates =
contentMap.contents.entrySet();
final Set<Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>>>
candidates = contentMap.contents.entrySet();
final RtpContentMap remote = getRemoteContentMap();
final Set<String> remoteContentIds =
remote == null ? Collections.emptySet() : remote.contents.keySet();
@ -1004,14 +1021,17 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
private void processCandidates(
final Set<Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>>> contents) {
for (final Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>> content : contents) {
final Set<Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>>>
contents) {
for (final Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>>
content : contents) {
processCandidate(content);
}
}
private void processCandidate(
final Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>> content) {
final Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>>
content) {
final RtpContentMap rtpContentMap = getRemoteContentMap();
final List<String> indices = toIdentificationTags(rtpContentMap);
final String sdpMid = content.getKey(); // aka content name
@ -1382,7 +1402,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
private void addIceCandidatesFromBlackLog() {
Map.Entry<String, DescriptionTransport<RtpDescription,IceUdpTransportInfo>> foo;
Map.Entry<String, DescriptionTransport<RtpDescription, IceUdpTransportInfo>> foo;
while ((foo = this.pendingIceCandidates.poll()) != null) {
processCandidate(foo);
Log.d(
@ -1960,12 +1980,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
sendSessionTerminate(reason, null);
}
protected void sendSessionTerminate(final Reason reason, final String text) {
sendSessionTerminate(reason,text, this::writeLogMessage);
sendSessionTerminate(reason, text, this::writeLogMessage);
}
private void sendTransportInfo(
final String contentName, IceUdpTransportInfo.Candidate candidate) {
final RtpContentMap transportInfo;
@ -2351,7 +2369,6 @@ public class JingleRtpConnection extends AbstractJingleConnection
sendSessionAccept();
}
@Override
protected synchronized boolean transition(final State target, final Runnable runnable) {
if (super.transition(target, runnable)) {
@ -2592,7 +2609,6 @@ public class JingleRtpConnection extends AbstractJingleConnection
private void modifyLocalContentMap(final RtpContentMap rtpContentMap) {
final RtpContentMap activeContents = rtpContentMap.activeContents();
setLocalContentMap(activeContents);
// TODO change audio device on callIntegration was (`switchSpeakerPhonePreference(AppRTCAudioManager.SpeakerPhonePreference.of(activeContents.getMedia())`)
updateEndUserState();
}
@ -2625,7 +2641,6 @@ public class JingleRtpConnection extends AbstractJingleConnection
return this.sessionDuration.elapsed(TimeUnit.MILLISECONDS);
}
public CallIntegration getCallIntegration() {
return this.callIntegration;
}
@ -2673,11 +2688,37 @@ public class JingleRtpConnection extends AbstractJingleConnection
}
}
@Override
public void onCallIntegrationReject() {
Log.d(Config.LOGTAG, "rejecting call from system notification / call integration");
try {
rejectCall();
} catch (final IllegalStateException e) {
Log.w(Config.LOGTAG, "race condition on rejecting call from notification", e);
}
}
@Override
public void onCallIntegrationAnswer() {
// we need to start the UI to a) show it and b) be able to ask for permissions
final Intent intent = new Intent(xmppConnectionService, RtpSessionActivity.class);
intent.setAction(RtpSessionActivity.ACTION_ACCEPT_CALL);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, id.account.getJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toEscapedString());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
Log.d(Config.LOGTAG, "start activity to accept call from call integration");
xmppConnectionService.startActivity(intent);
}
@Override
public void onAudioDeviceChanged(
final CallIntegration.AudioDevice selectedAudioDevice,
final Set<CallIntegration.AudioDevice> availableAudioDevices) {
Log.d(Config.LOGTAG,"onAudioDeviceChanged("+selectedAudioDevice+","+availableAudioDevices+")");
Log.d(
Config.LOGTAG,
"onAudioDeviceChanged(" + selectedAudioDevice + "," + availableAudioDevices + ")");
xmppConnectionService.notifyJingleRtpConnectionUpdate(
selectedAudioDevice, availableAudioDevices);
}
@ -2732,7 +2773,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
onIceServersDiscovered.onIceServersDiscovered(Collections.emptyList());
}
}
@Override
protected void terminateTransport() {
this.webRTCWrapper.close();