diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 7075be30e..4052c7f85 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -81,6 +81,8 @@
android:name=".service.ForegroundService"
android:exported="false" />
+
+
diff --git a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java
index 04cea807d..baa66f083 100644
--- a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java
+++ b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/AbstractJingleConnection.java
@@ -1,6 +1,7 @@
package eu.siacs.conversations.xmpp.jingle;
import android.content.Context;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
@@ -84,6 +85,14 @@ public abstract class AbstractJingleConnection extends XmppConnection.Delegate {
public int hashCode() {
return Objects.hashCode(with, sessionId);
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("with", with)
+ .add("sessionId", sessionId)
+ .toString();
+ }
}
public enum State {
diff --git a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
index 49380bfea..0cc10008d 100644
--- a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
+++ b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java
@@ -30,7 +30,9 @@ import im.conversations.android.BuildConfig;
import im.conversations.android.axolotl.AxolotlEncryptionException;
import im.conversations.android.axolotl.AxolotlService;
import im.conversations.android.dns.IP;
+import im.conversations.android.notification.OngoingCall;
import im.conversations.android.notification.RtpSessionNotification;
+import im.conversations.android.service.RtpSessionService;
import im.conversations.android.transformer.CallLogTransformation;
import im.conversations.android.util.BooleanFutures;
import im.conversations.android.xml.Element;
@@ -592,7 +594,10 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.incomingContentAdd = null;
updateEndUserState();
} else {
- LOGGER.info("content add summary {} did not match remove summary {}", contentAddSummary, removeSummary);
+ LOGGER.info(
+ "content add summary {} did not match remove summary {}",
+ contentAddSummary,
+ removeSummary);
webRTCWrapper.close();
sendSessionTerminate(
Reason.FAILED_APPLICATION,
@@ -2424,6 +2429,7 @@ public class JingleRtpConnection extends AbstractJingleConnection
this.webRTCWrapper.switchSpeakerPhonePreference(
AppRTCAudioManager.SpeakerPhonePreference.of(activeContents.getMedia()));
updateEndUserState();
+ updateOngoingCallNotification();
}
private SessionDescription setLocalSessionDescription()
@@ -2505,21 +2511,26 @@ public class JingleRtpConnection extends AbstractJingleConnection
private void updateOngoingCallNotification() {
final State state = this.state;
if (STATES_SHOWING_ONGOING_CALL.contains(state)) {
- final boolean reconnecting;
+ RtpSessionService.updateOngoingCall(context, getAccount().id, id);
+ } else {
+ RtpSessionService.stop(context);
+ }
+ }
+
+ public OngoingCall getOngoingCall() {
+ final State state = this.state;
+ final boolean reconnecting;
+ if (STATES_SHOWING_ONGOING_CALL.contains(state)) {
if (state == State.SESSION_ACCEPTED) {
reconnecting =
getPeerConnectionStateAsEndUserState() == RtpEndUserState.RECONNECTING;
} else {
reconnecting = false;
}
-
- // TODO decide what we want to do with ongoing call? create a foreground service of
- // RtpSessionService?
-
- // xmppConnectionService.setOngoingCall(id, getMedia(), reconnecting);
} else {
- // xmppConnectionService.removeOngoingCall();
+ reconnecting = false;
}
+ return new OngoingCall(id, getMedia(), reconnecting);
}
private void discoverIceServers(final OnIceServersDiscovered onIceServersDiscovered) {
diff --git a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java
index 2093fbf18..38d4e4c50 100644
--- a/app/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java
+++ b/app/src/main/java/eu/siacs/conversations/xmpp/jingle/TrackWrapper.java
@@ -38,7 +38,9 @@ class TrackWrapper {
final RtpTransceiver transceiver =
peerConnection == null ? null : getTransceiver(peerConnection, trackWrapper);
if (transceiver == null) {
- Log.w(Config.LOGTAG, "unable to detect transceiver for " + trackWrapper.getRtpSenderId());
+ Log.w(
+ Config.LOGTAG,
+ "unable to detect transceiver for " + trackWrapper.getRtpSenderId());
return Optional.of(trackWrapper.track);
}
final RtpTransceiver.RtpTransceiverDirection direction = transceiver.getDirection();
@@ -62,10 +64,13 @@ class TrackWrapper {
public static RtpTransceiver getTransceiver(
@Nonnull final PeerConnection peerConnection, final TrackWrapper trackWrapper) {
final String rtpSenderId = trackWrapper.getRtpSenderId();
+ if (rtpSenderId == null) {
+ return null;
+ }
for (final RtpTransceiver transceiver : peerConnection.getTransceivers()) {
- if (transceiver.getSender().id().equals(rtpSenderId)) {
- return transceiver;
- }
+ if (transceiver.getSender().id().equals(rtpSenderId)) {
+ return transceiver;
+ }
}
return null;
}
diff --git a/app/src/main/java/im/conversations/android/notification/Channels.java b/app/src/main/java/im/conversations/android/notification/Channels.java
index 0477838ba..3cb086e70 100644
--- a/app/src/main/java/im/conversations/android/notification/Channels.java
+++ b/app/src/main/java/im/conversations/android/notification/Channels.java
@@ -12,7 +12,8 @@ import im.conversations.android.R;
public final class Channels {
static final String CHANNEL_FOREGROUND = "foreground";
- static final String INCOMING_CALLS_NOTIFICATION_CHANNEL = "incoming_calls_channel";
+ static final String CHANNEL_INCOMING_CALL = "incoming_calls_channel";
+ static final String CHANNEL_ONGOING_CALL = "ongoing_call";
static final String CHANNEL_GROUP_STATUS = "status";
static final String CHANNEL_GROUP_CALLS = "calls";
private final Application application;
@@ -32,9 +33,22 @@ public final class Channels {
this.initializeForegroundChannel(notificationManager);
this.initializeIncomingCallChannel(notificationManager);
+ this.initializeOngoingCallChannel(notificationManager);
}
}
+ @RequiresApi(api = Build.VERSION_CODES.O)
+ private void initializeOngoingCallChannel(NotificationManager notificationManager) {
+ final NotificationChannel ongoingCallsChannel =
+ new NotificationChannel(
+ CHANNEL_ONGOING_CALL,
+ application.getString(R.string.ongoing_calls_channel_name),
+ NotificationManager.IMPORTANCE_LOW);
+ ongoingCallsChannel.setShowBadge(false);
+ ongoingCallsChannel.setGroup(CHANNEL_GROUP_CALLS);
+ notificationManager.createNotificationChannel(ongoingCallsChannel);
+ }
+
@RequiresApi(api = Build.VERSION_CODES.O)
private void initializeGroups(NotificationManager notificationManager) {
notificationManager.createNotificationChannelGroup(
@@ -67,7 +81,7 @@ public final class Channels {
private void initializeIncomingCallChannel(final NotificationManager notificationManager) {
final NotificationChannel incomingCallsChannel =
new NotificationChannel(
- INCOMING_CALLS_NOTIFICATION_CHANNEL,
+ CHANNEL_INCOMING_CALL,
application.getString(R.string.incoming_calls_channel_name),
NotificationManager.IMPORTANCE_HIGH);
incomingCallsChannel.setSound(null, null);
diff --git a/app/src/main/java/im/conversations/android/notification/OngoingCall.java b/app/src/main/java/im/conversations/android/notification/OngoingCall.java
index 9bb5b4b85..4e34c892f 100644
--- a/app/src/main/java/im/conversations/android/notification/OngoingCall.java
+++ b/app/src/main/java/im/conversations/android/notification/OngoingCall.java
@@ -1,5 +1,6 @@
package im.conversations.android.notification;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
import eu.siacs.conversations.xmpp.jingle.Media;
@@ -31,4 +32,13 @@ public class OngoingCall {
public int hashCode() {
return Objects.hashCode(id, media, reconnecting);
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("id", id)
+ .add("media", media)
+ .add("reconnecting", reconnecting)
+ .toString();
+ }
}
diff --git a/app/src/main/java/im/conversations/android/notification/RtpSessionNotification.java b/app/src/main/java/im/conversations/android/notification/RtpSessionNotification.java
index 7b6a6804f..1269862d0 100644
--- a/app/src/main/java/im/conversations/android/notification/RtpSessionNotification.java
+++ b/app/src/main/java/im/conversations/android/notification/RtpSessionNotification.java
@@ -15,6 +15,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Vibrator;
import android.preference.PreferenceManager;
+import android.service.notification.StatusBarNotification;
import android.util.Log;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
@@ -40,6 +41,7 @@ public class RtpSessionNotification extends AbstractNotification {
private static final Logger LOGGER = LoggerFactory.getLogger(RtpSessionNotification.class);
public static final int INCOMING_CALL_ID = 2;
+ public static final int ONGOING_CALL_ID = 3;
public static final int LED_COLOR = 0xff00ff00;
@@ -149,8 +151,7 @@ public class RtpSessionNotification extends AbstractNotification {
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
fullScreenIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
final NotificationCompat.Builder builder =
- new NotificationCompat.Builder(
- context, Channels.INCOMING_CALLS_NOTIFICATION_CHANNEL);
+ new NotificationCompat.Builder(context, Channels.CHANNEL_INCOMING_CALL);
if (media.contains(Media.VIDEO)) {
builder.setSmallIcon(R.drawable.ic_videocam_24dp);
builder.setContentTitle(context.getString(R.string.rtp_state_incoming_video_call));
@@ -181,7 +182,7 @@ public class RtpSessionNotification extends AbstractNotification {
R.drawable.ic_call_end_24dp,
context.getString(R.string.dismiss_call),
createCallAction(
- id.sessionId, RtpSessionService.ACTION_DISMISS_CALL, 102))
+ account, id, RtpSessionService.ACTION_REJECT_CALL, 102))
.build());
builder.addAction(
new NotificationCompat.Action.Builder(
@@ -199,7 +200,7 @@ public class RtpSessionNotification extends AbstractNotification {
public Notification getOngoingCallNotification(final Account account, OngoingCall ongoingCall) {
final AbstractJingleConnection.Id id = ongoingCall.id;
final NotificationCompat.Builder builder =
- new NotificationCompat.Builder(context, "ongoing_calls");
+ new NotificationCompat.Builder(context, Channels.CHANNEL_ONGOING_CALL);
if (ongoingCall.media.contains(Media.VIDEO)) {
builder.setSmallIcon(R.drawable.ic_videocam_24dp);
if (ongoingCall.reconnecting) {
@@ -216,7 +217,8 @@ public class RtpSessionNotification extends AbstractNotification {
}
}
// TODO fix me when we have a Contact model
- // builder.setContentText(id.account.getRoster().getContact(id.with).getDisplayName());
+ builder.setContentText(
+ "Contact Name"); // id.account.getRoster().getContact(id.with).getDisplayName());
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
builder.setPriority(NotificationCompat.PRIORITY_HIGH);
builder.setCategory(NotificationCompat.CATEGORY_CALL);
@@ -227,11 +229,26 @@ public class RtpSessionNotification extends AbstractNotification {
R.drawable.ic_call_end_24dp,
context.getString(R.string.hang_up),
createCallAction(
- id.sessionId, RtpSessionService.ACTION_END_CALL, 104))
+ account, id, RtpSessionService.ACTION_END_CALL, 104))
.build());
return builder.build();
}
+ public static boolean isShowingOngoingCallNotification(final Context context) {
+ final var notificationManager =
+ ContextCompat.getSystemService(context, NotificationManager.class);
+ if (notificationManager == null) {
+ return false;
+ }
+ for (final StatusBarNotification statusBarNotification :
+ notificationManager.getActiveNotifications()) {
+ if (statusBarNotification.getId() == ONGOING_CALL_ID) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private PendingIntent createPendingRtpSession(
final Account account,
final AbstractJingleConnection.Id id,
@@ -249,11 +266,14 @@ public class RtpSessionNotification extends AbstractNotification {
PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
}
- private PendingIntent createCallAction(String sessionId, final String action, int requestCode) {
+ private PendingIntent createCallAction(
+ Account account, AbstractJingleConnection.Id id, final String action, int requestCode) {
final Intent intent = new Intent(context, RtpSessionService.class);
intent.setAction(action);
intent.setPackage(context.getPackageName());
- intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, sessionId);
+ intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account.id);
+ intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
return PendingIntent.getService(
context,
requestCode,
@@ -273,6 +293,8 @@ public class RtpSessionNotification extends AbstractNotification {
public void pushMissedCallNow(CallLogTransformation message) {}
+ public void cancelOngoingCallNotification() {}
+
private class VibrationRunnable implements Runnable {
@Override
diff --git a/app/src/main/java/im/conversations/android/service/ForegroundService.java b/app/src/main/java/im/conversations/android/service/ForegroundService.java
index 1ee86972b..a5e064e30 100644
--- a/app/src/main/java/im/conversations/android/service/ForegroundService.java
+++ b/app/src/main/java/im/conversations/android/service/ForegroundService.java
@@ -5,6 +5,7 @@ import android.content.Intent;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleService;
import im.conversations.android.notification.ForegroundServiceNotification;
+import im.conversations.android.notification.RtpSessionNotification;
import im.conversations.android.xmpp.ConnectionPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -19,7 +20,6 @@ public class ForegroundService extends LifecycleService {
@Override
public void onCreate() {
super.onCreate();
- LOGGER.info("Creating service");
final var pool = ConnectionPool.getInstance(this);
startForeground(
ForegroundServiceNotification.ID,
@@ -39,6 +39,14 @@ public class ForegroundService extends LifecycleService {
}
public static void start(final Context context) {
+ if (RtpSessionNotification.isShowingOngoingCallNotification(context)) {
+ LOGGER.info("Do not start foreground service. Ongoing call.");
+ return;
+ }
+ startForegroundService(context);
+ }
+
+ static void startForegroundService(final Context context) {
try {
ContextCompat.startForegroundService(
context, new Intent(context, ForegroundService.class));
@@ -46,4 +54,9 @@ public class ForegroundService extends LifecycleService {
LOGGER.error("Could not start foreground service", e);
}
}
+
+ public static void stop(final Context context) {
+ final var intent = new Intent(context, ForegroundService.class);
+ context.stopService(intent);
+ }
}
diff --git a/app/src/main/java/im/conversations/android/service/RtpSessionService.java b/app/src/main/java/im/conversations/android/service/RtpSessionService.java
index a341f6c93..b95a536d4 100644
--- a/app/src/main/java/im/conversations/android/service/RtpSessionService.java
+++ b/app/src/main/java/im/conversations/android/service/RtpSessionService.java
@@ -1,16 +1,153 @@
package im.conversations.android.service;
+import android.app.Service;
+import android.content.Context;
import android.content.Intent;
+import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleService;
+import com.google.common.base.Strings;
+import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection;
+import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
+import im.conversations.android.notification.RtpSessionNotification;
+import im.conversations.android.ui.activity.RtpSessionActivity;
+import im.conversations.android.xmpp.ConnectionPool;
+import im.conversations.android.xmpp.manager.JingleConnectionManager;
+import org.jxmpp.jid.Jid;
+import org.jxmpp.jid.impl.JidCreate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class RtpSessionService extends LifecycleService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(RtpSessionService.class);
- public static final String ACTION_DISMISS_CALL = "dismiss_call";
+ public static final String ACTION_REJECT_CALL = "dismiss_call";
public static final String ACTION_END_CALL = "end_call";
+ public static final String ACTION_UPDATE_ONGOING_CALL = "update_ongoing_call";
+
@Override
public int onStartCommand(final Intent intent, final int flags, final int startId) {
-
+ if (intent == null) {
+ LOGGER.info("Intent was null");
+ return Service.START_NOT_STICKY;
+ }
+ final String sessionId = intent.getStringExtra(RtpSessionActivity.EXTRA_SESSION_ID);
+ final long accountId = intent.getLongExtra(RtpSessionActivity.EXTRA_ACCOUNT, -1);
+ final String with = intent.getStringExtra(RtpSessionActivity.EXTRA_WITH);
+ if (Strings.isNullOrEmpty(sessionId) || accountId < 0 || Strings.isNullOrEmpty(with)) {
+ LOGGER.warn("intent was missing mandatory extras");
+ return Service.START_NOT_STICKY;
+ }
+ final String action = intent.getAction();
+ switch (Strings.nullToEmpty(action)) {
+ case ACTION_UPDATE_ONGOING_CALL:
+ updateOngoingCall(accountId, JidCreate.fromOrThrowUnchecked(with), sessionId);
+ break;
+ case ACTION_REJECT_CALL:
+ rejectCall(accountId, JidCreate.fromOrThrowUnchecked(with), sessionId);
+ break;
+ case ACTION_END_CALL:
+ endCall(accountId, JidCreate.fromOrThrowUnchecked(with), sessionId);
+ break;
+ default:
+ LOGGER.error("Service does not know how to handle {} action", action);
+ }
return super.onStartCommand(intent, flags, startId);
}
+
+ private void endCall(final long account, final Jid with, final String sessionId) {
+ final var jmc =
+ ConnectionPool.getInstance(this)
+ .getOptional(account)
+ .transform(xc -> xc.getManager(JingleConnectionManager.class));
+ if (jmc.isPresent()) {
+ endCall(jmc.get(), with, sessionId);
+ } else {
+ LOGGER.error("Could not end call. JingleConnectionManager not found");
+ }
+ }
+
+ private void endCall(
+ final JingleConnectionManager jingleConnectionManager,
+ final Jid with,
+ final String sessionId) {
+ final var rtpConnection = jingleConnectionManager.getJingleRtpConnection(with, sessionId);
+ if (rtpConnection.isPresent()) {
+ rtpConnection.get().endCall();
+ } else {
+ LOGGER.error("Could not end {} with {}", sessionId, with);
+ }
+ }
+
+ private void rejectCall(long account, Jid with, String sessionId) {
+ final var jmc =
+ ConnectionPool.getInstance(this)
+ .getOptional(account)
+ .transform(xc -> xc.getManager(JingleConnectionManager.class));
+ if (jmc.isPresent()) {
+ rejectCall(jmc.get(), with, sessionId);
+ } else {
+ LOGGER.error("Could not reject call. JingleConnectionManager not found");
+ }
+ }
+
+ private void rejectCall(
+ JingleConnectionManager jingleConnectionManager, Jid with, String sessionId) {
+ final var rtpConnection = jingleConnectionManager.getJingleRtpConnection(with, sessionId);
+ if (rtpConnection.isPresent()) {
+ rtpConnection.get().rejectCall();
+ } else {
+ LOGGER.error("Could not reject call {} with {}", sessionId, with);
+ }
+ }
+
+ private void updateOngoingCall(final long account, final Jid with, final String sessionId) {
+ final var jmc =
+ ConnectionPool.getInstance(this)
+ .getOptional(account)
+ .transform(xc -> xc.getManager(JingleConnectionManager.class));
+ if (jmc.isPresent()) {
+ updateOngoingCall(jmc.get(), with, sessionId);
+ } else {
+ LOGGER.error("JingleConnectionManager not found for {}", account);
+ }
+ }
+
+ private void updateOngoingCall(
+ final JingleConnectionManager jingleConnectionManager,
+ final Jid with,
+ final String sessionId) {
+ final var ongoingCall =
+ jingleConnectionManager
+ .getJingleRtpConnection(with, sessionId)
+ .transform(JingleRtpConnection::getOngoingCall);
+ if (ongoingCall.isPresent()) {
+ LOGGER.info("Updating notification for {}", ongoingCall.get());
+ ForegroundService.stop(this);
+ startForeground(
+ RtpSessionNotification.ONGOING_CALL_ID,
+ jingleConnectionManager
+ .getNotificationService()
+ .getOngoingCallNotification(
+ jingleConnectionManager.getAccount(), ongoingCall.get()));
+ } else {
+ LOGGER.error("JingleRtpConnection not found for {}", sessionId);
+ }
+ }
+
+ public static void updateOngoingCall(
+ final Context context, final long account, final AbstractJingleConnection.Id id) {
+ final var intent = new Intent(context, RtpSessionService.class);
+ intent.setAction(ACTION_UPDATE_ONGOING_CALL);
+ intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, account);
+ intent.putExtra(RtpSessionActivity.EXTRA_WITH, id.with.toString());
+ intent.putExtra(RtpSessionActivity.EXTRA_SESSION_ID, id.sessionId);
+ ContextCompat.startForegroundService(context, intent);
+ }
+
+ public static void stop(final Context context) {
+ final var intent = new Intent(context, RtpSessionService.class);
+ context.stopService(intent);
+ ForegroundService.startForegroundService(context);
+ }
}
diff --git a/app/src/main/java/im/conversations/android/ui/activity/MainActivity.java b/app/src/main/java/im/conversations/android/ui/activity/MainActivity.java
index 1f3f2942c..28a080b80 100644
--- a/app/src/main/java/im/conversations/android/ui/activity/MainActivity.java
+++ b/app/src/main/java/im/conversations/android/ui/activity/MainActivity.java
@@ -15,7 +15,6 @@ public class MainActivity extends BaseActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ForegroundService.start(this);
final ActivityMainBinding binding =
DataBindingUtil.setContentView(this, R.layout.activity_main);
final ViewModelProvider viewModelProvider =
@@ -33,4 +32,10 @@ public class MainActivity extends BaseActivity {
});
Activities.setStatusAndNavigationBarColors(this, binding.getRoot());
}
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ ForegroundService.start(this);
+ }
}
diff --git a/app/src/main/java/im/conversations/android/ui/activity/RtpSessionActivity.java b/app/src/main/java/im/conversations/android/ui/activity/RtpSessionActivity.java
index 28aef0e75..3cdee5472 100644
--- a/app/src/main/java/im/conversations/android/ui/activity/RtpSessionActivity.java
+++ b/app/src/main/java/im/conversations/android/ui/activity/RtpSessionActivity.java
@@ -732,7 +732,7 @@ public class RtpSessionActivity extends BaseActivity
private boolean initializeActivityWithRunningRtpSession(
final Account account, Jid with, String sessionId) {
final WeakReference reference =
- requireJingleConnectionManager().findJingleRtpConnection(with, sessionId);
+ requireJingleConnectionManager().getWeakJingleRtpConnection(with, sessionId);
if (reference == null || reference.get() == null) {
final JingleConnectionManager.TerminatedRtpSession terminatedRtpSession =
requireJingleConnectionManager().getTerminalSessionState(with, sessionId);
diff --git a/app/src/main/java/im/conversations/android/ui/activity/SettingsActivity.java b/app/src/main/java/im/conversations/android/ui/activity/SettingsActivity.java
index 550725e4b..1849b9a1a 100644
--- a/app/src/main/java/im/conversations/android/ui/activity/SettingsActivity.java
+++ b/app/src/main/java/im/conversations/android/ui/activity/SettingsActivity.java
@@ -13,7 +13,6 @@ public class SettingsActivity extends BaseActivity {
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ForegroundService.start(this);
final ActivitySettingsBinding binding =
DataBindingUtil.setContentView(this, R.layout.activity_settings);
setSupportActionBar(binding.materialToolbar);
@@ -36,4 +35,10 @@ public class SettingsActivity extends BaseActivity {
}
});
}
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ ForegroundService.start(this);
+ }
}
diff --git a/app/src/main/java/im/conversations/android/xmpp/ConnectionPool.java b/app/src/main/java/im/conversations/android/xmpp/ConnectionPool.java
index f6d426d1a..17cc9f5c2 100644
--- a/app/src/main/java/im/conversations/android/xmpp/ConnectionPool.java
+++ b/app/src/main/java/im/conversations/android/xmpp/ConnectionPool.java
@@ -109,6 +109,10 @@ public class ConnectionPool {
reconfigurationExecutor);
}
+ public synchronized Optional getOptional(final long id) {
+ return Iterables.tryFind(this.connections, c -> id == c.getAccount().id);
+ }
+
public synchronized ListenableFuture get(final long id) {
final var configured = Iterables.tryFind(this.connections, c -> id == c.getAccount().id);
if (configured.isPresent()) {
diff --git a/app/src/main/java/im/conversations/android/xmpp/manager/JingleConnectionManager.java b/app/src/main/java/im/conversations/android/xmpp/manager/JingleConnectionManager.java
index 4ec440d86..ad46a19a9 100644
--- a/app/src/main/java/im/conversations/android/xmpp/manager/JingleConnectionManager.java
+++ b/app/src/main/java/im/conversations/android/xmpp/manager/JingleConnectionManager.java
@@ -26,6 +26,7 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Reason;
import eu.siacs.conversations.xmpp.jingle.stanzas.RtpDescription;
import im.conversations.android.IDs;
import im.conversations.android.database.model.Account;
+import im.conversations.android.notification.OngoingCall;
import im.conversations.android.notification.RtpSessionNotification;
import im.conversations.android.xml.Element;
import im.conversations.android.xml.Namespace;
@@ -522,6 +523,18 @@ public class JingleConnectionManager extends AbstractManager {
return Optional.absent();
}
+ public OngoingCall getOngoingCall(final String sessionId) {
+ for (final Map.Entry entry :
+ this.connections.entrySet()) {
+ if (entry.getValue() instanceof JingleRtpConnection
+ && entry.getKey().sessionId.equals(sessionId)) {
+ final var jingleRtpConnection = (JingleRtpConnection) entry.getValue();
+ return jingleRtpConnection.getOngoingCall();
+ }
+ }
+ return null;
+ }
+
void finishConnection(final AbstractJingleConnection connection) {
this.connections.remove(connection.getId());
}
@@ -646,13 +659,21 @@ public class JingleConnectionManager extends AbstractManager {
resendSessionProposals();
}
- public WeakReference findJingleRtpConnection(Jid with, String sessionId) {
+ public WeakReference getWeakJingleRtpConnection(
+ Jid with, String sessionId) {
+ final var jingleRtpConnection = getJingleRtpConnection(with, sessionId);
+ return jingleRtpConnection.isPresent()
+ ? new WeakReference<>(jingleRtpConnection.get())
+ : null;
+ }
+
+ public Optional getJingleRtpConnection(Jid with, String sessionId) {
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(with, sessionId);
final AbstractJingleConnection connection = connections.get(id);
if (connection instanceof JingleRtpConnection) {
- return new WeakReference<>((JingleRtpConnection) connection);
+ return Optional.of((JingleRtpConnection) connection);
}
- return null;
+ return Optional.absent();
}
private void resendSessionProposals() {
@@ -701,34 +722,6 @@ public class JingleConnectionManager extends AbstractManager {
}
}
- public void rejectRtpSession(final String sessionId) {
- for (final AbstractJingleConnection connection : this.connections.values()) {
- if (connection.getId().sessionId.equals(sessionId)) {
- if (connection instanceof JingleRtpConnection) {
- try {
- ((JingleRtpConnection) connection).rejectCall();
- return;
- } catch (final IllegalStateException e) {
- Log.w(
- Config.LOGTAG,
- "race condition on rejecting call from notification",
- e);
- }
- }
- }
- }
- }
-
- public void endRtpSession(final String sessionId) {
- for (final AbstractJingleConnection connection : this.connections.values()) {
- if (connection.getId().sessionId.equals(sessionId)) {
- if (connection instanceof JingleRtpConnection) {
- ((JingleRtpConnection) connection).endCall();
- }
- }
- }
- }
-
public void failProceed(final Jid with, final String sessionId, final String message) {
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(with, sessionId);
final AbstractJingleConnection existingJingleConnection = connections.get(id);