Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95d5587d authored by Hall Liu's avatar Hall Liu
Browse files

Introduce APIs for RTT calls (part 1)

Add signaling methods and data pipes for handling real-time text during
a call.

Change-Id: I876827c448252c5f786d7a4919c47891acb03877
Test: manual, through telecom testapps
parent 975be6c0
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -36581,9 +36581,11 @@ package android.telecom {
    method public android.telecom.Call.Details getDetails();
    method public android.telecom.Call getParent();
    method public java.lang.String getRemainingPostDialSequence();
    method public android.telecom.Call.RttCall getRttCall();
    method public int getState();
    method public android.telecom.InCallService.VideoCall getVideoCall();
    method public void hold();
    method public boolean isRttActive();
    method public void mergeConference();
    method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
    method public void playDtmfTone(char);
@@ -36595,9 +36597,12 @@ package android.telecom {
    method public void reject(boolean, java.lang.String);
    method public final void removeExtras(java.util.List<java.lang.String>);
    method public final void removeExtras(java.lang.String...);
    method public void respondToRttRequest(int, boolean);
    method public void sendCallEvent(java.lang.String, android.os.Bundle);
    method public void sendRttRequest();
    method public void splitFromConference();
    method public void stopDtmfTone();
    method public void stopRtt();
    method public void swapConference();
    method public void unhold();
    method public void unregisterCallback(android.telecom.Call.Callback);
@@ -36624,6 +36629,9 @@ package android.telecom {
    method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
    method public void onParentChanged(android.telecom.Call, android.telecom.Call);
    method public void onPostDialWait(android.telecom.Call, java.lang.String);
    method public void onRttModeChanged(android.telecom.Call, int);
    method public void onRttRequest(android.telecom.Call, int);
    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
    method public void onStateChanged(android.telecom.Call, int);
    method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
  }
@@ -36677,6 +36685,19 @@ package android.telecom {
    field public static final int PROPERTY_WIFI = 8; // 0x8
  }
  public static final class Call.RttCall {
    method public int getRttAudioMode();
    method public java.lang.String read();
    method public void setRttMode(int);
    method public void write(java.lang.String) throws java.io.IOException;
    field public static final int RTT_MODE_FULL = 1; // 0x1
    field public static final int RTT_MODE_HCO = 2; // 0x2
    field public static final int RTT_MODE_VCO = 3; // 0x3
  }
  public static abstract class Call.RttCall.RttAudioMode implements java.lang.annotation.Annotation {
  }
  public final class CallAudioState implements android.os.Parcelable {
    ctor public CallAudioState(boolean, int, int);
    method public static java.lang.String audioRouteToString(int);
@@ -37048,6 +37069,7 @@ package android.telecom {
    field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
    field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
    field public static final int CAPABILITY_RTT = 4096; // 0x1000
    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -37260,6 +37282,7 @@ package android.telecom {
    field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
    field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
    field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
    field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
+23 −0
Original line number Diff line number Diff line
@@ -39548,9 +39548,11 @@ package android.telecom {
    method public android.telecom.Call.Details getDetails();
    method public android.telecom.Call getParent();
    method public java.lang.String getRemainingPostDialSequence();
    method public android.telecom.Call.RttCall getRttCall();
    method public int getState();
    method public android.telecom.InCallService.VideoCall getVideoCall();
    method public void hold();
    method public boolean isRttActive();
    method public void mergeConference();
    method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
    method public void playDtmfTone(char);
@@ -39563,9 +39565,12 @@ package android.telecom {
    method public final void removeExtras(java.util.List<java.lang.String>);
    method public final void removeExtras(java.lang.String...);
    method public deprecated void removeListener(android.telecom.Call.Listener);
    method public void respondToRttRequest(int, boolean);
    method public void sendCallEvent(java.lang.String, android.os.Bundle);
    method public void sendRttRequest();
    method public void splitFromConference();
    method public void stopDtmfTone();
    method public void stopRtt();
    method public void swapConference();
    method public void unhold();
    method public void unregisterCallback(android.telecom.Call.Callback);
@@ -39593,6 +39598,9 @@ package android.telecom {
    method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
    method public void onParentChanged(android.telecom.Call, android.telecom.Call);
    method public void onPostDialWait(android.telecom.Call, java.lang.String);
    method public void onRttModeChanged(android.telecom.Call, int);
    method public void onRttRequest(android.telecom.Call, int);
    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
    method public void onStateChanged(android.telecom.Call, int);
    method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
  }
@@ -39650,6 +39658,19 @@ package android.telecom {
    ctor public Call.Listener();
  }
  public static final class Call.RttCall {
    method public int getRttAudioMode();
    method public java.lang.String read();
    method public void setRttMode(int);
    method public void write(java.lang.String) throws java.io.IOException;
    field public static final int RTT_MODE_FULL = 1; // 0x1
    field public static final int RTT_MODE_HCO = 2; // 0x2
    field public static final int RTT_MODE_VCO = 3; // 0x3
  }
  public static abstract class Call.RttCall.RttAudioMode implements java.lang.annotation.Annotation {
  }
  public final class CallAudioState implements android.os.Parcelable {
    ctor public CallAudioState(boolean, int, int);
    method public static java.lang.String audioRouteToString(int);
@@ -40152,6 +40173,7 @@ package android.telecom {
    field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
    field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
    field public static final int CAPABILITY_RTT = 4096; // 0x1000
    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -40428,6 +40450,7 @@ package android.telecom {
    field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
    field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
    field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
    field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
+23 −0
Original line number Diff line number Diff line
@@ -36663,9 +36663,11 @@ package android.telecom {
    method public android.telecom.Call.Details getDetails();
    method public android.telecom.Call getParent();
    method public java.lang.String getRemainingPostDialSequence();
    method public android.telecom.Call.RttCall getRttCall();
    method public int getState();
    method public android.telecom.InCallService.VideoCall getVideoCall();
    method public void hold();
    method public boolean isRttActive();
    method public void mergeConference();
    method public void phoneAccountSelected(android.telecom.PhoneAccountHandle, boolean);
    method public void playDtmfTone(char);
@@ -36677,9 +36679,12 @@ package android.telecom {
    method public void reject(boolean, java.lang.String);
    method public final void removeExtras(java.util.List<java.lang.String>);
    method public final void removeExtras(java.lang.String...);
    method public void respondToRttRequest(int, boolean);
    method public void sendCallEvent(java.lang.String, android.os.Bundle);
    method public void sendRttRequest();
    method public void splitFromConference();
    method public void stopDtmfTone();
    method public void stopRtt();
    method public void swapConference();
    method public void unhold();
    method public void unregisterCallback(android.telecom.Call.Callback);
@@ -36706,6 +36711,9 @@ package android.telecom {
    method public void onDetailsChanged(android.telecom.Call, android.telecom.Call.Details);
    method public void onParentChanged(android.telecom.Call, android.telecom.Call);
    method public void onPostDialWait(android.telecom.Call, java.lang.String);
    method public void onRttModeChanged(android.telecom.Call, int);
    method public void onRttRequest(android.telecom.Call, int);
    method public void onRttStatusChanged(android.telecom.Call, boolean, android.telecom.Call.RttCall);
    method public void onStateChanged(android.telecom.Call, int);
    method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
  }
@@ -36759,6 +36767,19 @@ package android.telecom {
    field public static final int PROPERTY_WIFI = 8; // 0x8
  }
  public static final class Call.RttCall {
    method public int getRttAudioMode();
    method public java.lang.String read();
    method public void setRttMode(int);
    method public void write(java.lang.String) throws java.io.IOException;
    field public static final int RTT_MODE_FULL = 1; // 0x1
    field public static final int RTT_MODE_HCO = 2; // 0x2
    field public static final int RTT_MODE_VCO = 3; // 0x3
  }
  public static abstract class Call.RttCall.RttAudioMode implements java.lang.annotation.Annotation {
  }
  public final class CallAudioState implements android.os.Parcelable {
    ctor public CallAudioState(boolean, int, int);
    method public static java.lang.String audioRouteToString(int);
@@ -37130,6 +37151,7 @@ package android.telecom {
    field public static final int CAPABILITY_CALL_SUBJECT = 64; // 0x40
    field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
    field public static final int CAPABILITY_RTT = 4096; // 0x1000
    field public static final int CAPABILITY_SELF_MANAGED = 2048; // 0x800
    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
    field public static final int CAPABILITY_SUPPORTS_VIDEO_CALLING = 1024; // 0x400
@@ -37342,6 +37364,7 @@ package android.telecom {
    field public static final java.lang.String EXTRA_NOTIFICATION_PHONE_NUMBER = "android.telecom.extra.NOTIFICATION_PHONE_NUMBER";
    field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_RTT = "android.telecom.extra.START_CALL_WITH_RTT";
    field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
    field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
+258 −0
Original line number Diff line number Diff line
@@ -16,12 +16,21 @@

package android.telecom;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.String;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -828,6 +837,142 @@ public final class Call {
         * @param extras Extras associated with the connection event.
         */
        public void onConnectionEvent(Call call, String event, Bundle extras) {}

        /**
         * Invoked when the RTT mode changes for this call.
         * @param call The call whose RTT mode has changed.
         * @param mode the new RTT mode, one of
         * {@link RttCall#RTT_MODE_FULL}, {@link RttCall#RTT_MODE_HCO},
         *             or {@link RttCall#RTT_MODE_VCO}
         */
        public void onRttModeChanged(Call call, int mode) {}

        /**
         * Invoked when the call's RTT status changes, either from off to on or from on to off.
         * @param call The call whose RTT status has changed.
         * @param enabled whether RTT is now enabled or disabled
         * @param rttCall the {@link RttCall} object to use for reading and writing if RTT is now
         *                on, null otherwise.
         */
        public void onRttStatusChanged(Call call, boolean enabled, RttCall rttCall) {}

        /**
         * Invoked when the remote end of the connection has requested that an RTT communication
         * channel be opened. A response to this should be sent via {@link #respondToRttRequest}
         * with the same ID that this method is invoked with.
         * @param call The call which the RTT request was placed on
         * @param id The ID of the request.
         */
        public void onRttRequest(Call call, int id) {}
    }

    /**
     * A class that holds the state that describes the state of the RTT channel to the remote
     * party, if it is active.
     */
    public static final class RttCall {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({RTT_MODE_INVALID, RTT_MODE_FULL, RTT_MODE_HCO, RTT_MODE_VCO})
        public @interface RttAudioMode {}

        /**
         * For metrics use. Default value in the proto.
         * @hide
         */
        public static final int RTT_MODE_INVALID = 0;

        /**
         * Indicates that there should be a bidirectional audio stream between the two parties
         * on the call.
         */
        public static final int RTT_MODE_FULL = 1;

        /**
         * Indicates that the local user should be able to hear the audio stream from the remote
         * user, but not vice versa. Equivalent to muting the microphone.
         */
        public static final int RTT_MODE_HCO = 2;

        /**
         * Indicates that the remote user should be able to hear the audio stream from the local
         * user, but not vice versa. Equivalent to setting the volume to zero.
         */
        public static final int RTT_MODE_VCO = 3;

        private static final int READ_BUFFER_SIZE = 1000;

        private InputStreamReader mReceiveStream;
        private OutputStreamWriter mTransmitStream;
        private int mRttMode;
        private final InCallAdapter mInCallAdapter;
        private char[] mReadBuffer = new char[READ_BUFFER_SIZE];

        /**
         * @hide
         */
        public RttCall(InputStreamReader receiveStream, OutputStreamWriter transmitStream,
                int mode, InCallAdapter inCallAdapter) {
            mReceiveStream = receiveStream;
            mTransmitStream = transmitStream;
            mRttMode = mode;
            mInCallAdapter = inCallAdapter;
        }

        /**
         * Returns the current RTT audio mode.
         * @return Current RTT audio mode. One of {@link #RTT_MODE_FULL}, {@link #RTT_MODE_VCO}, or
         * {@link #RTT_MODE_HCO}.
         */
        public int getRttAudioMode() {
            return mRttMode;
        }

        /**
         * Sets the RTT audio mode. The requested mode change will be communicated through
         * {@link Callback#onRttModeChanged(Call, int)}.
         * @param mode The desired RTT audio mode, one of {@link #RTT_MODE_FULL},
         * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}.
         */
        public void setRttMode(@RttAudioMode int mode) {
            mInCallAdapter.setRttMode(mode);
        }

        /**
         * Writes the string {@param input} into the outgoing text stream for this RTT call. Since
         * RTT transmits text in real-time, this method should be called once for each character
         * the user enters into the device.
         *
         * This method is not thread-safe -- calling it from multiple threads simultaneously may
         * lead to interleaved text.
         * @param input The message to send to the remote user.
         */
        public void write(String input) throws IOException {
            mTransmitStream.write(input);
            mTransmitStream.flush();
        }

        /**
         * Reads a string from the remote user, blocking if there is no data available. Returns
         * {@code null} if the RTT conversation has been terminated and there is no further data
         * to read.
         *
         * This method is not thread-safe -- calling it from multiple threads simultaneously may
         * lead to interleaved text.
         * @return A string containing text sent by the remote user, or {@code null} if the
         * conversation has been terminated or if there was an error while reading.
         */
        public String read() {
            try {
                int numRead = mReceiveStream.read(mReadBuffer, 0, READ_BUFFER_SIZE);
                if (numRead < 0) {
                    return null;
                }
                return new String(mReadBuffer, 0, numRead);
            } catch (IOException e) {
                Log.w(this, "Exception encountered when reading from InputStreamReader: %s", e);
                return null;
            }
        }
    }

    /**
@@ -856,6 +1001,7 @@ public final class Call {
    private String mCallingPackage;
    private String mRemainingPostDialSequence;
    private VideoCallImpl mVideoCallImpl;
    private RttCall mRttCall;
    private Details mDetails;
    private Bundle mExtras;

@@ -1053,6 +1199,34 @@ public final class Call {
        mInCallAdapter.sendCallEvent(mTelecomCallId, event, extras);
    }

    /**
     * Sends an RTT upgrade request to the remote end of the connection. Success is not
     * guaranteed, and notification of success will be via the
     * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
     */
    public void sendRttRequest() {
        mInCallAdapter.sendRttRequest();
    }

    /**
     * Responds to an RTT request received via the {@link Callback#onRttRequest(Call, int)} )}
     * callback.
     * The ID used here should be the same as the ID that was received via the callback.
     * @param id The request ID received via {@link Callback#onRttRequest(Call, int)}
     * @param accept {@code true} if the RTT request should be accepted, {@code false} otherwise.
     */
    public void respondToRttRequest(int id, boolean accept) {
        mInCallAdapter.respondToRttRequest(id, accept);
    }

    /**
     * Terminate the RTT session on this call. The resulting state change will be notified via
     * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback.
     */
    public void stopRtt() {
        mInCallAdapter.stopRtt();
    }

    /**
     * Adds some extras to this {@link Call}.  Existing keys are replaced and new ones are
     * added.
@@ -1232,6 +1406,23 @@ public final class Call {
        return mDetails;
    }

    /**
     * Returns this call's RttCall object. The {@link RttCall} instance is used to send and
     * receive RTT text data, as well as to change the RTT mode.
     * @return A {@link Call.RttCall}. {@code null} if there is no active RTT connection.
     */
    public @Nullable RttCall getRttCall() {
        return mRttCall;
    }

    /**
     * Returns whether this call has an active RTT connection.
     * @return true if there is a connection, false otherwise.
     */
    public boolean isRttActive() {
        return mRttCall != null;
    }

    /**
     * Registers a callback to this {@code Call}.
     *
@@ -1426,6 +1617,32 @@ public final class Call {
            fireConferenceableCallsChanged();
        }

        boolean isRttChanged = false;
        boolean rttModeChanged = false;
        if (parcelableCall.getParcelableRttCall() != null && parcelableCall.getIsRttCallChanged()) {
            ParcelableRttCall parcelableRttCall = parcelableCall.getParcelableRttCall();
            InputStreamReader receiveStream = new InputStreamReader(
                    new ParcelFileDescriptor.AutoCloseInputStream(
                            parcelableRttCall.getReceiveStream()),
                    StandardCharsets.UTF_8);
            OutputStreamWriter transmitStream = new OutputStreamWriter(
                    new ParcelFileDescriptor.AutoCloseOutputStream(
                            parcelableRttCall.getTransmitStream()),
                    StandardCharsets.UTF_8);
            RttCall newRttCall = new Call.RttCall(
                    receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter);
            if (mRttCall == null) {
                isRttChanged = true;
            } else if (mRttCall.getRttAudioMode() != newRttCall.getRttAudioMode()) {
                rttModeChanged = true;
            }
            mRttCall = newRttCall;
        } else if (mRttCall != null && parcelableCall.getParcelableRttCall() == null
                && parcelableCall.getIsRttCallChanged()) {
            isRttChanged = true;
            mRttCall = null;
        }

        // Now we fire updates, ensuring that any client who listens to any of these notifications
        // gets the most up-to-date state.

@@ -1447,6 +1664,12 @@ public final class Call {
        if (childrenChanged) {
            fireChildrenChanged(getChildren());
        }
        if (isRttChanged) {
            fireOnIsRttChanged(mRttCall != null, mRttCall);
        }
        if (rttModeChanged) {
            fireOnRttModeChanged(mRttCall.getRttAudioMode());
        }

        // If we have transitioned to DISCONNECTED, that means we need to notify clients and
        // remove ourselves from the Phone. Note that we do this after completing all state updates
@@ -1477,6 +1700,15 @@ public final class Call {
        fireOnConnectionEvent(event, extras);
    }

    /** {@hide} */
    final void internalOnRttUpgradeRequest(final int requestId) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttRequest(call, requestId));
        }
    }

    private void fireStateChanged(final int newState) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
@@ -1644,6 +1876,32 @@ public final class Call {
        }
    }

    /**
     * Notifies listeners of an RTT on/off change
     *
     * @param enabled True if RTT is now enabled, false otherwise
     */
    private void fireOnIsRttChanged(final boolean enabled, final RttCall rttCall) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttStatusChanged(call, enabled, rttCall));
        }
    }

    /**
     * Notifies listeners of a RTT mode change
     *
     * @param mode The new RTT mode
     */
    private void fireOnRttModeChanged(final int mode) {
        for (CallbackRecord<Callback> record : mCallbackRecords) {
            final Call call = this;
            final Callback callback = record.getCallback();
            record.getHandler().post(() -> callback.onRttModeChanged(call, mode));
        }
    }

    /**
     * Determines if two bundles are equal.
     *
+70 −1

File changed.

Preview size limit exceeded, changes collapsed.

Loading