diff --git a/src/main/java/eu/siacs/conversations/services/NotificationService.java b/src/main/java/eu/siacs/conversations/services/NotificationService.java index bd8e0dabb..75097a4ae 100644 --- a/src/main/java/eu/siacs/conversations/services/NotificationService.java +++ b/src/main/java/eu/siacs/conversations/services/NotificationService.java @@ -76,7 +76,7 @@ public class NotificationService { private static final int NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 2; private static final int ERROR_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 6; private static final int INCOMING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 8; - private static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; + public static final int ONGOING_CALL_NOTIFICATION_ID = NOTIFICATION_ID_MULTIPLIER * 10; private final XmppConnectionService mXmppConnectionService; private final LinkedHashMap> notifications = new LinkedHashMap<>(); private final HashMap mBacklogMessageCounter = new HashMap<>(); @@ -362,10 +362,10 @@ public class NotificationService { .build()); final Notification notification = builder.build(); notification.flags = notification.flags | Notification.FLAG_INSISTENT; - notify(INCOMING_CALL_NOTIFICATION_ID, builder.build()); + notify(INCOMING_CALL_NOTIFICATION_ID, notification); } - public void showOngoingCallNotification(final AbstractJingleConnection.Id id) { + public Notification getOngoingCallNotification(final AbstractJingleConnection.Id id) { final NotificationCompat.Builder builder = new NotificationCompat.Builder(mXmppConnectionService, "ongoing_calls"); builder.setSmallIcon(R.drawable.ic_call_white_24dp); builder.setContentTitle(mXmppConnectionService.getString(R.string.ongoing_call)); @@ -380,9 +380,7 @@ public class NotificationService { mXmppConnectionService.getString(R.string.hang_up), createCallAction(id.sessionId, XmppConnectionService.ACTION_END_CALL, 104)) .build()); - final Notification notification = builder.build(); - notification.flags = notification.flags | Notification.FLAG_INSISTENT; - notify(ONGOING_CALL_NOTIFICATION_ID, builder.build()); + return builder.build(); } private PendingIntent createPendingRtpSession(final AbstractJingleConnection.Id id, final String action, final int requestCode) { @@ -1129,7 +1127,7 @@ public class NotificationService { } } - private void cancel(int id) { + public void cancel(int id) { final NotificationManagerCompat notificationManager = NotificationManagerCompat.from(mXmppConnectionService); try { notificationManager.cancel(id); diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index ed2e5ba5a..2ad2c49f3 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -71,6 +71,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -142,6 +143,7 @@ import eu.siacs.conversations.xmpp.Patches; import eu.siacs.conversations.xmpp.XmppConnection; import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.forms.Data; +import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.OnJinglePacketReceived; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; @@ -209,6 +211,7 @@ public class XmppConnectionService extends Service { private AtomicBoolean mInitialAddressbookSyncCompleted = new AtomicBoolean(false); private AtomicBoolean mForceForegroundService = new AtomicBoolean(false); private AtomicBoolean mForceDuringOnCreate = new AtomicBoolean(false); + private AtomicReference ongoingCall = new AtomicReference<>(); private OnMessagePacketReceived mMessageParser = new MessageParser(this); private OnPresencePacketReceived mPresenceParser = new PresenceParser(this); private IqParser mIqParser = new IqParser(this); @@ -1227,11 +1230,31 @@ public class XmppConnectionService extends Service { toggleForegroundService(false); } + public void setOngoingCall(AbstractJingleConnection.Id id) { + ongoingCall.set(id); + toggleForegroundService(false); + } + + public void removeOngoingCall(AbstractJingleConnection.Id id) { + if (ongoingCall.compareAndSet(id, null)) { + toggleForegroundService(false); + } + } + private void toggleForegroundService(boolean force) { final boolean status; - if (force || mForceDuringOnCreate.get() || mForceForegroundService.get() || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { - final Notification notification = this.mNotificationService.createForegroundNotification(); - startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, notification); + final AbstractJingleConnection.Id ongoing = ongoingCall.get(); + if (force || mForceDuringOnCreate.get() || mForceForegroundService.get() || ongoing != null || (Compatibility.keepForegroundService(this) && hasEnabledAccounts())) { + final Notification notification; + if (ongoing != null) { + notification = this.mNotificationService.getOngoingCallNotification(ongoing); + startForeground(NotificationService.ONGOING_CALL_NOTIFICATION_ID, notification); + mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID); + } else { + notification = this.mNotificationService.createForegroundNotification(); + startForeground(NotificationService.FOREGROUND_NOTIFICATION_ID, notification); + } + if (!mForceForegroundService.get()) { mNotificationService.notify(NotificationService.FOREGROUND_NOTIFICATION_ID, notification); } @@ -1241,7 +1264,10 @@ public class XmppConnectionService extends Service { status = false; } if (!mForceForegroundService.get()) { - mNotificationService.dismissForcedForegroundNotification(); //if the channel was changed the previous call might fail + mNotificationService.cancel(NotificationService.FOREGROUND_NOTIFICATION_ID); + } + if (ongoing == null) { + mNotificationService.cancel(NotificationService.ONGOING_CALL_NOTIFICATION_ID); } Log.d(Config.LOGTAG, "ForegroundService: " + (status ? "on" : "off")); } @@ -1253,7 +1279,7 @@ public class XmppConnectionService extends Service { @Override public void onTaskRemoved(final Intent rootIntent) { super.onTaskRemoved(rootIntent); - if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get()) { + if ((Compatibility.keepForegroundService(this) && hasEnabledAccounts()) || mForceForegroundService.get() || ongoingCall.get() != null) { Log.d(Config.LOGTAG, "ignoring onTaskRemoved because foreground service is activated"); } else { this.logoutAndSave(false); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index e184fb8c8..83416f7cb 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -772,9 +772,9 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web private void updateOngoingCallNotification() { if (STATES_SHOWING_ONGOING_CALL.contains(this.state)) { - xmppConnectionService.getNotificationService().showOngoingCallNotification(id); + xmppConnectionService.setOngoingCall(id); } else { - xmppConnectionService.getNotificationService().cancelOngoingCallNotification(); + xmppConnectionService.removeOngoingCall(id); } }