diff options
author | 2017-01-25 17:12:49 -0800 | |
---|---|---|
committer | 2017-02-21 15:27:25 -0800 | |
commit | 95d5587d0aad9dfd49f798408f4212f95ce68fc7 (patch) | |
tree | 3ab3c4797dfb6ba2d7e7c40c2f5da8a5701cdb52 | |
parent | 975be6c065b7b6ad256fae945551005156412073 (diff) |
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
-rw-r--r-- | api/current.txt | 23 | ||||
-rw-r--r-- | api/system-current.txt | 23 | ||||
-rw-r--r-- | api/test-current.txt | 23 | ||||
-rw-r--r-- | telecomm/java/android/telecom/Call.java | 258 | ||||
-rw-r--r-- | telecomm/java/android/telecom/Connection.java | 71 | ||||
-rw-r--r-- | telecomm/java/android/telecom/ConnectionRequest.java | 187 | ||||
-rw-r--r-- | telecomm/java/android/telecom/InCallAdapter.java | 46 | ||||
-rw-r--r-- | telecomm/java/android/telecom/InCallService.java | 12 | ||||
-rw-r--r-- | telecomm/java/android/telecom/ParcelableCall.java | 24 | ||||
-rw-r--r-- | telecomm/java/android/telecom/ParcelableRttCall.aidl | 22 | ||||
-rw-r--r-- | telecomm/java/android/telecom/ParcelableRttCall.java | 88 | ||||
-rw-r--r-- | telecomm/java/android/telecom/Phone.java | 7 | ||||
-rw-r--r-- | telecomm/java/android/telecom/PhoneAccount.java | 12 | ||||
-rw-r--r-- | telecomm/java/android/telecom/RemoteConnectionService.java | 13 | ||||
-rw-r--r-- | telecomm/java/android/telecom/TelecomManager.java | 8 | ||||
-rw-r--r-- | telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl | 8 | ||||
-rw-r--r-- | telecomm/java/com/android/internal/telecom/IInCallService.aidl | 2 |
17 files changed, 817 insertions, 10 deletions
diff --git a/api/current.txt b/api/current.txt index 1173dda9af21..cce3fa7d9712 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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"; diff --git a/api/system-current.txt b/api/system-current.txt index 4feda6c4f3fc..0676d0d9841b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -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"; diff --git a/api/test-current.txt b/api/test-current.txt index dfc9bb1ab130..d3755ea249cc 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -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"; diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index c69b7c2771ac..d67a0d62cb70 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -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; @@ -1054,6 +1200,34 @@ public final class Call { } /** + * 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. * <p> @@ -1233,6 +1407,23 @@ public final class Call { } /** + * 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}. * * @param callback A {@code Callback}. @@ -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; @@ -1645,6 +1877,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. * * @param bundle The original bundle. diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index b7391b4c57ac..3e690b997b29 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -31,10 +31,14 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.ArraySet; import android.view.Surface; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -385,8 +389,14 @@ public abstract class Connection extends Conferenceable { */ public static final int PROPERTY_SELF_MANAGED = 1<<7; + /** + * When set, indicates that a connection has an active RTT session associated with it. + * @hide + */ + public static final int PROPERTY_IS_RTT = 1 << 8; + //********************************************************************************************** - // Next PROPERTY value: 1<<8 + // Next PROPERTY value: 1<<9 //********************************************************************************************** /** @@ -757,6 +767,65 @@ public abstract class Connection extends Conferenceable { } /** + * Provides methods to read and write RTT data to/from the in-call app. + * @hide + */ + public static final class RttTextStream { + private static final int READ_BUFFER_SIZE = 1000; + private final InputStreamReader mPipeFromInCall; + private final OutputStreamWriter mPipeToInCall; + private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; + + /** + * @hide + */ + public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) { + mPipeFromInCall = new InputStreamReader( + new ParcelFileDescriptor.AutoCloseInputStream(fromInCall)); + mPipeToInCall = new OutputStreamWriter( + new ParcelFileDescriptor.AutoCloseOutputStream(toInCall)); + } + + /** + * Writes the string {@param input} into the text stream to the UI for this RTT call. Since + * RTT transmits text in real-time, this method should be called as often as text snippets + * are received from the remote user, even if it is only one character. + * + * 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 in-call app. + */ + public void write(String input) throws IOException { + mPipeToInCall.write(input); + mPipeToInCall.flush(); + } + + + /** + * Reads a string from the in-call app, 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 entered by the user, or {@code null} if the + * conversation has been terminated or if there was an error while reading. + */ + public String read() { + try { + int numRead = mPipeFromInCall.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; + } + } + } + + /** * Provides a means of controlling the video session associated with a {@link Connection}. * <p> * Implementations create a custom subclass of {@link VideoProvider} and the diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java index 23434624bf87..054de4c56138 100644 --- a/telecomm/java/android/telecom/ConnectionRequest.java +++ b/telecomm/java/android/telecom/ConnectionRequest.java @@ -19,6 +19,7 @@ package android.telecom; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; +import android.os.ParcelFileDescriptor; import android.os.Parcelable; /** @@ -27,13 +28,121 @@ import android.os.Parcelable; */ public final class ConnectionRequest implements Parcelable { - // TODO: Token to limit recursive invocations + /** + * Builder class for {@link ConnectionRequest} + * @hide + */ + public static final class Builder { + private PhoneAccountHandle mAccountHandle; + private Uri mAddress; + private Bundle mExtras; + private int mVideoState = VideoProfile.STATE_AUDIO_ONLY; + private String mTelecomCallId; + private boolean mShouldShowIncomingCallUi = false; + private ParcelFileDescriptor mRttPipeToInCall; + private ParcelFileDescriptor mRttPipeFromInCall; + + public Builder() { } + + /** + * Sets the phone account handle for the resulting {@link ConnectionRequest} + * @param accountHandle The accountHandle which should be used to place the call. + */ + public Builder setAccountHandle(PhoneAccountHandle accountHandle) { + this.mAccountHandle = accountHandle; + return this; + } + + /** + * Sets the address for the resulting {@link ConnectionRequest} + * @param address The address(e.g., phone number) to which the {@link Connection} is to + * connect. + */ + public Builder setAddress(Uri address) { + this.mAddress = address; + return this; + } + + /** + * Sets the extras bundle for the resulting {@link ConnectionRequest} + * @param extras Application-specific extra data. + */ + public Builder setExtras(Bundle extras) { + this.mExtras = extras; + return this; + } + + /** + * Sets the video state for the resulting {@link ConnectionRequest} + * @param videoState Determines the video state for the connection. + */ + public Builder setVideoState(int videoState) { + this.mVideoState = videoState; + return this; + } + + /** + * Sets the Telecom call ID for the resulting {@link ConnectionRequest} + * @param telecomCallId The telecom call ID. + */ + public Builder setTelecomCallId(String telecomCallId) { + this.mTelecomCallId = telecomCallId; + return this; + } + + /** + * Sets shouldShowIncomingUi for the resulting {@link ConnectionRequest} + * @param shouldShowIncomingCallUi For a self-managed {@link ConnectionService}, will be + * {@code true} if the {@link ConnectionService} should show + * its own incoming call UI for an incoming call. When + * {@code false}, Telecom shows the incoming call UI. + */ + public Builder setShouldShowIncomingCallUi(boolean shouldShowIncomingCallUi) { + this.mShouldShowIncomingCallUi = shouldShowIncomingCallUi; + return this; + } + + /** + * Sets the RTT pipe for transferring text into the {@link ConnectionService} for the + * resulting {@link ConnectionRequest} + * @param rttPipeFromInCall The data pipe to read from. + */ + public Builder setRttPipeFromInCall(ParcelFileDescriptor rttPipeFromInCall) { + this.mRttPipeFromInCall = rttPipeFromInCall; + return this; + } + + /** + * Sets the RTT pipe for transferring text out of {@link ConnectionService} for the + * resulting {@link ConnectionRequest} + * @param rttPipeToInCall The data pipe to write to. + */ + public Builder setRttPipeToInCall(ParcelFileDescriptor rttPipeToInCall) { + this.mRttPipeToInCall = rttPipeToInCall; + return this; + } + + public ConnectionRequest build() { + return new ConnectionRequest( + mAccountHandle, + mAddress, + mExtras, + mVideoState, + mTelecomCallId, + mShouldShowIncomingCallUi, + mRttPipeFromInCall, + mRttPipeToInCall); + } + } + private final PhoneAccountHandle mAccountHandle; private final Uri mAddress; private final Bundle mExtras; private final int mVideoState; private final String mTelecomCallId; private final boolean mShouldShowIncomingCallUi; + private final ParcelFileDescriptor mRttPipeToInCall; + private final ParcelFileDescriptor mRttPipeFromInCall; /** * @param accountHandle The accountHandle which should be used to place the call. @@ -44,7 +153,7 @@ public final class ConnectionRequest implements Parcelable { PhoneAccountHandle accountHandle, Uri handle, Bundle extras) { - this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false); + this(accountHandle, handle, extras, VideoProfile.STATE_AUDIO_ONLY, null, false, null, null); } /** @@ -58,7 +167,7 @@ public final class ConnectionRequest implements Parcelable { Uri handle, Bundle extras, int videoState) { - this(accountHandle, handle, extras, videoState, null, false); + this(accountHandle, handle, extras, videoState, null, false, null, null); } /** @@ -80,12 +189,27 @@ public final class ConnectionRequest implements Parcelable { int videoState, String telecomCallId, boolean shouldShowIncomingCallUi) { + this(accountHandle, handle, extras, videoState, telecomCallId, + shouldShowIncomingCallUi, null, null); + } + + private ConnectionRequest( + PhoneAccountHandle accountHandle, + Uri handle, + Bundle extras, + int videoState, + String telecomCallId, + boolean shouldShowIncomingCallUi, + ParcelFileDescriptor rttPipeFromInCall, + ParcelFileDescriptor rttPipeToInCall) { mAccountHandle = accountHandle; mAddress = handle; mExtras = extras; mVideoState = videoState; mTelecomCallId = telecomCallId; mShouldShowIncomingCallUi = shouldShowIncomingCallUi; + mRttPipeFromInCall = rttPipeFromInCall; + mRttPipeToInCall = rttPipeToInCall; } private ConnectionRequest(Parcel in) { @@ -95,6 +219,8 @@ public final class ConnectionRequest implements Parcelable { mVideoState = in.readInt(); mTelecomCallId = in.readString(); mShouldShowIncomingCallUi = in.readInt() == 1; + mRttPipeFromInCall = in.readParcelable(getClass().getClassLoader()); + mRttPipeToInCall = in.readParcelable(getClass().getClassLoader()); } /** @@ -149,6 +275,59 @@ public final class ConnectionRequest implements Parcelable { return mShouldShowIncomingCallUi; } + /** + * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the connection + * service to the in-call UI. In order to obtain an + * {@link java.io.InputStream} from this {@link ParcelFileDescriptor}, use + * {@link android.os.ParcelFileDescriptor.AutoCloseInputStream}. + * Only text data encoded using UTF-8 should be written into this {@link ParcelFileDescriptor}. + * @return The {@link ParcelFileDescriptor} that should be used for communication. + * Do not un-hide -- only for use by Telephony + * @hide + */ + public ParcelFileDescriptor getRttPipeToInCall() { + return mRttPipeToInCall; + } + + /** + * Gets the {@link ParcelFileDescriptor} that is used to send RTT text from the in-call UI to + * the connection service. In order to obtain an + * {@link java.io.OutputStream} from this {@link ParcelFileDescriptor}, use + * {@link android.os.ParcelFileDescriptor.AutoCloseOutputStream}. + * The contents of this {@link ParcelFileDescriptor} will consist solely of text encoded in + * UTF-8. + * @return The {@link ParcelFileDescriptor} that should be used for communication + * Do not un-hide -- only for use by Telephony + * @hide + */ + public ParcelFileDescriptor getRttPipeFromInCall() { + return mRttPipeFromInCall; + } + + /** + * Gets the {@link android.telecom.Connection.RttTextStream} object that should be used to + * send and receive RTT text to/from the in-call app. + * @return An instance of {@link android.telecom.Connection.RttTextStream}, or {@code null} + * if this connection request is not requesting an RTT session upon connection establishment. + * @hide + */ + public Connection.RttTextStream getRttTextStream() { + if (isRequestingRtt()) { + return new Connection.RttTextStream(mRttPipeToInCall, mRttPipeFromInCall); + } else { + return null; + } + } + + /** + * Convenience method for determining whether the ConnectionRequest is requesting an RTT session + * @return {@code true} if RTT is requested, {@code false} otherwise. + * @hide + */ + public boolean isRequestingRtt() { + return mRttPipeFromInCall != null && mRttPipeToInCall != null; + } + @Override public String toString() { return String.format("ConnectionRequest %s %s", @@ -186,5 +365,7 @@ public final class ConnectionRequest implements Parcelable { destination.writeInt(mVideoState); destination.writeString(mTelecomCallId); destination.writeInt(mShouldShowIncomingCallUi ? 1 : 0); + destination.writeParcelable(mRttPipeFromInCall, 0); + destination.writeParcelable(mRttPipeToInCall, 0); } } diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index 3f270d9c5829..d640b1dd6022 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -34,7 +34,7 @@ import java.util.List; * <p> * The adapter will stop functioning when there are no more calls. * - * {@hide} + * @hide */ public final class InCallAdapter { private final IInCallAdapter mAdapter; @@ -375,4 +375,48 @@ public final class InCallAdapter { } catch (RemoteException ignored) { } } + + /** + * Sends an RTT upgrade request to the remote end of the connection. + */ + public void sendRttRequest() { + try { + mAdapter.sendRttRequest(); + } catch (RemoteException ignored) { + } + } + + /** + * Responds to an RTT upgrade request initiated from the remote end. + * + * @param id the ID of the request as specified by Telecom + * @param accept Whether the request should be accepted. + */ + public void respondToRttRequest(int id, boolean accept) { + try { + mAdapter.respondToRttRequest(id, accept); + } catch (RemoteException ignored) { + } + } + + /** + * Instructs Telecom to shut down the RTT communication channel. + */ + public void stopRtt() { + try { + mAdapter.stopRtt(); + } catch (RemoteException ignored) { + } + } + + /** + * Sets the RTT audio mode. + * @param mode the desired RTT audio mode + */ + public void setRttMode(int mode) { + try { + mAdapter.setRttMode(mode); + } catch (RemoteException ignored) { + } + } } diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 5d68aaeda988..4bc64c05bfee 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -76,6 +76,7 @@ public abstract class InCallService extends Service { private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7; private static final int MSG_SILENCE_RINGER = 8; private static final int MSG_ON_CONNECTION_EVENT = 9; + private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10; /** Default Handler used to consolidate binder method calls onto a single thread. */ private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -133,6 +134,12 @@ public abstract class InCallService extends Service { } break; } + case MSG_ON_RTT_UPGRADE_REQUEST: { + String callId = (String) msg.obj; + int requestId = msg.arg1; + mPhone.internalOnRttUpgradeRequest(callId, requestId); + break; + } default: break; } @@ -198,6 +205,11 @@ public abstract class InCallService extends Service { args.arg3 = extras; mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget(); } + + @Override + public void onRttUpgradeRequest(String callId, int id) { + mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget(); + } } private Phone.Listener mPhoneListener = new Phone.Listener() { diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index a3fce9ca6709..975aa5a332ca 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -50,6 +50,8 @@ public final class ParcelableCall implements Parcelable { private final boolean mIsVideoCallProviderChanged; private final IVideoProvider mVideoCallProvider; private VideoCallImpl mVideoCall; + private final boolean mIsRttCallChanged; + private final ParcelableRttCall mRttCall; private final String mParentCallId; private final List<String> mChildCallIds; private final StatusHints mStatusHints; @@ -75,6 +77,8 @@ public final class ParcelableCall implements Parcelable { PhoneAccountHandle accountHandle, boolean isVideoCallProviderChanged, IVideoProvider videoCallProvider, + boolean isRttCallChanged, + ParcelableRttCall rttCall, String parentCallId, List<String> childCallIds, StatusHints statusHints, @@ -98,6 +102,8 @@ public final class ParcelableCall implements Parcelable { mAccountHandle = accountHandle; mIsVideoCallProviderChanged = isVideoCallProviderChanged; mVideoCallProvider = videoCallProvider; + mIsRttCallChanged = isRttCallChanged; + mRttCall = rttCall; mParentCallId = parentCallId; mChildCallIds = childCallIds; mStatusHints = statusHints; @@ -202,6 +208,18 @@ public final class ParcelableCall implements Parcelable { return mVideoCall; } + public boolean getIsRttCallChanged() { + return mIsRttCallChanged; + } + + /** + * RTT communication channel information + * @return The ParcelableRttCall + */ + public ParcelableRttCall getParcelableRttCall() { + return mRttCall; + } + /** * The conference call to which this call is conferenced. Null if not conferenced. */ @@ -301,6 +319,8 @@ public final class ParcelableCall implements Parcelable { Bundle intentExtras = source.readBundle(classLoader); Bundle extras = source.readBundle(classLoader); int supportedAudioRoutes = source.readInt(); + boolean isRttCallChanged = source.readByte() == 1; + ParcelableRttCall rttCall = source.readParcelable(classLoader); return new ParcelableCall( id, state, @@ -318,6 +338,8 @@ public final class ParcelableCall implements Parcelable { accountHandle, isVideoCallProviderChanged, videoCallProvider, + isRttCallChanged, + rttCall, parentCallId, childCallIds, statusHints, @@ -366,6 +388,8 @@ public final class ParcelableCall implements Parcelable { destination.writeBundle(mIntentExtras); destination.writeBundle(mExtras); destination.writeInt(mSupportedAudioRoutes); + destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0)); + destination.writeParcelable(mRttCall, 0); } @Override diff --git a/telecomm/java/android/telecom/ParcelableRttCall.aidl b/telecomm/java/android/telecom/ParcelableRttCall.aidl new file mode 100644 index 000000000000..4480710f51f6 --- /dev/null +++ b/telecomm/java/android/telecom/ParcelableRttCall.aidl @@ -0,0 +1,22 @@ +/* + * Copyright 2017, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telecom; + +/** + * {@hide} + */ +parcelable ParcelableRttCall; diff --git a/telecomm/java/android/telecom/ParcelableRttCall.java b/telecomm/java/android/telecom/ParcelableRttCall.java new file mode 100644 index 000000000000..763e48b19779 --- /dev/null +++ b/telecomm/java/android/telecom/ParcelableRttCall.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package android.telecom; + +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; + +/** + * Data container for information associated with the RTT connection on a call. + * @hide + */ +public class ParcelableRttCall implements Parcelable { + private final int mRttMode; + private final ParcelFileDescriptor mTransmitStream; + private final ParcelFileDescriptor mReceiveStream; + + public ParcelableRttCall( + int rttMode, + ParcelFileDescriptor transmitStream, + ParcelFileDescriptor receiveStream) { + mRttMode = rttMode; + mTransmitStream = transmitStream; + mReceiveStream = receiveStream; + } + + protected ParcelableRttCall(Parcel in) { + mRttMode = in.readInt(); + mTransmitStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); + mReceiveStream = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); + } + + public static final Creator<ParcelableRttCall> CREATOR = new Creator<ParcelableRttCall>() { + @Override + public ParcelableRttCall createFromParcel(Parcel in) { + return new ParcelableRttCall(in); + } + + @Override + public ParcelableRttCall[] newArray(int size) { + return new ParcelableRttCall[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mRttMode); + dest.writeParcelable(mTransmitStream, flags); + dest.writeParcelable(mReceiveStream, flags); + } + + public int getRttMode() { + return mRttMode; + } + + public ParcelFileDescriptor getReceiveStream() { + return mReceiveStream; + } + + public ParcelFileDescriptor getTransmitStream() { + return mTransmitStream; + } +} diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index 30ec5b350307..ebd04c7cd666 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -201,6 +201,13 @@ public final class Phone { } } + final void internalOnRttUpgradeRequest(String callId, int requestId) { + Call call = mCallByTelecomCallId.get(callId); + if (call != null) { + call.internalOnRttUpgradeRequest(requestId); + } + } + /** * Called to destroy the phone and cleanup any lingering calls. */ diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 845a1033c123..3926e201a5e3 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -204,6 +204,18 @@ public final class PhoneAccount implements Parcelable { public static final int CAPABILITY_SELF_MANAGED = 0x800; /** + * Flag indicating that this {@link PhoneAccount} is capable of making a call with an + * RTT (Real-time text) session. + * When set, Telecom will attempt to open an RTT session on outgoing calls that specify + * that they should be placed with an RTT session , and the in-call app will be displayed + * with text entry fields for RTT. Likewise, the in-call app can request that an RTT + * session be opened during a call if this bit is set. + */ + public static final int CAPABILITY_RTT = 0x1000; + + /* NEXT CAPABILITY: 0x2000 */ + + /** * URI scheme for telephone number URIs. */ public static final String SCHEME_TEL = "tel"; diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index 0c7404aa5e95..60a40f5261dd 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -450,11 +450,14 @@ final class RemoteConnectionService { ConnectionRequest request, boolean isIncoming) { final String id = UUID.randomUUID().toString(); - final ConnectionRequest newRequest = new ConnectionRequest( - request.getAccountHandle(), - request.getAddress(), - request.getExtras(), - request.getVideoState()); + final ConnectionRequest newRequest = new ConnectionRequest.Builder() + .setAccountHandle(request.getAccountHandle()) + .setAddress(request.getAddress()) + .setExtras(request.getExtras()) + .setVideoState(request.getVideoState()) + .setRttPipeFromInCall(request.getRttPipeFromInCall()) + .setRttPipeToInCall(request.getRttPipeToInCall()) + .build(); try { if (mConnectionById.isEmpty()) { mOutgoingConnectionServiceRpc.addConnectionServiceAdapter(mServant.getStub(), diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 7964cf2c8346..6807ef4b0601 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -326,6 +326,14 @@ public class TelecomManager { "android.telecom.extra.NEW_OUTGOING_CALL_CANCEL_TIMEOUT"; /** + * A boolean extra, which when set on the {@link Intent#ACTION_CALL} intent or on the bundle + * passed into {@link #placeCall(Uri, Bundle)}, indicates that the call should be initiated with + * an RTT session open. See {@link android.telecom.Call.RttCall} for more information on RTT. + */ + public static final String EXTRA_START_CALL_WITH_RTT = + "android.telecom.extra.START_CALL_WITH_RTT"; + + /** * A boolean meta-data value indicating whether an {@link InCallService} implements an * in-call user interface. Dialer implementations (see {@link #getDefaultDialerPackage()}) which * would also like to replace the in-call interface should set this meta-data to {@code true} in diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index 49f9b3b8af73..47c3e6cfc3d5 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -69,4 +69,12 @@ oneway interface IInCallAdapter { void putExtras(String callId, in Bundle extras); void removeExtras(String callId, in List<String> keys); + + void sendRttRequest(); + + void respondToRttRequest(int id, boolean accept); + + void stopRtt(); + + void setRttMode(int mode); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl index 3e43fe22cdfb..1f92e0c42443 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl @@ -50,4 +50,6 @@ oneway interface IInCallService { void silenceRinger(); void onConnectionEvent(String callId, String event, in Bundle extras); + + void onRttUpgradeRequest(String callId, int id); } |