mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 12:38:33 +00:00
Fix dangling call notification and remove active call manager flag.
This commit is contained in:
@@ -1099,12 +1099,6 @@
|
|||||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<service
|
|
||||||
android:enabled="true"
|
|
||||||
android:name=".service.webrtc.WebRtcCallService"
|
|
||||||
android:foregroundServiceType="camera|microphone"
|
|
||||||
android:exported="false"/>
|
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.signal.core.util.tracing.Tracer;
|
|||||||
import org.signal.glide.SignalGlideCodecs;
|
import org.signal.glide.SignalGlideCodecs;
|
||||||
import org.signal.libsignal.protocol.logging.SignalProtocolLoggerProvider;
|
import org.signal.libsignal.protocol.logging.SignalProtocolLoggerProvider;
|
||||||
import org.signal.ringrtc.CallManager;
|
import org.signal.ringrtc.CallManager;
|
||||||
|
import org.thoughtcrime.securesms.apkupdate.ApkUpdateRefreshListener;
|
||||||
import org.thoughtcrime.securesms.avatar.AvatarPickerStorage;
|
import org.thoughtcrime.securesms.avatar.AvatarPickerStorage;
|
||||||
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
import org.thoughtcrime.securesms.crypto.AttachmentSecretProvider;
|
||||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
||||||
@@ -89,7 +90,7 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
|
|||||||
import org.thoughtcrime.securesms.service.LocalBackupListener;
|
import org.thoughtcrime.securesms.service.LocalBackupListener;
|
||||||
import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
|
import org.thoughtcrime.securesms.service.RotateSenderCertificateListener;
|
||||||
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener;
|
||||||
import org.thoughtcrime.securesms.apkupdate.ApkUpdateRefreshListener;
|
import org.thoughtcrime.securesms.service.webrtc.ActiveCallManager;
|
||||||
import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil;
|
import org.thoughtcrime.securesms.service.webrtc.AndroidTelecomUtil;
|
||||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||||
import org.thoughtcrime.securesms.util.AppForegroundObserver;
|
import org.thoughtcrime.securesms.util.AppForegroundObserver;
|
||||||
@@ -218,6 +219,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
|
|||||||
.addPostRender(AccountConsistencyWorkerJob::enqueueIfNecessary)
|
.addPostRender(AccountConsistencyWorkerJob::enqueueIfNecessary)
|
||||||
.addPostRender(GroupRingCleanupJob::enqueue)
|
.addPostRender(GroupRingCleanupJob::enqueue)
|
||||||
.addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary)
|
.addPostRender(LinkedDeviceInactiveCheckJob::enqueueIfNecessary)
|
||||||
|
.addPostRender(() -> ActiveCallManager.clearNotifications(this))
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");
|
Log.d(TAG, "onCreate() took " + (System.currentTimeMillis() - startTime) + " ms");
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
package org.thoughtcrime.securesms.service.webrtc
|
package org.thoughtcrime.securesms.service.webrtc
|
||||||
|
|
||||||
import android.app.Notification
|
import android.app.Notification
|
||||||
|
import android.app.PendingIntent
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
@@ -24,6 +25,7 @@ import io.reactivex.rxjava3.core.Single
|
|||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import org.signal.core.util.PendingIntentFlags
|
||||||
import org.signal.core.util.ThreadUtil
|
import org.signal.core.util.ThreadUtil
|
||||||
import org.signal.core.util.logging.Log
|
import org.signal.core.util.logging.Log
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||||
@@ -38,12 +40,13 @@ import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCommand
|
|||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager
|
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager
|
||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.Companion.create
|
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager.Companion.create
|
||||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager
|
import org.thoughtcrime.securesms.webrtc.locks.LockManager
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import kotlin.concurrent.withLock
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry point for [SignalCallManager] and friends to interact with the Android system as
|
* Entry point for [SignalCallManager] and friends to interact with the Android system.
|
||||||
* previously done via [WebRtcCallService].
|
|
||||||
*
|
*
|
||||||
* This tries to limit the use of a foreground service until a call has been fully established
|
* This tries to limit the use of a foreground service until a call has been fully established
|
||||||
* and the user has likely foregrounded us by accepting a call.
|
* and the user has likely foregrounded us by accepting a call.
|
||||||
@@ -54,6 +57,79 @@ class ActiveCallManager(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = Log.tag(ActiveCallManager::class.java)
|
private val TAG = Log.tag(ActiveCallManager::class.java)
|
||||||
|
|
||||||
|
private var activeCallManager: ActiveCallManager? = null
|
||||||
|
private val activeCallManagerLock = ReentrantLock()
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun clearNotifications(context: Context) {
|
||||||
|
NotificationManagerCompat.from(context).apply {
|
||||||
|
cancel(CallNotificationBuilder.WEBRTC_NOTIFICATION)
|
||||||
|
cancel(CallNotificationBuilder.WEBRTC_NOTIFICATION_RINGING)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun update(context: Context, type: Int, recipientId: RecipientId, isVideoCall: Boolean) {
|
||||||
|
activeCallManagerLock.withLock {
|
||||||
|
if (activeCallManager == null) {
|
||||||
|
activeCallManager = ActiveCallManager(context)
|
||||||
|
}
|
||||||
|
activeCallManager!!.update(type, recipientId, isVideoCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun denyCall() {
|
||||||
|
ApplicationDependencies.getSignalCallManager().denyCall()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun hangup() {
|
||||||
|
ApplicationDependencies.getSignalCallManager().localHangup()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun stop() {
|
||||||
|
activeCallManagerLock.withLock {
|
||||||
|
activeCallManager?.shutdown()
|
||||||
|
activeCallManager = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun denyCallIntent(context: Context): PendingIntent {
|
||||||
|
val intent = Intent(context, ActiveCallServiceReceiver::class.java)
|
||||||
|
intent.setAction(ActiveCallServiceReceiver.ACTION_DENY)
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun hangupIntent(context: Context): PendingIntent {
|
||||||
|
val intent = Intent(context, ActiveCallServiceReceiver::class.java)
|
||||||
|
intent.setAction(ActiveCallServiceReceiver.ACTION_HANGUP)
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun sendAudioManagerCommand(context: Context, command: AudioManagerCommand) {
|
||||||
|
activeCallManagerLock.withLock {
|
||||||
|
if (activeCallManager == null) {
|
||||||
|
activeCallManager = ActiveCallManager(context)
|
||||||
|
}
|
||||||
|
activeCallManager!!.sendAudioCommand(command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun changePowerButtonReceiver(context: Context, register: Boolean) {
|
||||||
|
activeCallManagerLock.withLock {
|
||||||
|
if (activeCallManager == null) {
|
||||||
|
activeCallManager = ActiveCallManager(context)
|
||||||
|
}
|
||||||
|
activeCallManager!!.changePowerButton(register)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callManager = ApplicationDependencies.getSignalCallManager()
|
private val callManager = ApplicationDependencies.getSignalCallManager()
|
||||||
@@ -72,8 +148,8 @@ class ActiveCallManager(
|
|||||||
webSocketKeepAliveTask.start()
|
webSocketKeepAliveTask.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stop() {
|
fun shutdown() {
|
||||||
Log.v(TAG, "stop")
|
Log.v(TAG, "shutdown")
|
||||||
|
|
||||||
uncaughtExceptionHandlerManager?.unregister()
|
uncaughtExceptionHandlerManager?.unregister()
|
||||||
uncaughtExceptionHandlerManager = null
|
uncaughtExceptionHandlerManager = null
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class AndroidCallConnection(
|
|||||||
|
|
||||||
override fun onShowIncomingCallUi() {
|
override fun onShowIncomingCallUi() {
|
||||||
Log.i(TAG, "onShowIncomingCallUi()")
|
Log.i(TAG, "onShowIncomingCallUi()")
|
||||||
WebRtcCallService.update(context, CallNotificationBuilder.TYPE_INCOMING_CONNECTING, recipientId, isVideoCall)
|
ActiveCallManager.update(context, CallNotificationBuilder.TYPE_INCOMING_CONNECTING, recipientId, isVideoCall)
|
||||||
setRinging()
|
setRinging()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,17 +74,17 @@ class AndroidCallConnection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSilence() {
|
override fun onSilence() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, AudioManagerCommand.SilenceIncomingRinger())
|
ActiveCallManager.sendAudioManagerCommand(context, AudioManagerCommand.SilenceIncomingRinger())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReject() {
|
override fun onReject() {
|
||||||
Log.i(TAG, "onReject()")
|
Log.i(TAG, "onReject()")
|
||||||
WebRtcCallService.denyCall(context)
|
ActiveCallManager.denyCall()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDisconnect() {
|
override fun onDisconnect() {
|
||||||
Log.i(TAG, "onDisconnect()")
|
Log.i(TAG, "onDisconnect()")
|
||||||
WebRtcCallService.hangup(context)
|
ActiveCallManager.hangup()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,487 +0,0 @@
|
|||||||
package org.thoughtcrime.securesms.service.webrtc;
|
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.pm.ServiceInfo;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.telephony.PhoneStateListener;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
|
|
||||||
import androidx.annotation.MainThread;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.signal.core.util.PendingIntentFlags;
|
|
||||||
import org.signal.core.util.ThreadUtil;
|
|
||||||
import org.signal.core.util.concurrent.SignalExecutors;
|
|
||||||
import org.signal.core.util.logging.Log;
|
|
||||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
|
||||||
import org.thoughtcrime.securesms.jobs.ForegroundServiceUtil;
|
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
|
||||||
import org.thoughtcrime.securesms.util.FeatureFlags;
|
|
||||||
import org.thoughtcrime.securesms.util.TelephonyUtil;
|
|
||||||
import org.thoughtcrime.securesms.webrtc.CallNotificationBuilder;
|
|
||||||
import org.thoughtcrime.securesms.webrtc.UncaughtExceptionHandlerManager;
|
|
||||||
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCommand;
|
|
||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
|
||||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.core.Single;
|
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a foreground service for {@link SignalCallManager} to leverage to run in the background when necessary. Also
|
|
||||||
* provides devices listeners needed for during a call (i.e., bluetooth, power button).
|
|
||||||
*/
|
|
||||||
public final class WebRtcCallService extends Service implements SignalAudioManager.EventListener {
|
|
||||||
|
|
||||||
private static final String TAG = Log.tag(WebRtcCallService.class);
|
|
||||||
private static final String WEBSOCKET_KEEP_ALIVE_TOKEN = WebRtcCallService.class.getName();
|
|
||||||
|
|
||||||
private static final String ACTION_UPDATE = "UPDATE";
|
|
||||||
private static final String ACTION_STOP = "STOP";
|
|
||||||
private static final String ACTION_DENY_CALL = "DENY_CALL";
|
|
||||||
private static final String ACTION_LOCAL_HANGUP = "LOCAL_HANGUP";
|
|
||||||
private static final String ACTION_CHANGE_POWER_BUTTON = "CHANGE_POWER_BUTTON";
|
|
||||||
private static final String ACTION_SEND_AUDIO_COMMAND = "SEND_AUDIO_COMMAND";
|
|
||||||
|
|
||||||
private static final String EXTRA_UPDATE_TYPE = "UPDATE_TYPE";
|
|
||||||
private static final String EXTRA_RECIPIENT_ID = "RECIPIENT_ID";
|
|
||||||
private static final String EXTRA_ENABLED = "ENABLED";
|
|
||||||
private static final String EXTRA_AUDIO_COMMAND = "AUDIO_COMMAND";
|
|
||||||
private static final String EXTRA_IS_VIDEO_CALL = "IS_VIDEO_CALL";
|
|
||||||
|
|
||||||
private static final int INVALID_NOTIFICATION_ID = -1;
|
|
||||||
private static final long REQUEST_WEBSOCKET_STAY_OPEN_DELAY = TimeUnit.MINUTES.toMillis(1);
|
|
||||||
private static final long FOREGROUND_SERVICE_TIMEOUT = TimeUnit.SECONDS.toMillis(10);
|
|
||||||
|
|
||||||
private final WebSocketKeepAliveTask webSocketKeepAliveTask = new WebSocketKeepAliveTask();
|
|
||||||
private final Executor singleThreadExecutor = SignalExecutors.newCachedSingleThreadExecutor("signal-webrtc-in-call", ThreadUtil.PRIORITY_IMPORTANT_BACKGROUND_THREAD);
|
|
||||||
|
|
||||||
private SignalCallManager callManager;
|
|
||||||
|
|
||||||
private NetworkReceiver networkReceiver;
|
|
||||||
private PowerButtonReceiver powerButtonReceiver;
|
|
||||||
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
|
||||||
private PhoneStateListener hangUpRtcOnDeviceCallAnswered;
|
|
||||||
private SignalAudioManager signalAudioManager;
|
|
||||||
private int lastNotificationId;
|
|
||||||
private Notification lastNotification;
|
|
||||||
private long lastNotificationRequestTime;
|
|
||||||
private Disposable lastNotificationDisposable = Disposable.disposed();
|
|
||||||
private boolean stopping = false;
|
|
||||||
|
|
||||||
private static ActiveCallManager activeCallManager = null;
|
|
||||||
|
|
||||||
public synchronized static void update(@NonNull Context context, int type, @NonNull RecipientId recipientId, boolean isVideoCall) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
if (activeCallManager == null) {
|
|
||||||
activeCallManager = new ActiveCallManager(context);
|
|
||||||
}
|
|
||||||
activeCallManager.update(type, recipientId, isVideoCall);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
|
||||||
intent.setAction(ACTION_UPDATE)
|
|
||||||
.putExtra(EXTRA_UPDATE_TYPE, type)
|
|
||||||
.putExtra(EXTRA_RECIPIENT_ID, recipientId)
|
|
||||||
.putExtra(EXTRA_IS_VIDEO_CALL, isVideoCall);
|
|
||||||
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, intent, FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void denyCall(@NonNull Context context) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
ApplicationDependencies.getSignalCallManager().denyCall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, new Intent(context, WebRtcCallService.class).setAction(ACTION_DENY_CALL), FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void hangup(@NonNull Context context) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
ApplicationDependencies.getSignalCallManager().localHangup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, new Intent(context, WebRtcCallService.class).setAction(ACTION_LOCAL_HANGUP), FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized static void stop(@NonNull Context context) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
if (activeCallManager != null) {
|
|
||||||
activeCallManager.stop();
|
|
||||||
activeCallManager = null;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
|
||||||
intent.setAction(ACTION_STOP);
|
|
||||||
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, intent, FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized static @NonNull PendingIntent denyCallIntent(@NonNull Context context) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
Intent intent = new Intent(context, ActiveCallManager.ActiveCallServiceReceiver.class);
|
|
||||||
intent.setAction(ActiveCallManager.ActiveCallServiceReceiver.ACTION_DENY);
|
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable());
|
|
||||||
}
|
|
||||||
|
|
||||||
return getServicePendingIntent(context, new Intent(context, WebRtcCallService.class).setAction(ACTION_DENY_CALL));
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized static @NonNull PendingIntent hangupIntent(@NonNull Context context) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
Intent intent = new Intent(context, ActiveCallManager.ActiveCallServiceReceiver.class);
|
|
||||||
intent.setAction(ActiveCallManager.ActiveCallServiceReceiver.ACTION_HANGUP);
|
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntentFlags.mutable());
|
|
||||||
}
|
|
||||||
|
|
||||||
return getServicePendingIntent(context, new Intent(context, WebRtcCallService.class).setAction(ACTION_LOCAL_HANGUP));
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized static void sendAudioManagerCommand(@NonNull Context context, @NonNull AudioManagerCommand command) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
if (activeCallManager == null) {
|
|
||||||
activeCallManager = new ActiveCallManager(context);
|
|
||||||
}
|
|
||||||
activeCallManager.sendAudioCommand(command);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
|
||||||
intent.setAction(ACTION_SEND_AUDIO_COMMAND)
|
|
||||||
.putExtra(EXTRA_AUDIO_COMMAND, command);
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, intent, FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized static void changePowerButtonReceiver(@NonNull Context context, boolean register) {
|
|
||||||
if (FeatureFlags.useActiveCallManager()) {
|
|
||||||
if (activeCallManager == null) {
|
|
||||||
activeCallManager = new ActiveCallManager(context);
|
|
||||||
}
|
|
||||||
activeCallManager.changePowerButton(register);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent intent = new Intent(context, WebRtcCallService.class);
|
|
||||||
intent.setAction(ACTION_CHANGE_POWER_BUTTON)
|
|
||||||
.putExtra(EXTRA_ENABLED, register);
|
|
||||||
|
|
||||||
ForegroundServiceUtil.tryToStartWhenCapable(context, intent, FOREGROUND_SERVICE_TIMEOUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
Log.v(TAG, "onCreate");
|
|
||||||
super.onCreate();
|
|
||||||
this.callManager = ApplicationDependencies.getSignalCallManager();
|
|
||||||
this.hangUpRtcOnDeviceCallAnswered = new HangUpRtcOnPstnCallAnsweredListener();
|
|
||||||
this.lastNotificationId = INVALID_NOTIFICATION_ID;
|
|
||||||
|
|
||||||
registerUncaughtExceptionHandler();
|
|
||||||
registerNetworkReceiver();
|
|
||||||
|
|
||||||
if (!AndroidTelecomUtil.getTelecomSupported()) {
|
|
||||||
try {
|
|
||||||
TelephonyUtil.getManager(this).listen(hangUpRtcOnDeviceCallAnswered, PhoneStateListener.LISTEN_CALL_STATE);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
Log.w(TAG, "Failed to listen to PSTN call answers!", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
Log.v(TAG, "onDestroy");
|
|
||||||
super.onDestroy();
|
|
||||||
|
|
||||||
if (uncaughtExceptionHandlerManager != null) {
|
|
||||||
uncaughtExceptionHandlerManager.unregister();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signalAudioManager != null) {
|
|
||||||
signalAudioManager.shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
unregisterNetworkReceiver();
|
|
||||||
unregisterPowerButtonReceiver();
|
|
||||||
|
|
||||||
if (!AndroidTelecomUtil.getTelecomSupported()) {
|
|
||||||
TelephonyUtil.getManager(this).listen(hangUpRtcOnDeviceCallAnswered, PhoneStateListener.LISTEN_NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
webSocketKeepAliveTask.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
||||||
if (intent == null || intent.getAction() == null) {
|
|
||||||
Log.w(TAG, "Service running with null intent/action likely from system restart, stopping");
|
|
||||||
stop();
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.i(TAG, "action: " + intent.getAction());
|
|
||||||
webSocketKeepAliveTask.start();
|
|
||||||
|
|
||||||
switch (intent.getAction()) {
|
|
||||||
case ACTION_UPDATE:
|
|
||||||
setCallInProgressNotification(intent.getIntExtra(EXTRA_UPDATE_TYPE, 0),
|
|
||||||
Objects.requireNonNull(intent.getParcelableExtra(EXTRA_RECIPIENT_ID)),
|
|
||||||
intent.getBooleanExtra(EXTRA_IS_VIDEO_CALL, false));
|
|
||||||
return START_STICKY;
|
|
||||||
case ACTION_SEND_AUDIO_COMMAND:
|
|
||||||
setCallNotification();
|
|
||||||
if (signalAudioManager == null) {
|
|
||||||
signalAudioManager = SignalAudioManager.create(this, this);
|
|
||||||
}
|
|
||||||
AudioManagerCommand audioCommand = Objects.requireNonNull(intent.getParcelableExtra(EXTRA_AUDIO_COMMAND));
|
|
||||||
Log.i(TAG, "Sending audio command [" + audioCommand.getClass().getSimpleName() + "] to " + signalAudioManager.getClass().getSimpleName());
|
|
||||||
signalAudioManager.handleCommand(audioCommand);
|
|
||||||
return START_STICKY;
|
|
||||||
case ACTION_CHANGE_POWER_BUTTON:
|
|
||||||
setCallNotification();
|
|
||||||
if (intent.getBooleanExtra(EXTRA_ENABLED, false)) {
|
|
||||||
registerPowerButtonReceiver();
|
|
||||||
} else {
|
|
||||||
unregisterPowerButtonReceiver();
|
|
||||||
}
|
|
||||||
return START_STICKY;
|
|
||||||
case ACTION_STOP:
|
|
||||||
setCallNotification(true);
|
|
||||||
stop();
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
case ACTION_DENY_CALL:
|
|
||||||
setCallNotification();
|
|
||||||
callManager.denyCall();
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
case ACTION_LOCAL_HANGUP:
|
|
||||||
setCallNotification();
|
|
||||||
callManager.localHangup();
|
|
||||||
return START_NOT_STICKY;
|
|
||||||
default:
|
|
||||||
throw new AssertionError("Unknown action: " + intent.getAction());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCallNotification() {
|
|
||||||
setCallNotification(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCallNotification(boolean stopping) {
|
|
||||||
if (!stopping && lastNotificationId != INVALID_NOTIFICATION_ID) {
|
|
||||||
startForegroundCompat(lastNotificationId, lastNotification);
|
|
||||||
} else {
|
|
||||||
if (!stopping) {
|
|
||||||
Log.i(TAG, "Service was started without calling UPDATE first, using temporary notification.");
|
|
||||||
}
|
|
||||||
startForegroundCompat(CallNotificationBuilder.getStartingStoppingNotificationId(), stopping ? CallNotificationBuilder.getStoppingNotification(this)
|
|
||||||
: CallNotificationBuilder.getStartingNotification(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCallInProgressNotification(int type, @NonNull RecipientId id, boolean isVideoCall) {
|
|
||||||
lastNotificationDisposable.dispose();
|
|
||||||
|
|
||||||
boolean requiresAsyncNotificationLoad = Build.VERSION.SDK_INT <= 29;
|
|
||||||
|
|
||||||
lastNotificationId = CallNotificationBuilder.getNotificationId(type);
|
|
||||||
lastNotification = CallNotificationBuilder.getCallInProgressNotification(this, type, Recipient.resolved(id), isVideoCall, requiresAsyncNotificationLoad);
|
|
||||||
|
|
||||||
startForegroundCompat(lastNotificationId, lastNotification);
|
|
||||||
|
|
||||||
if (requiresAsyncNotificationLoad) {
|
|
||||||
final long requestTime = System.currentTimeMillis();
|
|
||||||
lastNotificationRequestTime = requestTime;
|
|
||||||
lastNotificationDisposable = Single
|
|
||||||
.fromCallable(() -> CallNotificationBuilder.getCallInProgressNotification(this, type, Recipient.resolved(id), isVideoCall, false))
|
|
||||||
.subscribeOn(Schedulers.from(singleThreadExecutor))
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.filter(unused -> requestTime == lastNotificationRequestTime && !stopping)
|
|
||||||
.subscribe(notification -> {
|
|
||||||
lastNotification = notification;
|
|
||||||
startForegroundCompat(lastNotificationId, lastNotification);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void startForegroundCompat(int notificationId, Notification notification) {
|
|
||||||
if (stopping) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 30) {
|
|
||||||
startForeground(notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
|
||||||
} else {
|
|
||||||
startForeground(notificationId, notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void stop() {
|
|
||||||
stopping = true;
|
|
||||||
stopForeground(true);
|
|
||||||
stopSelf();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerUncaughtExceptionHandler() {
|
|
||||||
uncaughtExceptionHandlerManager = new UncaughtExceptionHandlerManager();
|
|
||||||
uncaughtExceptionHandlerManager.registerHandler(new ProximityLockRelease(callManager.getLockManager()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerNetworkReceiver() {
|
|
||||||
if (networkReceiver == null) {
|
|
||||||
networkReceiver = new NetworkReceiver();
|
|
||||||
|
|
||||||
registerReceiver(networkReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unregisterNetworkReceiver() {
|
|
||||||
if (networkReceiver != null) {
|
|
||||||
unregisterReceiver(networkReceiver);
|
|
||||||
|
|
||||||
networkReceiver = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerPowerButtonReceiver() {
|
|
||||||
if (!AndroidTelecomUtil.getTelecomSupported() && powerButtonReceiver == null) {
|
|
||||||
powerButtonReceiver = new PowerButtonReceiver();
|
|
||||||
|
|
||||||
registerReceiver(powerButtonReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregisterPowerButtonReceiver() {
|
|
||||||
if (powerButtonReceiver != null) {
|
|
||||||
unregisterReceiver(powerButtonReceiver);
|
|
||||||
|
|
||||||
powerButtonReceiver = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable IBinder onBind(Intent intent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAudioDeviceChanged(@NonNull SignalAudioManager.AudioDevice activeDevice, @NonNull Set<SignalAudioManager.AudioDevice> availableDevices) {
|
|
||||||
callManager.onAudioDeviceChanged(activeDevice, availableDevices);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBluetoothPermissionDenied() {
|
|
||||||
callManager.onBluetoothPermissionDenied();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PendingIntent getServicePendingIntent(@NonNull Context context, @NonNull Intent intent) {
|
|
||||||
return Build.VERSION.SDK_INT >= 26 ? PendingIntent.getForegroundService(context, 0, intent, PendingIntentFlags.mutable())
|
|
||||||
: PendingIntent.getService(context, 0, intent, PendingIntentFlags.mutable());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
private class HangUpRtcOnPstnCallAnsweredListener extends PhoneStateListener {
|
|
||||||
@Override
|
|
||||||
public void onCallStateChanged(int state, @NonNull String phoneNumber) {
|
|
||||||
super.onCallStateChanged(state, phoneNumber);
|
|
||||||
if (state == TelephonyManager.CALL_STATE_OFFHOOK) {
|
|
||||||
hangup();
|
|
||||||
Log.i(TAG, "Device phone call ended Signal call.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hangup() {
|
|
||||||
callManager.localHangup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Periodically request the web socket stay open if we are doing anything call related.
|
|
||||||
*/
|
|
||||||
private class WebSocketKeepAliveTask implements Runnable {
|
|
||||||
private boolean keepRunning = false;
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
public void start() {
|
|
||||||
if (!keepRunning) {
|
|
||||||
keepRunning = true;
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
public void stop() {
|
|
||||||
keepRunning = false;
|
|
||||||
ThreadUtil.cancelRunnableOnMain(webSocketKeepAliveTask);
|
|
||||||
ApplicationDependencies.getIncomingMessageObserver().removeKeepAliveToken(WEBSOCKET_KEEP_ALIVE_TOKEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainThread
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (keepRunning) {
|
|
||||||
ApplicationDependencies.getIncomingMessageObserver().registerKeepAliveToken(WEBSOCKET_KEEP_ALIVE_TOKEN);
|
|
||||||
ThreadUtil.runOnMainDelayed(this, REQUEST_WEBSOCKET_STAY_OPEN_DELAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class NetworkReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
|
||||||
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
|
|
||||||
|
|
||||||
ApplicationDependencies.getSignalCallManager().networkChange(activeNetworkInfo != null && activeNetworkInfo.isConnected());
|
|
||||||
ApplicationDependencies.getSignalCallManager().dataModeUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class PowerButtonReceiver extends BroadcastReceiver {
|
|
||||||
@Override
|
|
||||||
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
|
|
||||||
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
|
|
||||||
ApplicationDependencies.getSignalCallManager().screenOff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ProximityLockRelease implements Thread.UncaughtExceptionHandler {
|
|
||||||
private final LockManager lockManager;
|
|
||||||
|
|
||||||
private ProximityLockRelease(@NonNull LockManager lockManager) {
|
|
||||||
this.lockManager = lockManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
|
|
||||||
Log.i(TAG, "Uncaught exception - releasing proximity lock", throwable);
|
|
||||||
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCommand;
|
|||||||
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager;
|
||||||
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
import org.thoughtcrime.securesms.webrtc.locks.LockManager;
|
||||||
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMessage;
|
||||||
import org.whispersystems.signalservice.internal.push.SyncMessage;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -96,11 +95,11 @@ public class WebRtcInteractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setCallInProgressNotification(int type, @NonNull RemotePeer remotePeer, boolean isVideoCall) {
|
void setCallInProgressNotification(int type, @NonNull RemotePeer remotePeer, boolean isVideoCall) {
|
||||||
WebRtcCallService.update(context, type, remotePeer.getRecipient().getId(), isVideoCall);
|
ActiveCallManager.update(context, type, remotePeer.getRecipient().getId(), isVideoCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallInProgressNotification(int type, @NonNull Recipient recipient, boolean isVideoCall) {
|
void setCallInProgressNotification(int type, @NonNull Recipient recipient, boolean isVideoCall) {
|
||||||
WebRtcCallService.update(context, type, recipient.getId(), isVideoCall);
|
ActiveCallManager.update(context, type, recipient.getId(), isVideoCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
void retrieveTurnServers(@NonNull RemotePeer remotePeer) {
|
void retrieveTurnServers(@NonNull RemotePeer remotePeer) {
|
||||||
@@ -108,7 +107,7 @@ public class WebRtcInteractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void stopForegroundService() {
|
void stopForegroundService() {
|
||||||
WebRtcCallService.stop(context);
|
ActiveCallManager.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) {
|
void insertMissedCall(@NonNull RemotePeer remotePeer, long timestamp, boolean isVideoOffer) {
|
||||||
@@ -128,51 +127,51 @@ public class WebRtcInteractor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void registerPowerButtonReceiver() {
|
void registerPowerButtonReceiver() {
|
||||||
WebRtcCallService.changePowerButtonReceiver(context, true);
|
ActiveCallManager.changePowerButtonReceiver(context, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterPowerButtonReceiver() {
|
void unregisterPowerButtonReceiver() {
|
||||||
WebRtcCallService.changePowerButtonReceiver(context, false);
|
ActiveCallManager.changePowerButtonReceiver(context, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void silenceIncomingRinger() {
|
void silenceIncomingRinger() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.SilenceIncomingRinger());
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.SilenceIncomingRinger());
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeAudioForCall() {
|
void initializeAudioForCall() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.Initialize());
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.Initialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
void startIncomingRinger(@Nullable Uri ringtoneUri, boolean vibrate) {
|
void startIncomingRinger(@Nullable Uri ringtoneUri, boolean vibrate) {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.StartIncomingRinger(ringtoneUri, vibrate));
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.StartIncomingRinger(ringtoneUri, vibrate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void startOutgoingRinger() {
|
void startOutgoingRinger() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.StartOutgoingRinger());
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.StartOutgoingRinger());
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopAudio(boolean playDisconnect) {
|
void stopAudio(boolean playDisconnect) {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.Stop(playDisconnect));
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.Stop(playDisconnect));
|
||||||
}
|
}
|
||||||
|
|
||||||
void startAudioCommunication() {
|
void startAudioCommunication() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.Start());
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.Start());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUserAudioDevice(@Nullable RecipientId recipientId, @NonNull SignalAudioManager.ChosenAudioDeviceIdentifier userDevice) {
|
public void setUserAudioDevice(@Nullable RecipientId recipientId, @NonNull SignalAudioManager.ChosenAudioDeviceIdentifier userDevice) {
|
||||||
if (userDevice.isLegacy()) {
|
if (userDevice.isLegacy()) {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.SetUserDevice(recipientId, userDevice.getDesiredAudioDeviceLegacy().ordinal(), false));
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.SetUserDevice(recipientId, userDevice.getDesiredAudioDeviceLegacy().ordinal(), false));
|
||||||
} else {
|
} else {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.SetUserDevice(recipientId, userDevice.getDesiredAudioDevice31(), true));
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.SetUserDevice(recipientId, userDevice.getDesiredAudioDevice31(), true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDefaultAudioDevice(@NonNull RecipientId recipientId, @NonNull SignalAudioManager.AudioDevice userDevice, boolean clearUserEarpieceSelection) {
|
public void setDefaultAudioDevice(@NonNull RecipientId recipientId, @NonNull SignalAudioManager.AudioDevice userDevice, boolean clearUserEarpieceSelection) {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.SetDefaultDevice(recipientId, userDevice, clearUserEarpieceSelection));
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.SetDefaultDevice(recipientId, userDevice, clearUserEarpieceSelection));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playStateChangeUp() {
|
public void playStateChangeUp() {
|
||||||
WebRtcCallService.sendAudioManagerCommand(context, new AudioManagerCommand.PlayStateChangeUp());
|
ActiveCallManager.sendAudioManagerCommand(context, new AudioManagerCommand.PlayStateChangeUp());
|
||||||
}
|
}
|
||||||
|
|
||||||
void peekGroupCallForRingingCheck(@NonNull GroupCallRingCheckInfo groupCallRingCheckInfo) {
|
void peekGroupCallForRingingCheck(@NonNull GroupCallRingCheckInfo groupCallRingCheckInfo) {
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ public final class FeatureFlags {
|
|||||||
private static final String CALLING_REACTIONS = "android.calling.reactions";
|
private static final String CALLING_REACTIONS = "android.calling.reactions";
|
||||||
private static final String NOTIFICATION_THUMBNAIL_BLOCKLIST = "android.notificationThumbnailProductBlocklist";
|
private static final String NOTIFICATION_THUMBNAIL_BLOCKLIST = "android.notificationThumbnailProductBlocklist";
|
||||||
private static final String CALLING_RAISE_HAND = "android.calling.raiseHand";
|
private static final String CALLING_RAISE_HAND = "android.calling.raiseHand";
|
||||||
private static final String USE_ACTIVE_CALL_MANAGER = "android.calling.useActiveCallManager.4";
|
|
||||||
private static final String GIF_SEARCH = "global.gifSearch";
|
private static final String GIF_SEARCH = "global.gifSearch";
|
||||||
private static final String AUDIO_REMUXING = "android.media.audioRemux.1";
|
private static final String AUDIO_REMUXING = "android.media.audioRemux.1";
|
||||||
private static final String VIDEO_RECORD_1X_ZOOM = "android.media.videoCaptureDefaultZoom";
|
private static final String VIDEO_RECORD_1X_ZOOM = "android.media.videoCaptureDefaultZoom";
|
||||||
@@ -197,7 +196,6 @@ public final class FeatureFlags {
|
|||||||
CALLING_REACTIONS,
|
CALLING_REACTIONS,
|
||||||
NOTIFICATION_THUMBNAIL_BLOCKLIST,
|
NOTIFICATION_THUMBNAIL_BLOCKLIST,
|
||||||
CALLING_RAISE_HAND,
|
CALLING_RAISE_HAND,
|
||||||
USE_ACTIVE_CALL_MANAGER,
|
|
||||||
GIF_SEARCH,
|
GIF_SEARCH,
|
||||||
AUDIO_REMUXING,
|
AUDIO_REMUXING,
|
||||||
VIDEO_RECORD_1X_ZOOM,
|
VIDEO_RECORD_1X_ZOOM,
|
||||||
@@ -694,11 +692,6 @@ public final class FeatureFlags {
|
|||||||
return getString(NOTIFICATION_THUMBNAIL_BLOCKLIST, "");
|
return getString(NOTIFICATION_THUMBNAIL_BLOCKLIST, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether or not to use active call manager instead of WebRtcCallService. */
|
|
||||||
public static boolean useActiveCallManager() {
|
|
||||||
return getBoolean(USE_ACTIVE_CALL_MANAGER, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the in-app GIF search is available for use. */
|
/** Whether the in-app GIF search is available for use. */
|
||||||
public static boolean gifSearchAvailable() {
|
public static boolean gifSearchAvailable() {
|
||||||
return getBoolean(GIF_SEARCH, true);
|
return getBoolean(GIF_SEARCH, true);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import org.thoughtcrime.securesms.R;
|
|||||||
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
import org.thoughtcrime.securesms.WebRtcCallActivity;
|
||||||
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
import org.thoughtcrime.securesms.notifications.NotificationChannels;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.webrtc.WebRtcCallService;
|
import org.thoughtcrime.securesms.service.webrtc.ActiveCallManager;
|
||||||
import org.thoughtcrime.securesms.util.ConversationUtil;
|
import org.thoughtcrime.securesms.util.ConversationUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,8 +29,8 @@ import org.thoughtcrime.securesms.util.ConversationUtil;
|
|||||||
|
|
||||||
public class CallNotificationBuilder {
|
public class CallNotificationBuilder {
|
||||||
|
|
||||||
public static final int WEBRTC_NOTIFICATION = 313388;
|
public static final int WEBRTC_NOTIFICATION = 313388;
|
||||||
private static final int WEBRTC_NOTIFICATION_RINGING = 313389;
|
public static final int WEBRTC_NOTIFICATION_RINGING = 313389;
|
||||||
|
|
||||||
public static final int TYPE_INCOMING_RINGING = 1;
|
public static final int TYPE_INCOMING_RINGING = 1;
|
||||||
public static final int TYPE_OUTGOING_RINGING = 2;
|
public static final int TYPE_OUTGOING_RINGING = 2;
|
||||||
@@ -114,7 +114,7 @@ public class CallNotificationBuilder {
|
|||||||
if (deviceVersionSupportsIncomingCallStyle()) {
|
if (deviceVersionSupportsIncomingCallStyle()) {
|
||||||
builder.setStyle(NotificationCompat.CallStyle.forIncomingCall(
|
builder.setStyle(NotificationCompat.CallStyle.forIncomingCall(
|
||||||
person,
|
person,
|
||||||
WebRtcCallService.denyCallIntent(context),
|
ActiveCallManager.denyCallIntent(context),
|
||||||
getActivityPendingIntent(context, isVideoCall ? LaunchCallScreenIntentState.VIDEO : LaunchCallScreenIntentState.AUDIO)
|
getActivityPendingIntent(context, isVideoCall ? LaunchCallScreenIntentState.VIDEO : LaunchCallScreenIntentState.AUDIO)
|
||||||
).setIsVideo(isVideoCall));
|
).setIsVideo(isVideoCall));
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ public class CallNotificationBuilder {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
} else if (type == TYPE_OUTGOING_RINGING) {
|
} else if (type == TYPE_OUTGOING_RINGING) {
|
||||||
builder.setContentText(context.getString(R.string.NotificationBarManager__establishing_signal_call));
|
builder.setContentText(context.getString(R.string.NotificationBarManager__establishing_signal_call));
|
||||||
builder.addAction(getServiceNotificationAction(context, WebRtcCallService.hangupIntent(context), R.drawable.symbol_phone_down_fill_24, R.string.NotificationBarManager__cancel_call));
|
builder.addAction(getServiceNotificationAction(context, ActiveCallManager.hangupIntent(context), R.drawable.symbol_phone_down_fill_24, R.string.NotificationBarManager__cancel_call));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
} else {
|
} else {
|
||||||
builder.setContentText(getOngoingCallContentText(context, recipient, isVideoCall));
|
builder.setContentText(getOngoingCallContentText(context, recipient, isVideoCall));
|
||||||
@@ -138,7 +138,7 @@ public class CallNotificationBuilder {
|
|||||||
if (deviceVersionSupportsIncomingCallStyle()) {
|
if (deviceVersionSupportsIncomingCallStyle()) {
|
||||||
builder.setStyle(NotificationCompat.CallStyle.forOngoingCall(
|
builder.setStyle(NotificationCompat.CallStyle.forOngoingCall(
|
||||||
person,
|
person,
|
||||||
WebRtcCallService.hangupIntent(context)
|
ActiveCallManager.hangupIntent(context)
|
||||||
).setIsVideo(isVideoCall));
|
).setIsVideo(isVideoCall));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ import org.thoughtcrime.securesms.util.ParcelUtil
|
|||||||
* Commands that can be issued to [SignalAudioManager] to perform various tasks.
|
* Commands that can be issued to [SignalAudioManager] to perform various tasks.
|
||||||
*
|
*
|
||||||
* Additional context: The audio management is tied closely with the Android audio and thus benefits from being
|
* Additional context: The audio management is tied closely with the Android audio and thus benefits from being
|
||||||
* tied to the [org.thoughtcrime.securesms.service.webrtc.WebRtcCallService] lifecycle. Because of this, all
|
* tied to the [org.thoughtcrime.securesms.service.webrtc.ActiveCallManager] lifecycle. Because of this, all
|
||||||
* calls have to go through an intent to the service and this allows one entry point for that but multiple
|
* calls have to go through it and this allows one entry point for that but multiple operations.
|
||||||
* operations.
|
|
||||||
*/
|
*/
|
||||||
sealed class AudioManagerCommand : Parcelable {
|
sealed class AudioManagerCommand : Parcelable {
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user