Add shared calling intent system.

This commit is contained in:
Alex Hart 2024-09-03 15:22:44 -03:00 committed by Cody Henthorne
parent e5b482c7ad
commit 4d23f11f6e
12 changed files with 277 additions and 90 deletions

View file

@ -84,9 +84,10 @@ import org.thoughtcrime.securesms.components.webrtc.controls.ControlsAndInfoCont
import org.thoughtcrime.securesms.components.webrtc.controls.ControlsAndInfoViewModel;
import org.thoughtcrime.securesms.components.webrtc.participantslist.CallParticipantsListDialog;
import org.thoughtcrime.securesms.components.webrtc.requests.CallLinkIncomingRequestSheet;
import org.thoughtcrime.securesms.components.webrtc.v2.CallEvent;
import org.thoughtcrime.securesms.components.webrtc.v2.CallPermissionsDialogController;
import org.thoughtcrime.securesms.components.webrtc.v2.CallControlsChange;
import org.thoughtcrime.securesms.components.webrtc.v2.CallEvent;
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent;
import org.thoughtcrime.securesms.components.webrtc.v2.CallPermissionsDialogController;
import org.thoughtcrime.securesms.conversation.ui.error.SafetyNumberChangeDialog;
import org.thoughtcrime.securesms.dependencies.AppDependencies;
import org.thoughtcrime.securesms.events.WebRtcViewModel;
@ -132,23 +133,6 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
private static final int STANDARD_DELAY_FINISH = 1000;
private static final int VIBRATE_DURATION = 50;
/**
* ANSWER the call via voice-only.
*/
public static final String ANSWER_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".ANSWER_ACTION";
/**
* ANSWER the call via video.
*/
public static final String ANSWER_VIDEO_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".ANSWER_VIDEO_ACTION";
public static final String DENY_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".DENY_ACTION";
public static final String END_CALL_ACTION = WebRtcCallActivity.class.getCanonicalName() + ".END_CALL_ACTION";
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;
private CallOverflowPopupWindow callOverflowPopupWindow;
@ -184,7 +168,8 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
@SuppressLint({ "MissingInflatedId" })
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "onCreate(" + getIntent().getBooleanExtra(EXTRA_STARTED_FROM_FULLSCREEN, false) + ")");
CallIntent callIntent = getCallIntent();
Log.i(TAG, "onCreate(" + callIntent.isStartedFromFullScreen() + ")");
lifecycleDisposable = new LifecycleDisposable();
lifecycleDisposable.bindTo(this);
@ -214,18 +199,18 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
lifecycleDisposable.add(controlsAndInfo);
logIntent(getIntent());
logIntent(callIntent);
if (ANSWER_VIDEO_ACTION.equals(getIntent().getAction())) {
if (callIntent.getAction() == CallIntent.Action.ANSWER_VIDEO) {
enableVideoIfAvailable = true;
} else if (ANSWER_ACTION.equals(getIntent().getAction()) || getIntent().getBooleanExtra(EXTRA_STARTED_FROM_FULLSCREEN, false)) {
} else if (callIntent.getAction() == CallIntent.Action.ANSWER_AUDIO || callIntent.isStartedFromFullScreen()) {
enableVideoIfAvailable = false;
} else {
enableVideoIfAvailable = getIntent().getBooleanExtra(EXTRA_ENABLE_VIDEO_IF_AVAILABLE, false);
getIntent().removeExtra(EXTRA_ENABLE_VIDEO_IF_AVAILABLE);
enableVideoIfAvailable = callIntent.shouldEnableVideoIfAvailable();
callIntent.setShouldEnableVideoIfAvailable(false);
}
processIntent(getIntent());
processIntent(callIntent);
registerSystemPipChangeListeners();
@ -302,10 +287,11 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
@Override
public void onNewIntent(Intent intent) {
Log.i(TAG, "onNewIntent(" + intent.getBooleanExtra(EXTRA_STARTED_FROM_FULLSCREEN, false) + ")");
CallIntent callIntent = getCallIntent();
Log.i(TAG, "onNewIntent(" + callIntent.isStartedFromFullScreen() + ")");
super.onNewIntent(intent);
logIntent(intent);
processIntent(intent);
logIntent(callIntent);
processIntent(callIntent);
}
@Override
@ -373,6 +359,10 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
}
}
private @NonNull CallIntent getCallIntent() {
return new CallIntent(getIntent());
}
private boolean enterPipModeIfPossible() {
if (isSystemPipEnabledAndAvailable()) {
if (viewModel.canEnterPipMode()) {
@ -396,26 +386,20 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
return isSystemPipEnabledAndAvailable() && isInPictureInPictureMode();
}
private void logIntent(@NonNull Intent intent) {
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 logIntent(@NonNull CallIntent intent) {
Log.d(TAG, intent.toString());
}
private void processIntent(@NonNull Intent intent) {
if (ANSWER_ACTION.equals(intent.getAction())) {
handleAnswerWithAudio();
} else if (ANSWER_VIDEO_ACTION.equals(intent.getAction())) {
handleAnswerWithVideo();
} else if (DENY_ACTION.equals(intent.getAction())) {
handleDenyCall();
} else if (END_CALL_ACTION.equals(intent.getAction())) {
handleEndCall();
private void processIntent(@NonNull CallIntent intent) {
switch (intent.getAction()) {
case ANSWER_AUDIO -> handleAnswerWithAudio();
case ANSWER_VIDEO -> handleAnswerWithVideo();
case DENY -> handleDenyCall();
case END_CALL -> handleEndCall();
}
if (System.currentTimeMillis() - lastProcessedIntentTimestamp > TimeUnit.SECONDS.toMillis(1)) {
enterPipOnResume = intent.getBooleanExtra(EXTRA_LAUNCH_IN_PIP, false);
enterPipOnResume = intent.shouldLaunchInPip();
}
lastProcessedIntentTimestamp = System.currentTimeMillis();
@ -529,7 +513,7 @@ public class WebRtcCallActivity extends BaseActivity implements SafetyNumberChan
lifecycleDisposable.add(viewModel.getInCallstatus().subscribe(this::handleInCallStatus));
boolean isStartedFromCallLink = getIntent().getBooleanExtra(WebRtcCallActivity.EXTRA_STARTED_FROM_CALL_LINK, false);
boolean isStartedFromCallLink = getCallIntent().isStartedFromCallLink();
LiveDataUtil.combineLatest(LiveDataReactiveStreams.fromPublisher(viewModel.getCallParticipantsState().toFlowable(BackpressureStrategy.LATEST)),
orientationAndLandscapeEnabled,
viewModel.getEphemeralState(),

View file

@ -506,6 +506,14 @@ class InternalSettingsFragment : DSLSettingsFragment(R.string.preferences__inter
sectionHeaderPref(DSLSettingsText.from("Calling options"))
switchPref(
title = DSLSettingsText.from("Use new calling UI"),
isChecked = state.newCallingUi,
onClick = {
viewModel.setUseNewCallingUi(!state.newCallingUi)
}
)
radioListPref(
title = DSLSettingsText.from("Audio processing method"),
listItems = CallManager.AudioProcessingMethod.values().map { it.name }.toTypedArray(),

View file

@ -24,5 +24,6 @@ data class InternalSettingsState(
val pnpInitialized: Boolean,
val useConversationItemV2ForMedia: Boolean,
val hasPendingOneTimeDonation: Boolean,
val hevcEncoding: Boolean
val hevcEncoding: Boolean,
val newCallingUi: Boolean
)

View file

@ -165,7 +165,8 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
pnpInitialized = SignalStore.misc.hasPniInitializedDevices,
useConversationItemV2ForMedia = SignalStore.internal.useConversationItemV2Media(),
hasPendingOneTimeDonation = SignalStore.inAppPayments.getPendingOneTimeDonation() != null,
hevcEncoding = SignalStore.internal.hevcEncoding
hevcEncoding = SignalStore.internal.hevcEncoding,
newCallingUi = SignalStore.internal.newCallingUi
)
fun onClearOnboardingState() {
@ -176,6 +177,11 @@ class InternalSettingsViewModel(private val repository: InternalSettingsReposito
StoryOnboardingDownloadJob.enqueueIfNeeded()
}
fun setUseNewCallingUi(newCallingUi: Boolean) {
SignalStore.internal.newCallingUi = newCallingUi
refresh()
}
class Factory(private val repository: InternalSettingsRepository) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return requireNotNull(modelClass.cast(InternalSettingsViewModel(repository)))

View file

@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.components.webrtc.v2
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
@ -91,6 +92,7 @@ class CallActivity : BaseActivity(), CallControlsCallback {
val callInfoCallbacks = CallInfoCallbacks(this, controlsAndInfoViewModel, compositeDisposable)
observeCallEvents()
viewModel.processCallIntent(CallIntent(intent))
setContent {
val lifecycleOwner = LocalLifecycleOwner.current
@ -179,6 +181,13 @@ class CallActivity : BaseActivity(), CallControlsCallback {
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent != null) {
viewModel.processCallIntent(CallIntent(intent))
}
}
override fun onResume() {
Log.i(TAG, "onResume")
super.onResume()
@ -203,13 +212,9 @@ class CallActivity : BaseActivity(), CallControlsCallback {
}
}
/*
TODO
if (enterPipOnResume) {
enterPipOnResume = false;
enterPipModeIfPossible();
if (viewModel.consumeEnterPipOnResume()) {
// TODO enterPipModeIfPossible()
}
*/
}
override fun onPause() {

View file

@ -0,0 +1,138 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.components.webrtc.v2
import android.app.Activity
import android.content.Context
import android.content.Intent
import org.thoughtcrime.securesms.WebRtcCallActivity
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.util.RemoteConfig
/**
* CallIntent wraps an intent inside one of the call activities to allow for easy typed access to the necessary data within it.
*/
class CallIntent(
private val intent: Intent
) {
companion object {
private const val CALL_INTENT_PREFIX = "CallIntent"
private fun getActivityClass(): Class<out Activity> = if (RemoteConfig.newCallUi || SignalStore.internal.newCallingUi) {
CallActivity::class.java
} else {
WebRtcCallActivity::class.java
}
private fun getActionString(action: Action): String {
return "$CALL_INTENT_PREFIX.${action.code}"
}
private fun getExtraString(extra: Extra): String {
return "$CALL_INTENT_PREFIX.${extra.code}"
}
}
val action: Action by lazy { Action.fromIntent(intent) }
@get:JvmName("shouldEnableVideoIfAvailable")
var shouldEnableVideoIfAvailable: Boolean
get() = intent.getBooleanExtra(getExtraString(Extra.ENABLE_VIDEO_IF_AVAILABLE), false)
set(value) {
intent.putExtra(getExtraString(Extra.ENABLE_VIDEO_IF_AVAILABLE), value)
}
val isStartedFromFullScreen: Boolean by lazy { intent.getBooleanExtra(getExtraString(Extra.STARTED_FROM_FULLSCREEN), false) }
val isStartedFromCallLink: Boolean by lazy { intent.getBooleanExtra(getExtraString(Extra.STARTED_FROM_CALL_LINK), false) }
@get:JvmName("shouldLaunchInPip")
val shouldLaunchInPip: Boolean by lazy { intent.getBooleanExtra(getExtraString(Extra.LAUNCH_IN_PIP), false) }
override fun toString(): String {
return """
CallIntent
Action - $action
Enable video if available? $shouldEnableVideoIfAvailable
Started from full screen? $isStartedFromFullScreen
Started from call link? $isStartedFromCallLink
Launch in pip? $shouldLaunchInPip
""".trimIndent()
}
enum class Action(val code: String) {
VIEW(Intent.ACTION_VIEW),
ANSWER_AUDIO("ANSWER_ACTION"),
ANSWER_VIDEO("ANSWER_VIDEO_ACTION"),
DENY("DENY_ACTION"),
END_CALL("END_CALL_ACTION");
companion object {
fun fromIntent(intent: Intent): Action {
return intent.action?.let { a -> entries.firstOrNull { a == it.code || a == getActionString(it) } } ?: VIEW
}
}
}
private enum class Extra(val code: String) {
ENABLE_VIDEO_IF_AVAILABLE("ENABLE_VIDEO_IF_AVAILABLE"),
STARTED_FROM_FULLSCREEN("STARTED_FROM_FULLSCREEN"),
STARTED_FROM_CALL_LINK("STARTED_FROM_CALL_LINK"),
LAUNCH_IN_PIP("LAUNCH_IN_PIP")
}
/**
* Builds an intent to launch the call screen.
*/
class Builder(val context: Context) {
private val intent = Intent(context, getActivityClass())
init {
withAction(Action.VIEW)
}
fun withAddedIntentFlags(flags: Int): Builder {
intent.addFlags(flags)
return this
}
fun withIntentFlags(flags: Int): Builder {
intent.flags = flags
return this
}
fun withAction(action: Action?): Builder {
intent.action = action?.let { getActionString(action) }
return this
}
fun withEnableVideoIfAvailable(enableVideoIfAvailable: Boolean): Builder {
intent.putExtra(getExtraString(Extra.ENABLE_VIDEO_IF_AVAILABLE), enableVideoIfAvailable)
return this
}
fun withStartedFromFullScreen(startedFromFullScreen: Boolean): Builder {
intent.putExtra(getExtraString(Extra.STARTED_FROM_FULLSCREEN), startedFromFullScreen)
return this
}
fun withStartedFromCallLink(startedFromCallLink: Boolean): Builder {
intent.putExtra(getExtraString(Extra.STARTED_FROM_CALL_LINK), startedFromCallLink)
return this
}
fun withLaunchInPip(launchInPip: Boolean): Builder {
intent.putExtra(getExtraString(Extra.LAUNCH_IN_PIP), launchInPip)
return this
}
fun build(): Intent {
return intent
}
}
}

View file

@ -32,6 +32,7 @@ import org.thoughtcrime.securesms.sms.MessageSender
import org.thoughtcrime.securesms.webrtc.audio.SignalAudioManager
import org.whispersystems.signalservice.api.messages.calls.HangupMessage
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
/**
* Presentation logic and state holder for information that was generally done
@ -48,10 +49,18 @@ class CallViewModel(
private var previousEvent: WebRtcViewModel? = null
private var enableVideoIfAvailable = false
private var lastProcessedIntentTimestamp = 0L
private var enterPipOnResume = false
private val internalCallScreenState = MutableStateFlow(CallScreenState())
val callScreenState: StateFlow<CallScreenState> = internalCallScreenState
fun consumeEnterPipOnResume(): Boolean {
val enter = enterPipOnResume
enterPipOnResume = false
return enter
}
fun unregisterEventBus() {
EventBus.getDefault().unregister(this)
}
@ -337,4 +346,31 @@ class CallViewModel(
AppDependencies.signalCallManager.selectAudioDevice(SignalAudioManager.ChosenAudioDeviceIdentifier(managerDevice))
}
}
fun processCallIntent(callIntent: CallIntent) {
if (callIntent.action == CallIntent.Action.ANSWER_VIDEO) {
enableVideoIfAvailable = true
} else if (callIntent.action == CallIntent.Action.ANSWER_AUDIO || callIntent.isStartedFromFullScreen) {
enableVideoIfAvailable = false
} else {
enableVideoIfAvailable = callIntent.shouldEnableVideoIfAvailable
callIntent.shouldEnableVideoIfAvailable = false
}
when (callIntent.action) {
CallIntent.Action.ANSWER_AUDIO -> startCall(false)
CallIntent.Action.ANSWER_VIDEO -> startCall(true)
CallIntent.Action.DENY -> deny()
CallIntent.Action.END_CALL -> hangup()
CallIntent.Action.VIEW -> Unit
}
// Prevents some issues around intent re-use when dealing with picture-in-picture.
val now = System.currentTimeMillis()
if (now - lastProcessedIntentTimestamp > 1.seconds.inWholeMilliseconds) {
enterPipOnResume = callIntent.shouldLaunchInPip
}
lastProcessedIntentTimestamp = now
}
}

View file

@ -33,6 +33,7 @@ public final class InternalValues extends SignalStoreValues {
public static final String FORCE_ENTER_RESTORE_V2_FLOW = "internal.force_enter_restore_v2_flow";
public static final String WEB_SOCKET_SHADOWING_STATS = "internal.web_socket_shadowing_stats";
public static final String ENCODE_HEVC = "internal.hevc_encoding";
public static final String NEW_CALL_UI = "internal.new.call.ui";
InternalValues(KeyValueStore store) {
super(store);
@ -192,6 +193,14 @@ public final class InternalValues extends SignalStoreValues {
return getBoolean(ENCODE_HEVC, false);
}
public void setNewCallingUi(boolean enabled) {
putBoolean(NEW_CALL_UI, enabled);
}
public boolean getNewCallingUi() {
return getBoolean(NEW_CALL_UI, false);
}
public void setLastScrollPosition(int position) {
putInteger(LAST_SCROLL_POSITION, position);
}

View file

@ -6,7 +6,7 @@ import android.telecom.CallAudioState
import android.telecom.Connection
import androidx.annotation.RequiresApi
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.WebRtcCallActivity
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent
import org.thoughtcrime.securesms.dependencies.AppDependencies
import org.thoughtcrime.securesms.permissions.Permissions
import org.thoughtcrime.securesms.recipients.RecipientId
@ -66,9 +66,10 @@ class AndroidCallConnection(
if (Permissions.hasAll(context, android.Manifest.permission.RECORD_AUDIO)) {
AppDependencies.signalCallManager.acceptCall(false)
} else {
val intent = Intent(context, WebRtcCallActivity::class.java)
intent.action = if (isVideoCall) WebRtcCallActivity.ANSWER_VIDEO_ACTION else WebRtcCallActivity.ANSWER_ACTION
intent.flags = intent.flags or Intent.FLAG_ACTIVITY_NEW_TASK
val intent = CallIntent.Builder(context)
.withAddedIntentFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.withAction(if (isVideoCall) CallIntent.Action.ANSWER_VIDEO else CallIntent.Action.ANSWER_AUDIO)
.build()
context.startActivity(intent)
}
}

View file

@ -36,6 +36,7 @@ import org.signal.ringrtc.PeekInfo;
import org.signal.ringrtc.Remote;
import org.signal.storageservice.protos.groups.GroupExternalCredential;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent;
import org.thoughtcrime.securesms.crypto.SealedSenderAccessUtil;
import org.thoughtcrime.securesms.database.CallLinkTable;
import org.thoughtcrime.securesms.database.CallTable;
@ -1253,10 +1254,12 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall.
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);
context.startActivity(
new CallIntent.Builder(context)
.withIntentFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.withLaunchInPip(true)
.build()
);
}
return s;

View file

@ -32,6 +32,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.calls.links.CallLinks;
import org.thoughtcrime.securesms.components.webrtc.v2.CallActivity;
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent;
import org.thoughtcrime.securesms.contacts.sync.ContactDiscovery;
import org.thoughtcrime.securesms.conversation.ConversationIntents;
import org.thoughtcrime.securesms.database.CallLinkTable;
@ -397,11 +398,11 @@ public class CommunicationActions {
MessageSender.onMessageSent();
Intent activityIntent = new Intent(callContext.getContext(), getCallActivityClass());
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
callContext.startActivity(activityIntent);
callContext.startActivity(
new CallIntent.Builder(callContext.getContext())
.withIntentFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.build()
);
})
.execute();
}
@ -409,13 +410,13 @@ public class CommunicationActions {
private static void startVideoCallInternal(@NonNull CallContext callContext, @NonNull Recipient recipient, boolean fromCallLink) {
AppDependencies.getSignalCallManager().startPreJoinCall(recipient);
Intent activityIntent = new Intent(callContext.getContext(), getCallActivityClass());
activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(WebRtcCallActivity.EXTRA_ENABLE_VIDEO_IF_AVAILABLE, true)
.putExtra(WebRtcCallActivity.EXTRA_STARTED_FROM_CALL_LINK, fromCallLink);
callContext.startActivity(activityIntent);
callContext.startActivity(
new CallIntent.Builder(callContext.getContext())
.withIntentFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.withEnableVideoIfAvailable(true)
.withStartedFromCallLink(fromCallLink)
.build()
);
}
private static void handleE164Link(Activity activity, String e164) {
@ -479,10 +480,6 @@ public class CommunicationActions {
});
}
private static Class<? extends Activity> getCallActivityClass() {
return RemoteConfig.newCallUi() ? CallActivity.class : WebRtcCallActivity.class;
}
private interface CallContext {
@NonNull Permissions.PermissionsBuilder getPermissionsBuilder();
void startActivity(@NonNull Intent intent);

View file

@ -15,10 +15,9 @@ import androidx.core.app.Person;
import org.signal.core.util.PendingIntentFlags;
import org.thoughtcrime.securesms.MainActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WebRtcCallActivity;
import org.thoughtcrime.securesms.components.webrtc.v2.CallIntent;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.webrtc.ActiveCallManager;
import org.thoughtcrime.securesms.service.webrtc.WebRtcCallService;
import org.thoughtcrime.securesms.util.ConversationUtil;
@ -49,13 +48,13 @@ public class CallNotificationBuilder {
private enum LaunchCallScreenIntentState {
CONTENT(null, 0),
AUDIO(WebRtcCallActivity.ANSWER_ACTION, 1),
VIDEO(WebRtcCallActivity.ANSWER_VIDEO_ACTION, 2);
AUDIO(CallIntent.Action.ANSWER_AUDIO, 1),
VIDEO(CallIntent.Action.ANSWER_VIDEO, 2);
final @Nullable String action;
final int requestCode;
final @Nullable CallIntent.Action action;
final int requestCode;
LaunchCallScreenIntentState(@Nullable String action, int requestCode) {
LaunchCallScreenIntentState(@Nullable CallIntent.Action action, int requestCode) {
this.action = action;
this.requestCode = requestCode;
}
@ -219,17 +218,17 @@ public class CallNotificationBuilder {
}
private static PendingIntent getActivityPendingIntent(@NonNull Context context, @NonNull LaunchCallScreenIntentState launchCallScreenIntentState) {
Intent intent = new Intent(context, WebRtcCallActivity.class);
intent.setAction(launchCallScreenIntentState.action);
CallIntent.Builder builder = new CallIntent.Builder(context);
builder.withAction(launchCallScreenIntentState.action);
if (launchCallScreenIntentState == LaunchCallScreenIntentState.CONTENT) {
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
builder.withIntentFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
}
intent.putExtra(WebRtcCallActivity.EXTRA_STARTED_FROM_FULLSCREEN, launchCallScreenIntentState == LaunchCallScreenIntentState.CONTENT);
intent.putExtra(WebRtcCallActivity.EXTRA_ENABLE_VIDEO_IF_AVAILABLE, false);
builder.withStartedFromFullScreen(launchCallScreenIntentState == LaunchCallScreenIntentState.CONTENT);
builder.withEnableVideoIfAvailable(false);
return PendingIntent.getActivity(context, launchCallScreenIntentState.requestCode, intent, PendingIntentFlags.updateCurrent());
return PendingIntent.getActivity(context, launchCallScreenIntentState.requestCode, builder.build(), PendingIntentFlags.updateCurrent());
}
private static boolean deviceVersionSupportsIncomingCallStyle() {