~singpolyma/cheogram-android

a3085fbf1f143149cb40cfda085199fb4fe22992 — Daniel Gultsch 2 years ago 35c54f0
do not restart wakelock if activity is finishing
1 files changed, 311 insertions(+), 197 deletions(-)

M src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java
M src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java => src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +311 -197
@@ 69,7 69,9 @@ import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection;
import eu.siacs.conversations.xmpp.jingle.Media;
import eu.siacs.conversations.xmpp.jingle.RtpEndUserState;

public class RtpSessionActivity extends XmppActivity implements XmppConnectionService.OnJingleRtpConnectionUpdate, eu.siacs.conversations.ui.widget.SurfaceViewRenderer.OnAspectRatioChanged {
public class RtpSessionActivity extends XmppActivity
        implements XmppConnectionService.OnJingleRtpConnectionUpdate,
                eu.siacs.conversations.ui.widget.SurfaceViewRenderer.OnAspectRatioChanged {

    public static final String EXTRA_WITH = "with";
    public static final String EXTRA_SESSION_ID = "session_id";


@@ 81,33 83,31 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe

    private static final int CALL_DURATION_UPDATE_INTERVAL = 333;

    private static final List<RtpEndUserState> END_CARD = Arrays.asList(
            RtpEndUserState.APPLICATION_ERROR,
            RtpEndUserState.SECURITY_ERROR,
            RtpEndUserState.DECLINED_OR_BUSY,
            RtpEndUserState.CONNECTIVITY_ERROR,
            RtpEndUserState.CONNECTIVITY_LOST_ERROR,
            RtpEndUserState.RETRACTED
    );
    private static final List<RtpEndUserState> STATES_SHOWING_HELP_BUTTON = Arrays.asList(
            RtpEndUserState.APPLICATION_ERROR,
            RtpEndUserState.CONNECTIVITY_ERROR,
            RtpEndUserState.SECURITY_ERROR
    );
    private static final List<RtpEndUserState> STATES_SHOWING_SWITCH_TO_CHAT = Arrays.asList(
            RtpEndUserState.CONNECTING,
            RtpEndUserState.CONNECTED,
            RtpEndUserState.RECONNECTING
    );
    private static final List<RtpEndUserState> STATES_CONSIDERED_CONNECTED = Arrays.asList(
            RtpEndUserState.CONNECTED,
            RtpEndUserState.RECONNECTING
    );
    private static final List<RtpEndUserState> STATES_SHOWING_PIP_PLACEHOLDER = Arrays.asList(
            RtpEndUserState.ACCEPTING_CALL,
            RtpEndUserState.CONNECTING,
            RtpEndUserState.RECONNECTING
    );
    private static final List<RtpEndUserState> END_CARD =
            Arrays.asList(
                    RtpEndUserState.APPLICATION_ERROR,
                    RtpEndUserState.SECURITY_ERROR,
                    RtpEndUserState.DECLINED_OR_BUSY,
                    RtpEndUserState.CONNECTIVITY_ERROR,
                    RtpEndUserState.CONNECTIVITY_LOST_ERROR,
                    RtpEndUserState.RETRACTED);
    private static final List<RtpEndUserState> STATES_SHOWING_HELP_BUTTON =
            Arrays.asList(
                    RtpEndUserState.APPLICATION_ERROR,
                    RtpEndUserState.CONNECTIVITY_ERROR,
                    RtpEndUserState.SECURITY_ERROR);
    private static final List<RtpEndUserState> STATES_SHOWING_SWITCH_TO_CHAT =
            Arrays.asList(
                    RtpEndUserState.CONNECTING,
                    RtpEndUserState.CONNECTED,
                    RtpEndUserState.RECONNECTING);
    private static final List<RtpEndUserState> STATES_CONSIDERED_CONNECTED =
            Arrays.asList(RtpEndUserState.CONNECTED, RtpEndUserState.RECONNECTING);
    private static final List<RtpEndUserState> STATES_SHOWING_PIP_PLACEHOLDER =
            Arrays.asList(
                    RtpEndUserState.ACCEPTING_CALL,
                    RtpEndUserState.CONNECTING,
                    RtpEndUserState.RECONNECTING);
    private static final String PROXIMITY_WAKE_LOCK_TAG = "conversations:in-rtp-session";
    private static final int REQUEST_ACCEPT_CALL = 0x1111;
    private WeakReference<JingleRtpConnection> rtpConnectionReference;


@@ 116,13 116,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    private PowerManager.WakeLock mProximityWakeLock;

    private final Handler mHandler = new Handler();
    private final Runnable mTickExecutor = new Runnable() {
        @Override
        public void run() {
            updateCallDuration();
            mHandler.postDelayed(mTickExecutor, CALL_DURATION_UPDATE_INTERVAL);
        }
    };
    private final Runnable mTickExecutor =
            new Runnable() {
                @Override
                public void run() {
                    updateCallDuration();
                    mHandler.postDelayed(mTickExecutor, CALL_DURATION_UPDATE_INTERVAL);
                }
            };

    private static Set<Media> actionToMedia(final String action) {
        if (ACTION_MAKE_VIDEO_CALL.equals(action)) {


@@ 132,21 133,27 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        }
    }

    private static void addSink(final VideoTrack videoTrack, final SurfaceViewRenderer surfaceViewRenderer) {
    private static void addSink(
            final VideoTrack videoTrack, final SurfaceViewRenderer surfaceViewRenderer) {
        try {
            videoTrack.addSink(surfaceViewRenderer);
        } catch (final IllegalStateException e) {
            Log.e(Config.LOGTAG, "possible race condition on trying to display video track. ignoring", e);
            Log.e(
                    Config.LOGTAG,
                    "possible race condition on trying to display video track. ignoring",
                    e);
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        getWindow()
                .addFlags(
                        WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                                | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
        this.binding = DataBindingUtil.setContentView(this, R.layout.activity_rtp_session);
        setSupportActionBar(binding.toolbar);
    }


@@ 178,7 185,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            return STATES_SHOWING_HELP_BUTTON.contains(requireRtpConnection().getEndUserState());
        } catch (IllegalStateException e) {
            final Intent intent = getIntent();
            final String state = intent != null ? intent.getStringExtra(EXTRA_LAST_REPORTED_STATE) : null;
            final String state =
                    intent != null ? intent.getStringExtra(EXTRA_LAST_REPORTED_STATE) : null;
            if (state != null) {
                return STATES_SHOWING_HELP_BUTTON.contains(RtpEndUserState.valueOf(state));
            } else {


@@ 188,13 196,17 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private boolean isSwitchToConversationVisible() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        return connection != null && STATES_SHOWING_SWITCH_TO_CHAT.contains(connection.getEndUserState());
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        return connection != null
                && STATES_SHOWING_SWITCH_TO_CHAT.contains(connection.getEndUserState());
    }

    private void switchToConversation() {
        final Contact contact = getWith();
        final Conversation conversation = xmppConnectionService.findOrCreateConversation(contact.getAccount(), contact.getJid(), false, true);
        final Conversation conversation =
                xmppConnectionService.findOrCreateConversation(
                        contact.getAccount(), contact.getJid(), false, true);
        switchToConversation(conversation);
    }



@@ 215,7 227,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        try {
            startActivity(intent);
        } catch (final ActivityNotFoundException e) {
            Toast.makeText(this, R.string.no_application_found_to_open_link, Toast.LENGTH_LONG).show();
            Toast.makeText(this, R.string.no_application_found_to_open_link, Toast.LENGTH_LONG)
                    .show();
        }
    }



@@ 238,10 251,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        final Account account = extractAccount(intent);
        final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
        final String state = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
        if (!Intent.ACTION_VIEW.equals(action) || state == null || !END_CARD.contains(RtpEndUserState.valueOf(state))) {
            resetIntent(account, with, RtpEndUserState.RETRACTED, actionToMedia(intent.getAction()));
        if (!Intent.ACTION_VIEW.equals(action)
                || state == null
                || !END_CARD.contains(RtpEndUserState.valueOf(state))) {
            resetIntent(
                    account, with, RtpEndUserState.RETRACTED, actionToMedia(intent.getAction()));
        }
        xmppConnectionService.getJingleConnectionManager().retractSessionProposal(account, with.asBareJid());
        xmppConnectionService
                .getJingleConnectionManager()
                .retractSessionProposal(account, with.asBareJid());
    }

    private void rejectCall(View view) {


@@ 256,7 274,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    private void requestPermissionsAndAcceptCall() {
        final List<String> permissions;
        if (getMedia().contains(Media.VIDEO)) {
            permissions = ImmutableList.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO);
            permissions =
                    ImmutableList.of(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO);
        } else {
            permissions = ImmutableList.of(Manifest.permission.RECORD_AUDIO);
        }


@@ 267,7 286,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private void checkRecorderAndAcceptCall() {
        checkMicrophoneAvailability();
        checkMicrophoneAvailabilityAsync();
        try {
            requireRtpConnection().acceptCall();
        } catch (final IllegalStateException e) {


@@ 275,18 294,22 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        }
    }

    private void checkMicrophoneAvailabilityAsync() {
        new Thread(this::checkMicrophoneAvailability).start();
    }

    private void checkMicrophoneAvailability() {
        new Thread(() -> {
            final long start = SystemClock.elapsedRealtime();
            final boolean isMicrophoneAvailable = AppRTCAudioManager.isMicrophoneAvailable();
            final long stop = SystemClock.elapsedRealtime();
            Log.d(Config.LOGTAG, "checking microphone availability took " + (stop - start) + "ms");
            if (isMicrophoneAvailable) {
                return;
            }
            runOnUiThread(() -> Toast.makeText(this, R.string.microphone_unavailable, Toast.LENGTH_LONG).show());
        final long start = SystemClock.elapsedRealtime();
        final boolean isMicrophoneAvailable = AppRTCAudioManager.isMicrophoneAvailable();
        final long stop = SystemClock.elapsedRealtime();
        Log.d(Config.LOGTAG, "checking microphone availability took " + (stop - start) + "ms");
        if (isMicrophoneAvailable) {
            return;
        }
        ).start();
        runOnUiThread(
                () ->
                        Toast.makeText(this, R.string.microphone_unavailable, Toast.LENGTH_LONG)
                                .show());
    }

    private void putScreenInCallMode() {


@@ 296,9 319,13 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    private void putScreenInCallMode(final Set<Media> media) {
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        if (!media.contains(Media.VIDEO)) {
            final JingleRtpConnection rtpConnection = rtpConnectionReference != null ? rtpConnectionReference.get() : null;
            final AppRTCAudioManager audioManager = rtpConnection == null ? null : rtpConnection.getAudioManager();
            if (audioManager == null || audioManager.getSelectedAudioDevice() == AppRTCAudioManager.AudioDevice.EARPIECE) {
            final JingleRtpConnection rtpConnection =
                    rtpConnectionReference != null ? rtpConnectionReference.get() : null;
            final AppRTCAudioManager audioManager =
                    rtpConnection == null ? null : rtpConnection.getAudioManager();
            if (audioManager == null
                    || audioManager.getSelectedAudioDevice()
                            == AppRTCAudioManager.AudioDevice.EARPIECE) {
                acquireProximityWakeLock();
            }
        }


@@ 311,30 338,31 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            Log.e(Config.LOGTAG, "power manager not available");
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (this.mProximityWakeLock == null) {
                this.mProximityWakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, PROXIMITY_WAKE_LOCK_TAG);
            }
            if (!this.mProximityWakeLock.isHeld()) {
                Log.d(Config.LOGTAG, "acquiring proximity wake lock");
                this.mProximityWakeLock.acquire();
            }
        if (isFinishing()) {
            Log.e(Config.LOGTAG, "do not acquire wakelock. activity is finishing");
            return;
        }
        if (this.mProximityWakeLock == null) {
            this.mProximityWakeLock =
                    powerManager.newWakeLock(
                            PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, PROXIMITY_WAKE_LOCK_TAG);
        }
        if (!this.mProximityWakeLock.isHeld()) {
            Log.d(Config.LOGTAG, "acquiring proximity wake lock");
            this.mProximityWakeLock.acquire();
        }
    }

    private void releaseProximityWakeLock() {
        if (this.mProximityWakeLock != null && mProximityWakeLock.isHeld()) {
            Log.d(Config.LOGTAG, "releasing proximity wake lock");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                this.mProximityWakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
            } else {
                this.mProximityWakeLock.release();
            }
            this.mProximityWakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY);
            this.mProximityWakeLock = null;
        }
    }

    private void putProximityWakeLockInProperState(final AppRTCAudioManager.AudioDevice audioDevice) {
    private void putProximityWakeLockInProperState(
            final AppRTCAudioManager.AudioDevice audioDevice) {
        if (audioDevice == AppRTCAudioManager.AudioDevice.EARPIECE) {
            acquireProximityWakeLock();
        } else {


@@ 343,9 371,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @Override
    protected void refreshUiReal() {

    }
    protected void refreshUiReal() {}

    @Override
    public void onNewIntent(final Intent intent) {


@@ 353,7 379,9 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        super.onNewIntent(intent);
        setIntent(intent);
        if (xmppConnectionService == null) {
            Log.d(Config.LOGTAG, "RtpSessionActivity: background service wasn't bound in onNewIntent()");
            Log.d(
                    Config.LOGTAG,
                    "RtpSessionActivity: background service wasn't bound in onNewIntent()");
            return;
        }
        final Account account = extractAccount(intent);


@@ 399,7 427,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            binding.with.setText(account.getRoster().getContact(with).getDisplayName());
        } else if (Intent.ACTION_VIEW.equals(action)) {
            final String extraLastState = intent.getStringExtra(EXTRA_LAST_REPORTED_STATE);
            final RtpEndUserState state = extraLastState == null ? null : RtpEndUserState.valueOf(extraLastState);
            final RtpEndUserState state =
                    extraLastState == null ? null : RtpEndUserState.valueOf(extraLastState);
            if (state != null) {
                Log.d(Config.LOGTAG, "restored last state from intent extra");
                updateButtonConfiguration(state);


@@ 409,10 438,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                invalidateOptionsMenu();
            }
            binding.with.setText(account.getRoster().getContact(with).getDisplayName());
            if (xmppConnectionService.getJingleConnectionManager().fireJingleRtpConnectionStateUpdates()) {
            if (xmppConnectionService
                    .getJingleConnectionManager()
                    .fireJingleRtpConnectionStateUpdates()) {
                return;
            }
            if (END_CARD.contains(state) || xmppConnectionService.getJingleConnectionManager().hasMatchingProposal(account, with)) {
            if (END_CARD.contains(state)
                    || xmppConnectionService
                            .getJingleConnectionManager()
                            .hasMatchingProposal(account, with)) {
                return;
            }
            Log.d(Config.LOGTAG, "restored state (" + state + ") was not an end card. finishing");


@@ 420,12 454,18 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        }
    }

    private void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
        checkMicrophoneAvailability();
    private void proposeJingleRtpSession(
            final Account account, final Jid with, final Set<Media> media) {
        checkMicrophoneAvailabilityAsync();
        if (with.isBareJid()) {
            xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with, media);
            xmppConnectionService
                    .getJingleConnectionManager()
                    .proposeJingleRtpSession(account, with, media);
        } else {
            final String sessionId = xmppConnectionService.getJingleConnectionManager().initializeRtpSession(account, with, media);
            final String sessionId =
                    xmppConnectionService
                            .getJingleConnectionManager()
                            .initializeRtpSession(account, with, media);
            initializeActivityWithRunningRtpSession(account, with, sessionId);
            resetIntent(account, with, sessionId);
        }


@@ 433,7 473,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    public void onRequestPermissionsResult(
            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (PermissionUtils.allGranted(grantResults)) {
            if (requestCode == REQUEST_ACCEPT_CALL) {


@@ 449,7 490,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            } else {
                throw new IllegalStateException("Invalid permission result request");
            }
            Toast.makeText(this, getString(res, getString(R.string.app_name)), Toast.LENGTH_SHORT).show();
            Toast.makeText(this, getString(res, getString(R.string.app_name)), Toast.LENGTH_SHORT)
                    .show();
        }
    }



@@ 467,7 509,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        binding.remoteVideo.setOnAspectRatioChanged(null);
        binding.localVideo.release();
        final WeakReference<JingleRtpConnection> weakReference = this.rtpConnectionReference;
        final JingleRtpConnection jingleRtpConnection = weakReference == null ? null : weakReference.get();
        final JingleRtpConnection jingleRtpConnection =
                weakReference == null ? null : weakReference.get();
        if (jingleRtpConnection != null) {
            releaseVideoTracks(jingleRtpConnection);
        }


@@ 504,15 547,18 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        if (switchToPictureInPicture()) {
            return;
        }
        //TODO apparently this method is not getting called on Android 10 when using the task switcher
        // TODO apparently this method is not getting called on Android 10 when using the task
        // switcher
        if (emptyReference(rtpConnectionReference) && xmppConnectionService != null) {
            retractSessionProposal();
        }
    }

    private boolean isConnected() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        return connection != null && STATES_CONSIDERED_CONNECTED.contains(connection.getEndUserState());
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        return connection != null
                && STATES_CONSIDERED_CONNECTED.contains(connection.getEndUserState());
    }

    private boolean switchToPictureInPicture() {


@@ 530,14 576,13 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        try {
            final Rational rational = this.binding.remoteVideo.getAspectRatio();
            final Rational clippedRational = Rationals.clip(rational);
            Log.d(Config.LOGTAG, "suggested rational " + rational + ". clipped to " + clippedRational);
            Log.d(
                    Config.LOGTAG,
                    "suggested rational " + rational + ". clipped to " + clippedRational);
            enterPictureInPictureMode(
                    new PictureInPictureParams.Builder()
                            .setAspectRatio(clippedRational)
                            .build()
            );
                    new PictureInPictureParams.Builder().setAspectRatio(clippedRational).build());
        } catch (final IllegalStateException e) {
            //this sometimes happens on Samsung phones (possibly when Knox is enabled)
            // this sometimes happens on Samsung phones (possibly when Knox is enabled)
            Log.w(Config.LOGTAG, "unable to enter picture in picture mode", e);
        }
    }


@@ 546,10 591,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    public void onAspectRatioChanged(final Rational rational) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isPictureInPicture()) {
            final Rational clippedRational = Rationals.clip(rational);
            Log.d(Config.LOGTAG, "suggested rational after aspect ratio change " + rational + ". clipped to " + clippedRational);
            setPictureInPictureParams(new PictureInPictureParams.Builder()
                    .setAspectRatio(clippedRational)
                    .build());
            Log.d(
                    Config.LOGTAG,
                    "suggested rational after aspect ratio change "
                            + rational
                            + ". clipped to "
                            + clippedRational);
            setPictureInPictureParams(
                    new PictureInPictureParams.Builder().setAspectRatio(clippedRational).build());
        }
    }



@@ 564,24 613,31 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    private boolean shouldBePictureInPicture() {
        try {
            final JingleRtpConnection rtpConnection = requireRtpConnection();
            return rtpConnection.getMedia().contains(Media.VIDEO) && Arrays.asList(
                    RtpEndUserState.ACCEPTING_CALL,
                    RtpEndUserState.CONNECTING,
                    RtpEndUserState.CONNECTED
            ).contains(rtpConnection.getEndUserState());
            return rtpConnection.getMedia().contains(Media.VIDEO)
                    && Arrays.asList(
                                    RtpEndUserState.ACCEPTING_CALL,
                                    RtpEndUserState.CONNECTING,
                                    RtpEndUserState.CONNECTED)
                            .contains(rtpConnection.getEndUserState());
        } catch (final IllegalStateException e) {
            return false;
        }
    }

    private boolean initializeActivityWithRunningRtpSession(final Account account, Jid with, String sessionId) {
        final WeakReference<JingleRtpConnection> reference = xmppConnectionService.getJingleConnectionManager()
                .findJingleRtpConnection(account, with, sessionId);
    private boolean initializeActivityWithRunningRtpSession(
            final Account account, Jid with, String sessionId) {
        final WeakReference<JingleRtpConnection> reference =
                xmppConnectionService
                        .getJingleConnectionManager()
                        .findJingleRtpConnection(account, with, sessionId);
        if (reference == null || reference.get() == null) {
            final JingleConnectionManager.TerminatedRtpSession terminatedRtpSession = xmppConnectionService
                    .getJingleConnectionManager().getTerminalSessionState(with, sessionId);
            final JingleConnectionManager.TerminatedRtpSession terminatedRtpSession =
                    xmppConnectionService
                            .getJingleConnectionManager()
                            .getTerminalSessionState(with, sessionId);
            if (terminatedRtpSession == null) {
                throw new IllegalStateException("failed to initialize activity with running rtp session. session not found");
                throw new IllegalStateException(
                        "failed to initialize activity with running rtp session. session not found");
            }
            initializeWithTerminatedSessionState(account, with, terminatedRtpSession);
            return true;


@@ 598,7 654,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        if (currentState == RtpEndUserState.INCOMING_CALL) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        }
        if (JingleRtpConnection.STATES_SHOWING_ONGOING_CALL.contains(requireRtpConnection().getState())) {
        if (JingleRtpConnection.STATES_SHOWING_ONGOING_CALL.contains(
                requireRtpConnection().getState())) {
            putScreenInCallMode();
        }
        binding.with.setText(getWith().getDisplayName());


@@ 611,7 668,10 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        return false;
    }

    private void initializeWithTerminatedSessionState(final Account account, final Jid with, final JingleConnectionManager.TerminatedRtpSession terminatedRtpSession) {
    private void initializeWithTerminatedSessionState(
            final Account account,
            final Jid with,
            final JingleConnectionManager.TerminatedRtpSession terminatedRtpSession) {
        Log.d(Config.LOGTAG, "initializeWithTerminatedSessionState()");
        if (terminatedRtpSession.state == RtpEndUserState.ENDED) {
            finish();


@@ 628,7 688,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        binding.with.setText(account.getRoster().getContact(with).getDisplayName());
    }

    private void reInitializeActivityWithRunningRtpSession(final Account account, Jid with, String sessionId) {
    private void reInitializeActivityWithRunningRtpSession(
            final Account account, Jid with, String sessionId) {
        runOnUiThread(() -> initializeActivityWithRunningRtpSession(account, with, sessionId));
        resetIntent(account, with, sessionId);
    }


@@ 646,7 707,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        try {
            surfaceViewRenderer.init(requireRtpConnection().getEglBaseContext(), null);
        } catch (final IllegalStateException e) {
            //Log.d(Config.LOGTAG, "SurfaceViewRenderer was already initialized");
            // Log.d(Config.LOGTAG, "SurfaceViewRenderer was already initialized");
        }
        surfaceViewRenderer.setEnableHardwareScaler(true);
    }


@@ 705,9 766,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                setTitle(R.string.rtp_state_security_error);
                break;
            case ENDED:
                throw new IllegalStateException("Activity should have called finishAndReleaseWakeLock();");
                throw new IllegalStateException(
                        "Activity should have called finishAndReleaseWakeLock();");
            default:
                throw new IllegalStateException(String.format("State %s has not been handled in UI", state));
                throw new IllegalStateException(
                        String.format("State %s has not been handled in UI", state));
        }
    }



@@ 729,9 792,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            if (show) {
                binding.contactPhoto.setVisibility(View.VISIBLE);
                if (contact == null) {
                    AvatarWorkerTask.loadAvatar(getWith(), binding.contactPhoto, R.dimen.publish_avatar_size);
                    AvatarWorkerTask.loadAvatar(
                            getWith(), binding.contactPhoto, R.dimen.publish_avatar_size);
                } else {
                    AvatarWorkerTask.loadAvatar(contact, binding.contactPhoto, R.dimen.publish_avatar_size);
                    AvatarWorkerTask.loadAvatar(
                            contact, binding.contactPhoto, R.dimen.publish_avatar_size);
                }
            } else {
                binding.contactPhoto.setVisibility(View.GONE);


@@ 776,12 841,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            this.binding.acceptCall.setImageResource(R.drawable.ic_voicemail_white_24dp);
            this.binding.acceptCall.setVisibility(View.VISIBLE);
        } else if (asList(
                RtpEndUserState.CONNECTIVITY_ERROR,
                RtpEndUserState.CONNECTIVITY_LOST_ERROR,
                RtpEndUserState.APPLICATION_ERROR,
                RtpEndUserState.RETRACTED,
                RtpEndUserState.SECURITY_ERROR
        ).contains(state)) {
                        RtpEndUserState.CONNECTIVITY_ERROR,
                        RtpEndUserState.CONNECTIVITY_LOST_ERROR,
                        RtpEndUserState.APPLICATION_ERROR,
                        RtpEndUserState.RETRACTED,
                        RtpEndUserState.SECURITY_ERROR)
                .contains(state)) {
            this.binding.rejectCall.setContentDescription(getString(R.string.exit));
            this.binding.rejectCall.setOnClickListener(this::exit);
            this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp);


@@ 811,26 876,29 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private void updateInCallButtonConfiguration() {
        updateInCallButtonConfiguration(requireRtpConnection().getEndUserState(), requireRtpConnection().getMedia());
        updateInCallButtonConfiguration(
                requireRtpConnection().getEndUserState(), requireRtpConnection().getMedia());
    }

    @SuppressLint("RestrictedApi")
    private void updateInCallButtonConfiguration(final RtpEndUserState state, final Set<Media> media) {
    private void updateInCallButtonConfiguration(
            final RtpEndUserState state, final Set<Media> media) {
        if (STATES_CONSIDERED_CONNECTED.contains(state) && !isPictureInPicture()) {
            Preconditions.checkArgument(media.size() > 0, "Media must not be empty");
            if (media.contains(Media.VIDEO)) {
                final JingleRtpConnection rtpConnection = requireRtpConnection();
                updateInCallButtonConfigurationVideo(rtpConnection.isVideoEnabled(), rtpConnection.isCameraSwitchable());
                updateInCallButtonConfigurationVideo(
                        rtpConnection.isVideoEnabled(), rtpConnection.isCameraSwitchable());
            } else {
                final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
                updateInCallButtonConfigurationSpeaker(
                        audioManager.getSelectedAudioDevice(),
                        audioManager.getAudioDevices().size()
                );
                        audioManager.getAudioDevices().size());
                this.binding.inCallActionFarRight.setVisibility(View.GONE);
            }
            if (media.contains(Media.AUDIO)) {
                updateInCallButtonConfigurationMicrophone(requireRtpConnection().isMicrophoneEnabled());
                updateInCallButtonConfigurationMicrophone(
                        requireRtpConnection().isMicrophoneEnabled());
            } else {
                this.binding.inCallActionLeft.setVisibility(View.GONE);
            }


@@ 842,10 910,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @SuppressLint("RestrictedApi")
    private void updateInCallButtonConfigurationSpeaker(final AppRTCAudioManager.AudioDevice selectedAudioDevice, final int numberOfChoices) {
    private void updateInCallButtonConfigurationSpeaker(
            final AppRTCAudioManager.AudioDevice selectedAudioDevice, final int numberOfChoices) {
        switch (selectedAudioDevice) {
            case EARPIECE:
                this.binding.inCallActionRight.setImageResource(R.drawable.ic_volume_off_black_24dp);
                this.binding.inCallActionRight.setImageResource(
                        R.drawable.ic_volume_off_black_24dp);
                if (numberOfChoices >= 2) {
                    this.binding.inCallActionRight.setOnClickListener(this::switchToSpeaker);
                } else {


@@ 868,7 938,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                }
                break;
            case BLUETOOTH:
                this.binding.inCallActionRight.setImageResource(R.drawable.ic_bluetooth_audio_black_24dp);
                this.binding.inCallActionRight.setImageResource(
                        R.drawable.ic_bluetooth_audio_black_24dp);
                this.binding.inCallActionRight.setOnClickListener(null);
                this.binding.inCallActionRight.setClickable(false);
                break;


@@ 877,10 948,12 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @SuppressLint("RestrictedApi")
    private void updateInCallButtonConfigurationVideo(final boolean videoEnabled, final boolean isCameraSwitchable) {
    private void updateInCallButtonConfigurationVideo(
            final boolean videoEnabled, final boolean isCameraSwitchable) {
        this.binding.inCallActionRight.setVisibility(View.VISIBLE);
        if (isCameraSwitchable) {
            this.binding.inCallActionFarRight.setImageResource(R.drawable.ic_flip_camera_android_black_24dp);
            this.binding.inCallActionFarRight.setImageResource(
                    R.drawable.ic_flip_camera_android_black_24dp);
            this.binding.inCallActionFarRight.setVisibility(View.VISIBLE);
            this.binding.inCallActionFarRight.setOnClickListener(this::switchCamera);
        } else {


@@ 896,18 969,28 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private void switchCamera(final View view) {
        Futures.addCallback(requireRtpConnection().switchCamera(), new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(@NullableDecl Boolean isFrontCamera) {
                binding.localVideo.setMirror(isFrontCamera);
            }

            @Override
            public void onFailure(@NonNull final Throwable throwable) {
                Log.d(Config.LOGTAG, "could not switch camera", Throwables.getRootCause(throwable));
                Toast.makeText(RtpSessionActivity.this, R.string.could_not_switch_camera, Toast.LENGTH_LONG).show();
            }
        }, MainThreadExecutor.getInstance());
        Futures.addCallback(
                requireRtpConnection().switchCamera(),
                new FutureCallback<Boolean>() {
                    @Override
                    public void onSuccess(@NullableDecl Boolean isFrontCamera) {
                        binding.localVideo.setMirror(isFrontCamera);
                    }

                    @Override
                    public void onFailure(@NonNull final Throwable throwable) {
                        Log.d(
                                Config.LOGTAG,
                                "could not switch camera",
                                Throwables.getRootCause(throwable));
                        Toast.makeText(
                                        RtpSessionActivity.this,
                                        R.string.could_not_switch_camera,
                                        Toast.LENGTH_LONG)
                                .show();
                    }
                },
                MainThreadExecutor.getInstance());
    }

    private void enableVideo(View view) {


@@ 923,7 1006,6 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    private void disableVideo(View view) {
        requireRtpConnection().setVideoEnabled(false);
        updateInCallButtonConfigurationVideo(false, requireRtpConnection().isCameraSwitchable());

    }

    @SuppressLint("RestrictedApi")


@@ 939,7 1021,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private void updateCallDuration() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        if (connection == null || connection.getMedia().contains(Media.VIDEO)) {
            this.binding.duration.setVisibility(View.GONE);
            return;


@@ 947,7 1030,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        if (connection.zeroDuration()) {
            this.binding.duration.setVisibility(View.GONE);
        } else {
            this.binding.duration.setText(TimeFrameUtils.formatElapsedTime(connection.getCallDuration(), false));
            this.binding.duration.setText(
                    TimeFrameUtils.formatElapsedTime(connection.getCallDuration(), false));
            this.binding.duration.setVisibility(View.VISIBLE);
        }
    }


@@ 963,9 1047,9 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                binding.appBarLayout.setVisibility(View.GONE);
                binding.pipPlaceholder.setVisibility(View.VISIBLE);
                if (Arrays.asList(
                        RtpEndUserState.APPLICATION_ERROR,
                        RtpEndUserState.CONNECTIVITY_ERROR,
                        RtpEndUserState.SECURITY_ERROR)
                                RtpEndUserState.APPLICATION_ERROR,
                                RtpEndUserState.CONNECTIVITY_ERROR,
                                RtpEndUserState.SECURITY_ERROR)
                        .contains(state)) {
                    binding.pipWarning.setVisibility(View.VISIBLE);
                    binding.pipWaiting.setVisibility(View.GONE);


@@ 993,7 1077,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        final Optional<VideoTrack> localVideoTrack = getLocalVideoTrack();
        if (localVideoTrack.isPresent() && !isPictureInPicture()) {
            ensureSurfaceViewRendererIsSetup(binding.localVideo);
            //paint local view over remote view
            // paint local view over remote view
            binding.localVideo.setZOrderMediaOverlay(true);
            binding.localVideo.setMirror(requireRtpConnection().isFrontCamera());
            addSink(localVideoTrack.get(), binding.localVideo);


@@ 1006,8 1090,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
            addSink(remoteVideoTrack.get(), binding.remoteVideo);
            binding.remoteVideo.setScalingType(
                    RendererCommon.ScalingType.SCALE_ASPECT_FILL,
                    RendererCommon.ScalingType.SCALE_ASPECT_FIT
            );
                    RendererCommon.ScalingType.SCALE_ASPECT_FIT);
            if (state == RtpEndUserState.CONNECTED) {
                binding.appBarLayout.setVisibility(View.GONE);
                getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);


@@ 1030,7 1113,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private Optional<VideoTrack> getLocalVideoTrack() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        if (connection == null) {
            return Optional.absent();
        }


@@ 1038,7 1122,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private Optional<VideoTrack> getRemoteVideoTrack() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        if (connection == null) {
            return Optional.absent();
        }


@@ 1060,12 1145,16 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private void switchToEarpiece(View view) {
        requireRtpConnection().getAudioManager().setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.EARPIECE);
        requireRtpConnection()
                .getAudioManager()
                .setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.EARPIECE);
        acquireProximityWakeLock();
    }

    private void switchToSpeaker(View view) {
        requireRtpConnection().getAudioManager().setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE);
        requireRtpConnection()
                .getAudioManager()
                .setDefaultAudioDevice(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE);
        releaseProximityWakeLock();
    }



@@ 1089,12 1178,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        final Intent intent = getIntent();
        final Account account = extractAccount(intent);
        final Jid with = Jid.ofEscaped(intent.getStringExtra(EXTRA_WITH));
        final Conversation conversation = xmppConnectionService.findOrCreateConversation(account, with, false, true);
        final Conversation conversation =
                xmppConnectionService.findOrCreateConversation(account, with, false, true);
        final Intent launchIntent = new Intent(this, ConversationsActivity.class);
        launchIntent.setAction(ConversationsActivity.ACTION_VIEW_CONVERSATION);
        launchIntent.putExtra(ConversationsActivity.EXTRA_CONVERSATION, conversation.getUuid());
        launchIntent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        launchIntent.putExtra(ConversationsActivity.EXTRA_POST_INIT_ACTION, ConversationsActivity.POST_ACTION_RECORD_VOICE);
        launchIntent.putExtra(
                ConversationsActivity.EXTRA_POST_INIT_ACTION,
                ConversationsActivity.POST_ACTION_RECORD_VOICE);
        startActivity(launchIntent);
        finish();
    }


@@ 1106,7 1198,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    private JingleRtpConnection requireRtpConnection() {
        final JingleRtpConnection connection = this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        final JingleRtpConnection connection =
                this.rtpConnectionReference != null ? this.rtpConnectionReference.get() : null;
        if (connection == null) {
            throw new IllegalStateException("No RTP connection found");
        }


@@ 1114,12 1207,14 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @Override
    public void onJingleRtpConnectionUpdate(Account account, Jid with, final String sessionId, RtpEndUserState state) {
    public void onJingleRtpConnectionUpdate(
            Account account, Jid with, final String sessionId, RtpEndUserState state) {
        Log.d(Config.LOGTAG, "onJingleRtpConnectionUpdate(" + state + ")");
        if (END_CARD.contains(state)) {
            Log.d(Config.LOGTAG, "end card reached");
            releaseProximityWakeLock();
            runOnUiThread(() -> getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON));
            runOnUiThread(
                    () -> getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON));
        }
        if (with.isBareJid()) {
            updateRtpSessionProposalState(account, with, state);


@@ 1130,7 1225,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                Log.d(Config.LOGTAG, "not reinitializing session");
                return;
            }
            //this happens when going from proposed session to actual session
            // this happens when going from proposed session to actual session
            reInitializeActivityWithRunningRtpSession(account, with, sessionId);
            return;
        }


@@ 1143,14 1238,16 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                finish();
                return;
            }
            runOnUiThread(() -> {
                updateStateDisplay(state, media);
                updateVerifiedShield(verified && STATES_SHOWING_SWITCH_TO_CHAT.contains(state));
                updateButtonConfiguration(state, media);
                updateVideoViews(state);
                updateProfilePicture(state, contact);
                invalidateOptionsMenu();
            });
            runOnUiThread(
                    () -> {
                        updateStateDisplay(state, media);
                        updateVerifiedShield(
                                verified && STATES_SHOWING_SWITCH_TO_CHAT.contains(state));
                        updateButtonConfiguration(state, media);
                        updateVideoViews(state);
                        updateProfilePicture(state, contact);
                        invalidateOptionsMenu();
                    });
            if (END_CARD.contains(state)) {
                final JingleRtpConnection rtpConnection = requireRtpConnection();
                resetIntent(account, with, state, rtpConnection.getMedia());


@@ 1163,8 1260,15 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
    }

    @Override
    public void onAudioDeviceChanged(AppRTCAudioManager.AudioDevice selectedAudioDevice, Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
        Log.d(Config.LOGTAG, "onAudioDeviceChanged in activity: selected:" + selectedAudioDevice + ", available:" + availableAudioDevices);
    public void onAudioDeviceChanged(
            AppRTCAudioManager.AudioDevice selectedAudioDevice,
            Set<AppRTCAudioManager.AudioDevice> availableAudioDevices) {
        Log.d(
                Config.LOGTAG,
                "onAudioDeviceChanged in activity: selected:"
                        + selectedAudioDevice
                        + ", available:"
                        + availableAudioDevices);
        try {
            if (getMedia().contains(Media.VIDEO)) {
                Log.d(Config.LOGTAG, "nothing to do; in video mode");


@@ 1175,10 1279,11 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
                final AppRTCAudioManager audioManager = requireRtpConnection().getAudioManager();
                updateInCallButtonConfigurationSpeaker(
                        audioManager.getSelectedAudioDevice(),
                        audioManager.getAudioDevices().size()
                );
                        audioManager.getAudioDevices().size());
            } else if (END_CARD.contains(endUserState)) {
                Log.d(Config.LOGTAG, "onAudioDeviceChanged() nothing to do because end card has been reached");
                Log.d(
                        Config.LOGTAG,
                        "onAudioDeviceChanged() nothing to do because end card has been reached");
            } else {
                putProximityWakeLockInProperState(selectedAudioDevice);
            }


@@ 1187,20 1292,23 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        }
    }

    private void updateRtpSessionProposalState(final Account account, final Jid with, final RtpEndUserState state) {
    private void updateRtpSessionProposalState(
            final Account account, final Jid with, final RtpEndUserState state) {
        final Intent currentIntent = getIntent();
        final String withExtra = currentIntent == null ? null : currentIntent.getStringExtra(EXTRA_WITH);
        final String withExtra =
                currentIntent == null ? null : currentIntent.getStringExtra(EXTRA_WITH);
        if (withExtra == null) {
            return;
        }
        if (Jid.ofEscaped(withExtra).asBareJid().equals(with)) {
            runOnUiThread(() -> {
                updateVerifiedShield(false);
                updateStateDisplay(state);
                updateButtonConfiguration(state);
                updateProfilePicture(state);
                invalidateOptionsMenu();
            });
            runOnUiThread(
                    () -> {
                        updateVerifiedShield(false);
                        updateStateDisplay(state);
                        updateButtonConfiguration(state);
                        updateProfilePicture(state);
                        invalidateOptionsMenu();
                    });
            resetIntent(account, with, state, actionToMedia(currentIntent.getAction()));
        }
    }


@@ 1211,16 1319,22 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
        setIntent(intent);
    }

    private void resetIntent(final Account account, Jid with, final RtpEndUserState state, final Set<Media> media) {
    private void resetIntent(
            final Account account, Jid with, final RtpEndUserState state, final Set<Media> media) {
        final Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.putExtra(EXTRA_ACCOUNT, account.getJid().toEscapedString());
        if (account.getRoster().getContact(with).getPresences().anySupport(Namespace.JINGLE_MESSAGE)) {
        if (account.getRoster()
                .getContact(with)
                .getPresences()
                .anySupport(Namespace.JINGLE_MESSAGE)) {
            intent.putExtra(EXTRA_WITH, with.asBareJid().toEscapedString());
        } else {
            intent.putExtra(EXTRA_WITH, with.toEscapedString());
        }
        intent.putExtra(EXTRA_LAST_REPORTED_STATE, state.toString());
        intent.putExtra(EXTRA_LAST_ACTION, media.contains(Media.VIDEO) ? ACTION_MAKE_VIDEO_CALL : ACTION_MAKE_VOICE_CALL);
        intent.putExtra(
                EXTRA_LAST_ACTION,
                media.contains(Media.VIDEO) ? ACTION_MAKE_VIDEO_CALL : ACTION_MAKE_VOICE_CALL);
        setIntent(intent);
    }