diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/BroadcastVideoSink.java b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/BroadcastVideoSink.java index 06f5a0626..9b3bf0a0c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/BroadcastVideoSink.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/BroadcastVideoSink.java @@ -31,7 +31,7 @@ public class BroadcastVideoSink implements VideoSink { private RequestedSize currentlyRequestedMaxSize; public BroadcastVideoSink() { - this(new EglBaseWrapper(null), false, true, 0); + this(new EglBaseWrapper(), false, true, 0); } /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/EglBaseWrapper.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/EglBaseWrapper.kt index 6a78d27ca..952d92dbc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/EglBaseWrapper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/EglBaseWrapper.kt @@ -15,16 +15,21 @@ private val TAG = Log.tag(EglBaseWrapper::class.java) /** * Wrapper which allows caller to perform synchronized actions on an EglBase object. - */ -class EglBaseWrapper(val eglBase: EglBase?) { + * Must use [acquireEglBase] to get a valid instance to an [EglBaseWrapper] for use in calling. + * The instance returned may be shared across calls. Call [releaseEglBase] when it is no longer + * required. When the wrapper has no others are using it, it will be properly released (a la reference counting). +*/ +class EglBaseWrapper private constructor(val eglBase: EglBase?) { private val lock: Lock = ReentrantLock() - fun require(): EglBase = requireNotNull(eglBase) - @Volatile private var isReleased: Boolean = false + constructor() : this(null) + + fun require(): EglBase = requireNotNull(eglBase) + fun performWithValidEglBase(consumer: Consumer) { if (isReleased) { Log.d(TAG, "Tried to use a released EglBase", Exception()) @@ -53,7 +58,7 @@ class EglBaseWrapper(val eglBase: EglBase?) { } } - fun releaseEglBase() { + private fun releaseEglBase() { if (isReleased || eglBase == null) { return } @@ -67,4 +72,48 @@ class EglBaseWrapper(val eglBase: EglBase?) { eglBase.release() } } + + companion object { + const val OUTGOING_PLACEHOLDER: String = "OUTGOING_PLACEHOLDER" + + private var eglBaseWrapper: EglBaseWrapper? = null + private val holders: MutableSet = mutableSetOf() + + @JvmStatic + fun acquireEglBase(holder: Any): EglBaseWrapper { + val eglBase: EglBaseWrapper = eglBaseWrapper ?: EglBaseWrapper(EglBase.create()) + eglBaseWrapper = eglBase + holders += holder + Log.d(TAG, "Acquire EGL $eglBaseWrapper with holder: $holder") + return eglBase + } + + @JvmStatic + fun releaseEglBase(holder: Any) { + Log.d(TAG, "Release EGL with holder: $holder") + holders.remove(holder) + if (holders.isEmpty()) { + Log.d(TAG, "Holders empty, release EGL Base") + eglBaseWrapper?.releaseEglBase() + eglBaseWrapper = null + } + } + + @JvmStatic + fun replaceHolder(currentHolder: Any, newHolder: Any) { + if (currentHolder == newHolder) { + return + } + Log.d(TAG, "Replace holder $currentHolder with $newHolder") + holders += newHolder + holders.remove(currentHolder) + } + + @JvmStatic + fun forceRelease() { + eglBaseWrapper?.releaseEglBase() + eglBaseWrapper = null + holders.clear() + } + } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java index c494b14d7..8605cbd16 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ActiveCallActionProcessorDelegate.java @@ -118,21 +118,6 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor { } } - @Override - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - Log.i(tag, "handleCallConcluded():"); - - if (remotePeer == null) { - return currentState; - } - - Log.i(tag, "delete remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode()); - return currentState.builder() - .changeCallInfoState() - .removeRemotePeer(remotePeer) - .build(); - } - @Override protected @NonNull WebRtcServiceState handleReceivedOfferWhileActive(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { RemotePeer activePeer = currentState.getCallInfoState().requireActivePeer(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ConnectedCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ConnectedCallActionProcessor.java index 0796eb8e6..9757bd4a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ConnectedCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/ConnectedCallActionProcessor.java @@ -105,9 +105,4 @@ public class ConnectedCallActionProcessor extends DeviceAwareActionProcessor { protected @NonNull WebRtcServiceState handleReceivedOfferWhileActive(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { return activeCallDelegate.handleReceivedOfferWhileActive(currentState, remotePeer); } - - @Override - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - return activeCallDelegate.handleCallConcluded(currentState, remotePeer); - } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/DisconnectingCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/DisconnectingCallActionProcessor.java deleted file mode 100644 index 9426a0321..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/DisconnectingCallActionProcessor.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.thoughtcrime.securesms.service.webrtc; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.ringrtc.RemotePeer; -import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState; -import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder; -import org.whispersystems.signalservice.api.messages.calls.OfferMessage; - -/** - * Handles disconnecting state actions. This primairly entails dealing with final - * clean up in the call concluded action, but also allows for transitioning into idle/setup - * via beginning an outgoing or incoming call. - */ -public class DisconnectingCallActionProcessor extends WebRtcActionProcessor { - - private static final String TAG = Log.tag(DisconnectingCallActionProcessor.class); - - public DisconnectingCallActionProcessor(@NonNull WebRtcInteractor webRtcInteractor) { - super(webRtcInteractor, TAG); - } - - @Override - protected @NonNull WebRtcServiceState handleStartIncomingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { - Log.i(TAG, "handleStartIncomingCall():"); - currentState = currentState.builder() - .actionProcessor(new IdleActionProcessor(webRtcInteractor)) - .build(); - return currentState.getActionProcessor().handleStartIncomingCall(currentState, remotePeer); - } - - @Override - protected @NonNull WebRtcServiceState handleOutgoingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer, @NonNull OfferMessage.Type offerType) { - Log.i(TAG, "handleOutgoingCall():"); - currentState = currentState.builder() - .actionProcessor(new IdleActionProcessor(webRtcInteractor)) - .build(); - return currentState.getActionProcessor().handleOutgoingCall(currentState, remotePeer, offerType); - } - - @Override - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - Log.i(TAG, "handleCallConcluded():"); - - WebRtcServiceStateBuilder builder = currentState.builder() - .actionProcessor(new IdleActionProcessor(webRtcInteractor)); - - if (remotePeer != null) { - Log.i(TAG, "delete remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode()); - - builder.changeCallInfoState() - .removeRemotePeer(remotePeer) - .commit(); - } - - return builder.build(); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupNetworkUnavailableActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupNetworkUnavailableActionProcessor.java index f63695f5d..92c118221 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupNetworkUnavailableActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupNetworkUnavailableActionProcessor.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; import org.signal.ringrtc.GroupCall; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.events.WebRtcViewModel; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.ringrtc.RemotePeer; @@ -60,6 +61,7 @@ class GroupNetworkUnavailableActionProcessor extends WebRtcActionProcessor { Log.i(TAG, "handleCancelPreJoinCall():"); WebRtcVideoUtil.deinitializeVideo(currentState); + EglBaseWrapper.releaseEglBase(RemotePeer.GROUP_CALL_ID.longValue()); return new WebRtcServiceState(new IdleActionProcessor(webRtcInteractor)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java index 4e2e50e7a..d62899fa5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java @@ -9,6 +9,7 @@ import org.signal.ringrtc.CallException; import org.signal.ringrtc.GroupCall; import org.signal.ringrtc.PeekInfo; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.events.CallParticipant; import org.thoughtcrime.securesms.events.CallParticipantId; import org.thoughtcrime.securesms.events.WebRtcViewModel; @@ -78,6 +79,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor { } WebRtcVideoUtil.deinitializeVideo(currentState); + EglBaseWrapper.releaseEglBase(RemotePeer.GROUP_CALL_ID.longValue()); return new WebRtcServiceState(new IdleActionProcessor(webRtcInteractor)); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java index 44bb0ebaf..8c818363d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IdleActionProcessor.java @@ -5,6 +5,7 @@ import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; import org.signal.ringrtc.CallException; import org.signal.ringrtc.CallManager; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.WebRtcViewModel; import org.thoughtcrime.securesms.groups.GroupId; @@ -34,7 +35,7 @@ public class IdleActionProcessor extends WebRtcActionProcessor { protected @NonNull WebRtcServiceState handleStartIncomingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { Log.i(TAG, "handleStartIncomingCall():"); - currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState); + currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState, remotePeer.getCallId().longValue()); return beginCallDelegate.handleStartIncomingCall(currentState, remotePeer); } @@ -51,7 +52,7 @@ public class IdleActionProcessor extends WebRtcActionProcessor { return currentState; } - currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState); + currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState, EglBaseWrapper.OUTGOING_PLACEHOLDER); return beginCallDelegate.handleOutgoingCall(currentState, remotePeer, offerType); } @@ -63,7 +64,11 @@ public class IdleActionProcessor extends WebRtcActionProcessor { WebRtcActionProcessor processor = isGroupCall ? new GroupPreJoinActionProcessor(webRtcInteractor) : new PreJoinActionProcessor(webRtcInteractor); - currentState = WebRtcVideoUtil.initializeVanityCamera(WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState)); + currentState = WebRtcVideoUtil.initializeVanityCamera(WebRtcVideoUtil.initializeVideo(context, + webRtcInteractor.getCameraEventListener(), + currentState, + isGroupCall ? RemotePeer.GROUP_CALL_ID.longValue() + : EglBaseWrapper.OUTGOING_PLACEHOLDER)); currentState = currentState.builder() .actionProcessor(processor) diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java index 7c05fbfc4..ffacfce72 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingCallActionProcessor.java @@ -204,11 +204,6 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor { return activeCallDelegate.handleSetupFailure(currentState, callId); } - @Override - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - return activeCallDelegate.handleCallConcluded(currentState, remotePeer); - } - @Override public @NonNull WebRtcServiceState handleCallConnected(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { return callSetupDelegate.handleCallConnected(currentState, remotePeer); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java index d783ad0a8..068bc5a72 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java @@ -9,6 +9,7 @@ import org.signal.ringrtc.CallException; import org.signal.ringrtc.CallManager; import org.signal.ringrtc.GroupCall; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientDatabase; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; @@ -105,7 +106,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro DatabaseFactory.getGroupCallRingDatabase(context).insertGroupRing(ringId, System.currentTimeMillis(), ringUpdate); - currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState); + currentState = WebRtcVideoUtil.initializeVideo(context, webRtcInteractor.getCameraEventListener(), currentState, RemotePeer.GROUP_CALL_ID.longValue()); webRtcInteractor.setCallInProgressNotification(TYPE_INCOMING_RINGING, remotePeerGroup); webRtcInteractor.updatePhoneState(LockManager.PhoneState.INTERACTIVE); @@ -240,10 +241,12 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro webRtcInteractor.updatePhoneState(LockManager.PhoneState.IDLE); webRtcInteractor.stopForegroundService(); - return WebRtcVideoUtil.deinitializeVideo(currentState) - .builder() - .actionProcessor(new IdleActionProcessor(webRtcInteractor)) - .terminate(RemotePeer.GROUP_CALL_ID) - .build(); + currentState = WebRtcVideoUtil.deinitializeVideo(currentState); + EglBaseWrapper.releaseEglBase(RemotePeer.GROUP_CALL_ID.longValue()); + + return currentState.builder() + .actionProcessor(new IdleActionProcessor(webRtcInteractor)) + .terminate(RemotePeer.GROUP_CALL_ID) + .build(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java index 329a5942a..b48234c20 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/OutgoingCallActionProcessor.java @@ -9,6 +9,7 @@ import org.signal.core.util.logging.Log; import org.signal.ringrtc.CallException; import org.signal.ringrtc.CallId; import org.signal.ringrtc.CallManager; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.events.CallParticipant; @@ -76,6 +77,8 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor { RecipientUtil.setAndSendUniversalExpireTimerIfNecessary(context, Recipient.resolved(remotePeer.getId()), DatabaseFactory.getThreadDatabase(context).getThreadIdIfExistsFor(remotePeer.getId())); DatabaseFactory.getSmsDatabase(context).insertOutgoingCall(remotePeer.getId(), isVideoCall); + EglBaseWrapper.replaceHolder(EglBaseWrapper.OUTGOING_PLACEHOLDER, remotePeer.getCallId().longValue()); + webRtcInteractor.retrieveTurnServers(remotePeer); return builder.changeCallSetupState(remotePeer.getCallId()) @@ -210,11 +213,6 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor { return activeCallDelegate.handleSetupFailure(currentState, callId); } - @Override - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - return activeCallDelegate.handleCallConcluded(currentState, remotePeer); - } - @Override public @NonNull WebRtcServiceState handleCallConnected(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { return callSetupDelegate.handleCallConnected(currentState, remotePeer); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/PreJoinActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/PreJoinActionProcessor.java index fbe8880f0..78cf489a7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/PreJoinActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/PreJoinActionProcessor.java @@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.service.webrtc; import androidx.annotation.NonNull; import org.signal.core.util.logging.Log; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.events.WebRtcViewModel; import org.thoughtcrime.securesms.ringrtc.RemotePeer; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState; @@ -28,6 +29,7 @@ public class PreJoinActionProcessor extends DeviceAwareActionProcessor { Log.i(TAG, "handleCancelPreJoinCall():"); WebRtcVideoUtil.deinitializeVideo(currentState); + EglBaseWrapper.releaseEglBase(EglBaseWrapper.OUTGOING_PLACEHOLDER); return new WebRtcServiceState(new IdleActionProcessor(webRtcInteractor)); } @@ -35,6 +37,7 @@ public class PreJoinActionProcessor extends DeviceAwareActionProcessor { protected @NonNull WebRtcServiceState handleStartIncomingCall(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) { Log.i(TAG, "handleStartIncomingCall():"); + EglBaseWrapper.replaceHolder(EglBaseWrapper.OUTGOING_PLACEHOLDER, remotePeer.getCallId().longValue()); currentState = WebRtcVideoUtil.reinitializeCamera(context, webRtcInteractor.getCameraEventListener(), currentState) .builder() .changeCallInfoState() diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java index 964e24c40..c2461c206 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcActionProcessor.java @@ -16,6 +16,7 @@ import org.signal.ringrtc.CallManager.RingUpdate; import org.signal.ringrtc.GroupCall; import org.thoughtcrime.securesms.components.sensors.Orientation; import org.thoughtcrime.securesms.components.webrtc.BroadcastVideoSink; +import org.thoughtcrime.securesms.components.webrtc.EglBaseWrapper; import org.thoughtcrime.securesms.components.webrtc.GroupCallSafetyNumberChangeNotificationUtil; import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.database.DatabaseFactory; @@ -295,9 +296,21 @@ public abstract class WebRtcActionProcessor { return currentState; } - protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { - Log.i(tag, "handleCallConcluded not processed"); - return currentState; + final protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @Nullable RemotePeer remotePeer) { + Log.i(tag, "handleCallConcluded():"); + + if (remotePeer == null) { + return currentState; + } + + Log.i(tag, "delete remotePeer callId: " + remotePeer.getCallId() + " key: " + remotePeer.hashCode()); + + EglBaseWrapper.releaseEglBase(remotePeer.getCallId().longValue()); + + return currentState.builder() + .changeCallInfoState() + .removeRemotePeer(remotePeer) + .build(); } protected @NonNull WebRtcServiceState handleRemoteVideoEnable(@NonNull WebRtcServiceState currentState, boolean enable) { @@ -558,6 +571,8 @@ public abstract class WebRtcActionProcessor { Log.w(tag, "Unable to reset call manager: ", e); } + EglBaseWrapper.forceRelease(); + currentState = builder.changeCallInfoState().clearPeerMap().build(); return terminate(currentState, currentState.getCallInfoState().getActivePeer()); } @@ -596,7 +611,7 @@ public abstract class WebRtcActionProcessor { .commit() .changeLocalDeviceState() .commit() - .actionProcessor(currentState.getCallInfoState().getCallState() == WebRtcViewModel.State.CALL_DISCONNECTED ? new DisconnectingCallActionProcessor(webRtcInteractor) : new IdleActionProcessor(webRtcInteractor)) + .actionProcessor(new IdleActionProcessor(webRtcInteractor)) .terminate(remotePeer.getCallId()) .build(); } @@ -748,6 +763,7 @@ public abstract class WebRtcActionProcessor { if (terminateVideo) { WebRtcVideoUtil.deinitializeVideo(currentState); + EglBaseWrapper.releaseEglBase(RemotePeer.GROUP_CALL_ID.longValue()); } GroupCallSafetyNumberChangeNotificationUtil.cancelNotification(context, currentState.getCallInfoState().getCallRecipient()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java index 8b422d303..6cf0d12f5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/WebRtcVideoUtil.java @@ -13,7 +13,6 @@ import org.thoughtcrime.securesms.ringrtc.CameraState; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceState; import org.thoughtcrime.securesms.service.webrtc.state.WebRtcServiceStateBuilder; import org.webrtc.CapturerObserver; -import org.webrtc.EglBase; import org.webrtc.VideoFrame; import org.webrtc.VideoSink; @@ -27,12 +26,13 @@ public final class WebRtcVideoUtil { public static @NonNull WebRtcServiceState initializeVideo(@NonNull Context context, @NonNull CameraEventListener cameraEventListener, - @NonNull WebRtcServiceState currentState) + @NonNull WebRtcServiceState currentState, + @NonNull Object eglBaseHolder) { final WebRtcServiceStateBuilder builder = currentState.builder(); ThreadUtil.runOnMainSync(() -> { - EglBaseWrapper eglBase = new EglBaseWrapper(EglBase.create()); + EglBaseWrapper eglBase = EglBaseWrapper.acquireEglBase(eglBaseHolder); BroadcastVideoSink localSink = new BroadcastVideoSink(eglBase, true, false, @@ -89,8 +89,6 @@ public final class WebRtcVideoUtil { camera.dispose(); } - currentState.getVideoState().getLockableEglBase().releaseEglBase(); - return currentState.builder() .changeVideoState() .eglBase(null)