Resume call PIP on app foreground.

This commit is contained in:
Cody Henthorne
2024-03-11 15:39:47 -04:00
parent 9e349d2b30
commit ce778be895
3 changed files with 76 additions and 12 deletions

View File

@@ -137,6 +137,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
public static final String EXTRA_ENABLE_VIDEO_IF_AVAILABLE = WebRtcCallActivity.class.getCanonicalName() + ".ENABLE_VIDEO_IF_AVAILABLE";
public static final String EXTRA_STARTED_FROM_FULLSCREEN = WebRtcCallActivity.class.getCanonicalName() + ".STARTED_FROM_FULLSCREEN";
public static final String EXTRA_STARTED_FROM_CALL_LINK = WebRtcCallActivity.class.getCanonicalName() + ".STARTED_FROM_CALL_LINK";
public static final String EXTRA_LAUNCH_IN_PIP = WebRtcCallActivity.class.getCanonicalName() + ".STARTED_FROM_CALL_LINK";
private CallParticipantsListUpdatePopupWindow participantUpdateWindow;
private CallStateUpdatePopupWindow callStateUpdatePopupWindow;
@@ -159,6 +160,8 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
private LifecycleDisposable lifecycleDisposable;
private long lastCallLinkDisconnectDialogShowTime;
private ControlsAndInfoController controlsAndInfo;
private boolean enterPipOnResume;
private long lastProcessedIntentTimestamp;
private Disposable ephemeralStateDisposable = Disposable.empty();
@@ -264,6 +267,11 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
}
}, TimeUnit.SECONDS.toMillis(1));
}
if (enterPipOnResume) {
enterPipOnResume = false;
enterPipModeIfPossible();
}
}
@Override
@@ -303,8 +311,12 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
if (!viewModel.isCallStarting()) {
CallParticipantsState state = viewModel.getCallParticipantsStateSnapshot();
if (state != null && state.getCallState().isPreJoinOrNetworkUnavailable()) {
ApplicationDependencies.getSignalCallManager().cancelPreJoin();
if (state != null) {
if (state.getCallState().isPreJoinOrNetworkUnavailable()) {
ApplicationDependencies.getSignalCallManager().cancelPreJoin();
} else if (state.getCallState().getInOngoingCall() && isInPipMode()) {
ApplicationDependencies.getSignalCallManager().relaunchPipOnForeground();
}
}
}
}
@@ -363,6 +375,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
Log.d(TAG, "Intent: Action: " + intent.getAction());
Log.d(TAG, "Intent: EXTRA_STARTED_FROM_FULLSCREEN: " + intent.getBooleanExtra(EXTRA_STARTED_FROM_FULLSCREEN, false));
Log.d(TAG, "Intent: EXTRA_ENABLE_VIDEO_IF_AVAILABLE: " + intent.getBooleanExtra(EXTRA_ENABLE_VIDEO_IF_AVAILABLE, false));
Log.d(TAG, "Intent: EXTRA_LAUNCH_IN_PIP: " + intent.getBooleanExtra(EXTRA_LAUNCH_IN_PIP, false));
}
private void processIntent(@NonNull Intent intent) {
@@ -375,6 +388,12 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
} else if (END_CALL_ACTION.equals(intent.getAction())) {
handleEndCall();
}
if (System.currentTimeMillis() - lastProcessedIntentTimestamp > TimeUnit.SECONDS.toMillis(1)) {
enterPipOnResume = intent.getBooleanExtra(EXTRA_LAUNCH_IN_PIP, false);
}
lastProcessedIntentTimestamp = System.currentTimeMillis();
}
private void initializePendingParticipantFragmentListener() {
@@ -853,8 +872,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
}
private boolean isSystemPipEnabledAndAvailable() {
return Build.VERSION.SDK_INT >= 26 &&
getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
return Build.VERSION.SDK_INT >= 26 && getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
}
private void delayedFinish() {

View File

@@ -47,7 +47,10 @@ class WebRtcViewModel(state: WebRtcServiceState) {
get() = this == CALL_PRE_JOIN || this == NETWORK_FAILURE
val isPassedPreJoin: Boolean
get() = ordinal > ordinal
get() = ordinal > CALL_PRE_JOIN.ordinal
val inOngoingCall: Boolean
get() = this == CALL_INCOMING || this == CALL_OUTGOING || this == CALL_CONNECTED || this == CALL_RINGING || this == CALL_RECONNECTING
}
enum class GroupCallState {

View File

@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.service.webrtc;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.ResultReceiver;
@@ -125,14 +126,14 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
@Nullable private final CallManager callManager;
private final Context context;
private final ExecutorService serviceExecutor;
private final Executor networkExecutor;
private final LockManager lockManager;
private final Context context;
private final ExecutorService serviceExecutor;
private final Executor networkExecutor;
private final LockManager lockManager;
private WebRtcServiceState serviceState;
private RxStore<WebRtcEphemeralState> ephemeralStateStore;
private boolean needsToSetSelfUuid = true;
private boolean needsToSetSelfUuid = true;
private RxStore<Map<RecipientId, CallLinkPeekInfo>> linkPeekInfoStore;
@@ -182,8 +183,8 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
}
private void process(@NonNull ProcessAction action) {
Throwable t = new Throwable();
String caller = t.getStackTrace().length > 1 ? t.getStackTrace()[1].getMethodName() : "unknown";
Throwable t = new Throwable();
String caller = t.getStackTrace().length > 1 ? t.getStackTrace()[1].getMethodName() : "unknown";
if (callManager == null) {
Log.w(TAG, "Unable to process action, call manager is not initialized");
@@ -1151,6 +1152,10 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
return new SignalCallLinkManager(Objects.requireNonNull(callManager));
}
public void relaunchPipOnForeground() {
ApplicationDependencies.getAppForegroundObserver().addListener(new RelaunchListener(ApplicationDependencies.getAppForegroundObserver().isForegrounded()));
}
private void processSendMessageFailureWithChangeDetection(@NonNull RemotePeer remotePeer,
@NonNull ProcessAction failureProcessAction)
{
@@ -1169,6 +1174,44 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
});
}
private class RelaunchListener implements AppForegroundObserver.Listener {
private boolean canRelaunch;
public RelaunchListener(boolean isForegrounded) {
canRelaunch = !isForegrounded;
}
@Override
public void onForeground() {
if (canRelaunch) {
if (isSystemPipEnabledAndAvailable()) {
process((s, p) -> {
WebRtcViewModel.State callState = s.getCallInfoState().getCallState();
if (callState.getInOngoingCall()) {
Intent intent = new Intent(context, WebRtcCallActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(WebRtcCallActivity.EXTRA_LAUNCH_IN_PIP, true);
context.startActivity(intent);
}
return s;
});
}
ApplicationDependencies.getAppForegroundObserver().removeListener(this);
}
}
@Override
public void onBackground() {
canRelaunch = true;
}
private boolean isSystemPipEnabledAndAvailable() {
return Build.VERSION.SDK_INT >= 26 && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
}
}
interface ProcessAction {
@NonNull WebRtcServiceState process(@NonNull WebRtcServiceState currentState, @NonNull WebRtcActionProcessor processor);
}