diff options
17 files changed, 670 insertions, 20 deletions
diff --git a/api/current.txt b/api/current.txt index 0c20240150ae..1484267275e5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -36691,6 +36691,7 @@ 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 onRttInitiationFailure(android.telecom.Call, int); 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); @@ -36957,6 +36958,15 @@ package android.telecom { field public static final int STATE_RINGING = 2; // 0x2 } + public static final class Connection.RttModifyStatus { + ctor public Connection.RttModifyStatus(); + field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2 + field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3 + field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5 + field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1 + field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4 + } + public static abstract class Connection.VideoProvider { ctor public Connection.VideoProvider(); method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); diff --git a/api/system-current.txt b/api/system-current.txt index d6b6ad4a18d5..0968557c9ada 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -39665,6 +39665,7 @@ 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 onRttInitiationFailure(android.telecom.Call, int); 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); @@ -39942,6 +39943,15 @@ package android.telecom { field public static final int STATE_RINGING = 2; // 0x2 } + public static final class Connection.RttModifyStatus { + ctor public Connection.RttModifyStatus(); + field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2 + field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3 + field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5 + field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1 + field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4 + } + public static abstract class Connection.VideoProvider { ctor public Connection.VideoProvider(); method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); diff --git a/api/test-current.txt b/api/test-current.txt index 7aaab5bae645..6a964ff15860 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -36773,6 +36773,7 @@ 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 onRttInitiationFailure(android.telecom.Call, int); 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); @@ -37039,6 +37040,15 @@ package android.telecom { field public static final int STATE_RINGING = 2; // 0x2 } + public static final class Connection.RttModifyStatus { + ctor public Connection.RttModifyStatus(); + field public static final int SESSION_MODIFY_REQUEST_FAIL = 2; // 0x2 + field public static final int SESSION_MODIFY_REQUEST_INVALID = 3; // 0x3 + field public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; // 0x5 + field public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; // 0x1 + field public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; // 0x4 + } + public static abstract class Connection.VideoProvider { ctor public Connection.VideoProvider(); method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities); diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index e939b2e90d6c..9dc7dc5e30a6 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -871,6 +871,16 @@ public final class Call { * @param id The ID of the request. */ public void onRttRequest(Call call, int id) {} + + /** + * Invoked when the RTT session failed to initiate for some reason, including rejection + * by the remote party. + * @param call The call which the RTT initiation failure occurred on. + * @param reason One of the status codes defined in + * {@link android.telecom.Connection.RttModifyStatus}, with the exception of + * {@link android.telecom.Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. + */ + public void onRttInitiationFailure(Call call, int reason) {} } /** @@ -913,13 +923,15 @@ public final class Call { private OutputStreamWriter mTransmitStream; private int mRttMode; private final InCallAdapter mInCallAdapter; + private final String mTelecomCallId; private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; /** * @hide */ - public RttCall(InputStreamReader receiveStream, OutputStreamWriter transmitStream, - int mode, InCallAdapter inCallAdapter) { + public RttCall(String telecomCallId, InputStreamReader receiveStream, + OutputStreamWriter transmitStream, int mode, InCallAdapter inCallAdapter) { + mTelecomCallId = telecomCallId; mReceiveStream = receiveStream; mTransmitStream = transmitStream; mRttMode = mode; @@ -942,7 +954,7 @@ public final class Call { * {@link #RTT_MODE_VCO}, or {@link #RTT_MODE_HCO}. */ public void setRttMode(@RttAudioMode int mode) { - mInCallAdapter.setRttMode(mode); + mInCallAdapter.setRttMode(mTelecomCallId, mode); } /** @@ -1213,7 +1225,7 @@ public final class Call { * {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback. */ public void sendRttRequest() { - mInCallAdapter.sendRttRequest(); + mInCallAdapter.sendRttRequest(mTelecomCallId); } /** @@ -1224,7 +1236,7 @@ public final class Call { * @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); + mInCallAdapter.respondToRttRequest(mTelecomCallId, id, accept); } /** @@ -1232,7 +1244,7 @@ public final class Call { * the {@link Callback#onRttStatusChanged(Call, boolean, RttCall)} callback. */ public void stopRtt() { - mInCallAdapter.stopRtt(); + mInCallAdapter.stopRtt(mTelecomCallId); } /** @@ -1637,7 +1649,7 @@ public final class Call { new ParcelFileDescriptor.AutoCloseOutputStream( parcelableRttCall.getTransmitStream()), StandardCharsets.UTF_8); - RttCall newRttCall = new Call.RttCall( + RttCall newRttCall = new Call.RttCall(mTelecomCallId, receiveStream, transmitStream, parcelableRttCall.getRttMode(), mInCallAdapter); if (mRttCall == null) { isRttChanged = true; @@ -1717,6 +1729,15 @@ public final class Call { } } + /** @hide */ + final void internalOnRttInitiationFailure(int reason) { + for (CallbackRecord<Callback> record : mCallbackRecords) { + final Call call = this; + final Callback callback = record.getCallback(); + record.getHandler().post(() -> callback.onRttInitiationFailure(call, reason)); + } + } + private void fireStateChanged(final int newState) { for (CallbackRecord<Callback> record : mCallbackRecords) { final Call call = this; diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index 3e690b997b29..c2824f403fa9 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -20,6 +20,7 @@ import com.android.internal.os.SomeArgs; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -39,6 +40,8 @@ import android.view.Surface; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -764,6 +767,10 @@ public abstract class Connection extends Conferenceable { /** @hide */ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {} public void onAudioRouteChanged(Connection c, int audioRoute) {} + public void onRttInitiationSuccess(Connection c) {} + public void onRttInitiationFailure(Connection c, int reason) {} + public void onRttSessionRemotelyTerminated(Connection c) {} + public void onRemoteRttRequest(Connection c) {} } /** @@ -774,12 +781,16 @@ public abstract class Connection extends Conferenceable { private static final int READ_BUFFER_SIZE = 1000; private final InputStreamReader mPipeFromInCall; private final OutputStreamWriter mPipeToInCall; + private final ParcelFileDescriptor mFdFromInCall; + private final ParcelFileDescriptor mFdToInCall; private char[] mReadBuffer = new char[READ_BUFFER_SIZE]; /** * @hide */ public RttTextStream(ParcelFileDescriptor toInCall, ParcelFileDescriptor fromInCall) { + mFdFromInCall = fromInCall; + mFdToInCall = toInCall; mPipeFromInCall = new InputStreamReader( new ParcelFileDescriptor.AutoCloseInputStream(fromInCall)); mPipeToInCall = new OutputStreamWriter( @@ -823,6 +834,47 @@ public abstract class Connection extends Conferenceable { return null; } } + + /** @hide */ + public ParcelFileDescriptor getFdFromInCall() { + return mFdFromInCall; + } + + /** @hide */ + public ParcelFileDescriptor getFdToInCall() { + return mFdToInCall; + } + } + + /** + * Provides constants to represent the results of responses to session modify requests sent via + * {@link Call#sendRttRequest()} + */ + public static final class RttModifyStatus { + /** + * Session modify request was successful. + */ + public static final int SESSION_MODIFY_REQUEST_SUCCESS = 1; + + /** + * Session modify request failed. + */ + public static final int SESSION_MODIFY_REQUEST_FAIL = 2; + + /** + * Session modify request ignored due to invalid parameters. + */ + public static final int SESSION_MODIFY_REQUEST_INVALID = 3; + + /** + * Session modify request timed out. + */ + public static final int SESSION_MODIFY_REQUEST_TIMED_OUT = 4; + + /** + * Session modify request rejected by remote user. + */ + public static final int SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE = 5; } /** @@ -2426,6 +2478,47 @@ public abstract class Connection extends Conferenceable { } /** + * Informs listeners that a previously requested RTT session via + * {@link ConnectionRequest#isRequestingRtt()} or + * {@link #onStartRtt(ParcelFileDescriptor, ParcelFileDescriptor)} has succeeded. + * @hide + */ + public final void sendRttInitiationSuccess() { + mListeners.forEach((l) -> l.onRttInitiationSuccess(Connection.this)); + } + + /** + * Informs listeners that a previously requested RTT session via + * {@link ConnectionRequest#isRequestingRtt()} or + * {@link #onStartRtt(ParcelFileDescriptor, ParcelFileDescriptor)} + * has failed. + * @param reason One of the reason codes defined in {@link RttModifyStatus}, with the + * exception of {@link RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. + * @hide + */ + public final void sendRttInitiationFailure(int reason) { + mListeners.forEach((l) -> l.onRttInitiationFailure(Connection.this, reason)); + } + + /** + * Informs listeners that a currently active RTT session has been terminated by the remote + * side of the coll. + * @hide + */ + public final void sendRttSessionRemotelyTerminated() { + mListeners.forEach((l) -> l.onRttSessionRemotelyTerminated(Connection.this)); + } + + /** + * Informs listeners that the remote side of the call has requested an upgrade to include an + * RTT session in the call. + * @hide + */ + public final void sendRemoteRttRequest() { + mListeners.forEach((l) -> l.onRemoteRttRequest(Connection.this)); + } + + /** * Notifies this Connection that the {@link #getAudioState()} property has a new value. * * @param state The new connection audio state. @@ -2595,6 +2688,35 @@ public abstract class Connection extends Conferenceable { */ public void onShowIncomingCallUi() {} + /** + * Notifies this {@link Connection} that the user has requested an RTT session. + * The connection service should call {@link #sendRttInitiationSuccess} or + * {@link #sendRttInitiationFailure} to inform Telecom of the success or failure of the + * request, respectively. + * @param rttTextStream The object that should be used to send text to or receive text from + * the in-call app. + * @hide + */ + public void onStartRtt(@NonNull RttTextStream rttTextStream) {} + + /** + * Notifies this {@link Connection} that it should terminate any existing RTT communication + * channel. No response to Telecom is needed for this method. + * @hide + */ + public void onStopRtt() {} + + /** + * Notifies this connection of a response to a previous remotely-initiated RTT upgrade + * request sent via {@link #sendRemoteRttRequest}. Acceptance of the request is + * indicated by the supplied {@link RttTextStream} being non-null, and rejection is + * indicated by {@code rttTextStream} being {@code null} + * @hide + * @param rttTextStream The object that should be used to send text to or receive text from + * the in-call app. + */ + public void handleRttUpgradeResponse(@Nullable RttTextStream rttTextStream) {} + static String toLogSafePhoneNumber(String number) { // For unknown number, log empty string. if (number == null) { diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 6e100298da35..9bc77b81e3aa 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -26,6 +26,8 @@ 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.telecom.Logging.Session; import com.android.internal.os.SomeArgs; @@ -119,6 +121,9 @@ public abstract class ConnectionService extends Service { private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC"; private static final String SESSION_SEND_CALL_EVENT = "CS.sCE"; private static final String SESSION_EXTRAS_CHANGED = "CS.oEC"; + private static final String SESSION_START_RTT = "CS.+RTT"; + private static final String SESSION_STOP_RTT = "CS.-RTT"; + private static final String SESSION_RTT_UPGRADE_RESPONSE = "CS.rTRUR"; private static final int MSG_ADD_CONNECTION_SERVICE_ADAPTER = 1; private static final int MSG_CREATE_CONNECTION = 2; @@ -144,6 +149,9 @@ public abstract class ConnectionService extends Service { private static final int MSG_SEND_CALL_EVENT = 23; private static final int MSG_ON_EXTRAS_CHANGED = 24; private static final int MSG_CREATE_CONNECTION_FAILED = 25; + private static final int MSG_ON_START_RTT = 26; + private static final int MSG_ON_STOP_RTT = 27; + private static final int MSG_RTT_UPGRADE_RESPONSE = 28; private static Connection sNullConnection; @@ -501,6 +509,53 @@ public abstract class ConnectionService extends Service { Log.endSession(); } } + + @Override + public void startRtt(String callId, ParcelFileDescriptor fromInCall, + ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { + Log.startSession(sessionInfo, SESSION_START_RTT); + try { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = new Connection.RttTextStream(toInCall, fromInCall); + args.arg3 = Log.createSubsession(); + mHandler.obtainMessage(MSG_ON_START_RTT, args).sendToTarget(); + } finally { + Log.endSession(); + } + } + + @Override + public void stopRtt(String callId, Session.Info sessionInfo) throws RemoteException { + Log.startSession(sessionInfo, SESSION_STOP_RTT); + try { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + args.arg2 = Log.createSubsession(); + mHandler.obtainMessage(MSG_ON_STOP_RTT, args).sendToTarget(); + } finally { + Log.endSession(); + } + } + + @Override + public void respondToRttUpgradeRequest(String callId, ParcelFileDescriptor fromInCall, + ParcelFileDescriptor toInCall, Session.Info sessionInfo) throws RemoteException { + Log.startSession(sessionInfo, SESSION_RTT_UPGRADE_RESPONSE); + try { + SomeArgs args = SomeArgs.obtain(); + args.arg1 = callId; + if (toInCall == null || fromInCall == null) { + args.arg2 = null; + } else { + args.arg2 = new Connection.RttTextStream(toInCall, fromInCall); + } + args.arg3 = Log.createSubsession(); + mHandler.obtainMessage(MSG_RTT_UPGRADE_RESPONSE, args).sendToTarget(); + } finally { + Log.endSession(); + } + } }; private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -848,6 +903,49 @@ public abstract class ConnectionService extends Service { } break; } + case MSG_ON_START_RTT: { + SomeArgs args = (SomeArgs) msg.obj; + try { + Log.continueSession((Session) args.arg3, + SESSION_HANDLER + SESSION_START_RTT); + String callId = (String) args.arg1; + Connection.RttTextStream rttTextStream = + (Connection.RttTextStream) args.arg2; + startRtt(callId, rttTextStream); + } finally { + args.recycle(); + Log.endSession(); + } + break; + } + case MSG_ON_STOP_RTT: { + SomeArgs args = (SomeArgs) msg.obj; + try { + Log.continueSession((Session) args.arg2, + SESSION_HANDLER + SESSION_STOP_RTT); + String callId = (String) args.arg1; + stopRtt(callId); + } finally { + args.recycle(); + Log.endSession(); + } + break; + } + case MSG_RTT_UPGRADE_RESPONSE: { + SomeArgs args = (SomeArgs) msg.obj; + try { + Log.continueSession((Session) args.arg3, + SESSION_HANDLER + SESSION_RTT_UPGRADE_RESPONSE); + String callId = (String) args.arg1; + Connection.RttTextStream rttTextStream = + (Connection.RttTextStream) args.arg2; + handleRttUpgradeResponse(callId, rttTextStream); + } finally { + args.recycle(); + Log.endSession(); + } + break; + } default: break; } @@ -1136,6 +1234,38 @@ public abstract class ConnectionService extends Service { mAdapter.setAudioRoute(id, audioRoute); } } + + @Override + public void onRttInitiationSuccess(Connection c) { + String id = mIdByConnection.get(c); + if (id != null) { + mAdapter.onRttInitiationSuccess(id); + } + } + + @Override + public void onRttInitiationFailure(Connection c, int reason) { + String id = mIdByConnection.get(c); + if (id != null) { + mAdapter.onRttInitiationFailure(id, reason); + } + } + + @Override + public void onRttSessionRemotelyTerminated(Connection c) { + String id = mIdByConnection.get(c); + if (id != null) { + mAdapter.onRttSessionRemotelyTerminated(id); + } + } + + @Override + public void onRemoteRttRequest(Connection c) { + String id = mIdByConnection.get(c); + if (id != null) { + mAdapter.onRemoteRttRequest(id); + } + } }; /** {@inheritDoc} */ @@ -1430,7 +1560,6 @@ public abstract class ConnectionService extends Service { if (connection != null) { connection.onCallEvent(event, extras); } - } /** @@ -1454,6 +1583,34 @@ public abstract class ConnectionService extends Service { } } + private void startRtt(String callId, Connection.RttTextStream rttTextStream) { + Log.d(this, "startRtt(%s)", callId); + if (mConnectionById.containsKey(callId)) { + findConnectionForAction(callId, "startRtt").onStartRtt(rttTextStream); + } else if (mConferenceById.containsKey(callId)) { + Log.w(this, "startRtt called on a conference."); + } + } + + private void stopRtt(String callId) { + Log.d(this, "stopRtt(%s)", callId); + if (mConnectionById.containsKey(callId)) { + findConnectionForAction(callId, "stopRtt").onStopRtt(); + } else if (mConferenceById.containsKey(callId)) { + Log.w(this, "stopRtt called on a conference."); + } + } + + private void handleRttUpgradeResponse(String callId, Connection.RttTextStream rttTextStream) { + Log.d(this, "handleRttUpgradeResponse(%s, %s)", callId, rttTextStream == null); + if (mConnectionById.containsKey(callId)) { + findConnectionForAction(callId, "handleRttUpgradeResponse") + .handleRttUpgradeResponse(rttTextStream); + } else if (mConferenceById.containsKey(callId)) { + Log.w(this, "handleRttUpgradeResponse called on a conference."); + } + } + private void onPostDialContinue(String callId, boolean proceed) { Log.d(this, "onPostDialContinue(%s)", callId); findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed); diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java index 9542b73c68fb..63bdf74d383c 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java @@ -547,4 +547,66 @@ final class ConnectionServiceAdapter implements DeathRecipient { } } } + + /** + * Notifies Telecom that an RTT session was successfully established. + * + * @param callId The unique ID of the call. + */ + void onRttInitiationSuccess(String callId) { + Log.v(this, "onRttInitiationSuccess: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.onRttInitiationSuccess(callId, Log.getExternalSession()); + } catch (RemoteException ignored) { + } + } + } + + /** + * Notifies Telecom that a requested RTT session failed to be established. + * + * @param callId The unique ID of the call. + */ + void onRttInitiationFailure(String callId, int reason) { + Log.v(this, "onRttInitiationFailure: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.onRttInitiationFailure(callId, reason, Log.getExternalSession()); + } catch (RemoteException ignored) { + } + } + } + + /** + * Notifies Telecom that an established RTT session was terminated by the remote user on + * the call. + * + * @param callId The unique ID of the call. + */ + void onRttSessionRemotelyTerminated(String callId) { + Log.v(this, "onRttSessionRemotelyTerminated: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.onRttSessionRemotelyTerminated(callId, Log.getExternalSession()); + } catch (RemoteException ignored) { + } + } + } + + /** + * Notifies Telecom that the remote user on the call has requested an upgrade to an RTT + * session for this call. + * + * @param callId The unique ID of the call. + */ + void onRemoteRttRequest(String callId) { + Log.v(this, "onRemoteRttRequest: %s", callId); + for (IConnectionServiceAdapter adapter : mAdapters) { + try { + adapter.onRemoteRttRequest(callId, Log.getExternalSession()); + } catch (RemoteException ignored) { + } + } + } } diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java index cc437f9c7cd0..80e3c33a443d 100644 --- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java +++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java @@ -68,6 +68,10 @@ final class ConnectionServiceAdapterServant { private static final int MSG_SET_CONNECTION_PROPERTIES = 27; private static final int MSG_SET_PULLING = 28; private static final int MSG_SET_AUDIO_ROUTE = 29; + private static final int MSG_ON_RTT_INITIATION_SUCCESS = 30; + private static final int MSG_ON_RTT_INITIATION_FAILURE = 31; + private static final int MSG_ON_RTT_REMOTELY_TERMINATED = 32; + private static final int MSG_ON_RTT_UPGRADE_REQUEST = 33; private final IConnectionServiceAdapter mDelegate; @@ -300,6 +304,20 @@ final class ConnectionServiceAdapterServant { } break; } + case MSG_ON_RTT_INITIATION_SUCCESS: + mDelegate.onRttInitiationSuccess((String) msg.obj, null /*Session.Info*/); + break; + case MSG_ON_RTT_INITIATION_FAILURE: + mDelegate.onRttInitiationFailure((String) msg.obj, msg.arg1, + null /*Session.Info*/); + break; + case MSG_ON_RTT_REMOTELY_TERMINATED: + mDelegate.onRttSessionRemotelyTerminated((String) msg.obj, + null /*Session.Info*/); + break; + case MSG_ON_RTT_UPGRADE_REQUEST: + mDelegate.onRemoteRttRequest((String) msg.obj, null /*Session.Info*/); + break; } } }; @@ -537,6 +555,32 @@ final class ConnectionServiceAdapterServant { args.arg3 = extras; mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget(); } + + @Override + public void onRttInitiationSuccess(String connectionId, Session.Info sessionInfo) + throws RemoteException { + mHandler.obtainMessage(MSG_ON_RTT_INITIATION_SUCCESS, connectionId).sendToTarget(); + } + + @Override + public void onRttInitiationFailure(String connectionId, int reason, + Session.Info sessionInfo) + throws RemoteException { + mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, connectionId) + .sendToTarget(); + } + + @Override + public void onRttSessionRemotelyTerminated(String connectionId, Session.Info sessionInfo) + throws RemoteException { + mHandler.obtainMessage(MSG_ON_RTT_REMOTELY_TERMINATED, connectionId).sendToTarget(); + } + + @Override + public void onRemoteRttRequest(String connectionId, Session.Info sessionInfo) + throws RemoteException { + mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, connectionId).sendToTarget(); + } }; public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) { diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java index d640b1dd6022..9559a28c0bef 100644 --- a/telecomm/java/android/telecom/InCallAdapter.java +++ b/telecomm/java/android/telecom/InCallAdapter.java @@ -379,9 +379,9 @@ public final class InCallAdapter { /** * Sends an RTT upgrade request to the remote end of the connection. */ - public void sendRttRequest() { + public void sendRttRequest(String callId) { try { - mAdapter.sendRttRequest(); + mAdapter.sendRttRequest(callId); } catch (RemoteException ignored) { } } @@ -392,9 +392,9 @@ public final class InCallAdapter { * @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) { + public void respondToRttRequest(String callId, int id, boolean accept) { try { - mAdapter.respondToRttRequest(id, accept); + mAdapter.respondToRttRequest(callId, id, accept); } catch (RemoteException ignored) { } } @@ -402,9 +402,9 @@ public final class InCallAdapter { /** * Instructs Telecom to shut down the RTT communication channel. */ - public void stopRtt() { + public void stopRtt(String callId) { try { - mAdapter.stopRtt(); + mAdapter.stopRtt(callId); } catch (RemoteException ignored) { } } @@ -413,9 +413,9 @@ public final class InCallAdapter { * Sets the RTT audio mode. * @param mode the desired RTT audio mode */ - public void setRttMode(int mode) { + public void setRttMode(String callId, int mode) { try { - mAdapter.setRttMode(mode); + mAdapter.setRttMode(callId, mode); } catch (RemoteException ignored) { } } diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 4bc64c05bfee..5d8f9f6d5a7b 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -77,6 +77,7 @@ public abstract class InCallService extends Service { 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; + private static final int MSG_ON_RTT_INITIATION_FAILURE = 11; /** Default Handler used to consolidate binder method calls onto a single thread. */ private final Handler mHandler = new Handler(Looper.getMainLooper()) { @@ -140,6 +141,12 @@ public abstract class InCallService extends Service { mPhone.internalOnRttUpgradeRequest(callId, requestId); break; } + case MSG_ON_RTT_INITIATION_FAILURE: { + String callId = (String) msg.obj; + int reason = msg.arg1; + mPhone.internalOnRttInitiationFailure(callId, reason); + break; + } default: break; } @@ -210,6 +217,11 @@ public abstract class InCallService extends Service { public void onRttUpgradeRequest(String callId, int id) { mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget(); } + + @Override + public void onRttInitiationFailure(String callId, int reason) { + mHandler.obtainMessage(MSG_ON_RTT_INITIATION_FAILURE, reason, 0, callId).sendToTarget(); + } } private Phone.Listener mPhoneListener = new Phone.Listener() { diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index ebd04c7cd666..db2abf30cf6d 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -208,6 +208,13 @@ public final class Phone { } } + final void internalOnRttInitiationFailure(String callId, int reason) { + Call call = mCallByTelecomCallId.get(callId); + if (call != null) { + call.internalOnRttInitiationFailure(reason); + } + } + /** * Called to destroy the phone and cleanup any lingering calls. */ diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 77e0e5486127..1ca54c867dd7 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -20,6 +20,7 @@ import com.android.internal.telecom.IConnectionService; import com.android.internal.telecom.IVideoCallback; import com.android.internal.telecom.IVideoProvider; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.hardware.camera2.CameraManager; @@ -231,6 +232,41 @@ public final class RemoteConnection { * @param extras Extras associated with the event. */ public void onConnectionEvent(RemoteConnection connection, String event, Bundle extras) {} + + /** + * Indicates that a RTT session was successfully established on this + * {@link RemoteConnection}. See {@link Connection#sendRttInitiationSuccess()}. + * @hide + * @param connection The {@code RemoteConnection} invoking this method. + */ + public void onRttInitiationSuccess(RemoteConnection connection) {} + + /** + * Indicates that a RTT session failed to be established on this + * {@link RemoteConnection}. See {@link Connection#sendRttInitiationFailure()}. + * @hide + * @param connection The {@code RemoteConnection} invoking this method. + * @param reason One of the reason codes defined in {@link Connection.RttModifyStatus}, + * with the exception of + * {@link Connection.RttModifyStatus#SESSION_MODIFY_REQUEST_SUCCESS}. + */ + public void onRttInitiationFailure(RemoteConnection connection, int reason) {} + + /** + * Indicates that an established RTT session was terminated remotely on this + * {@link RemoteConnection}. See {@link Connection#sendRttSessionRemotelyTerminated()} + * @hide + * @param connection The {@code RemoteConnection} invoking this method. + */ + public void onRttSessionRemotelyTerminated(RemoteConnection connection) {} + + /** + * Indicates that the remote user on this {@link RemoteConnection} has requested an upgrade + * to an RTT session. See {@link Connection#sendRemoteRttRequest()} + * @hide + * @param connection The {@code RemoteConnection} invoking this method. + */ + public void onRemoteRttRequest(RemoteConnection connection) {} } /** @@ -1046,6 +1082,61 @@ public final class RemoteConnection { } /** + * Notifies this {@link RemoteConnection} that the user has requested an RTT session. + * @param rttTextStream The object that should be used to send text to or receive text from + * the in-call app. + * @hide + */ + public void startRtt(@NonNull Connection.RttTextStream rttTextStream) { + try { + if (mConnected) { + mConnectionService.startRtt(mConnectionId, rttTextStream.getFdFromInCall(), + rttTextStream.getFdToInCall(), null /*Session.Info*/); + } + } catch (RemoteException ignored) { + } + } + + /** + * Notifies this {@link RemoteConnection} that it should terminate any existing RTT + * session. No response to Telecom is needed for this method. + * @hide + */ + public void stopRtt() { + try { + if (mConnected) { + mConnectionService.stopRtt(mConnectionId, null /*Session.Info*/); + } + } catch (RemoteException ignored) { + } + } + + /** + * Notifies this {@link RemoteConnection} of a response to a previous remotely-initiated RTT + * upgrade request sent via {@link Connection#sendRemoteRttRequest}. + * Acceptance of the request is indicated by the supplied {@link RttTextStream} being non-null, + * and rejection is indicated by {@code rttTextStream} being {@code null} + * @hide + * @param rttTextStream The object that should be used to send text to or receive text from + * the in-call app. + */ + public void sendRttUpgradeResponse(@Nullable Connection.RttTextStream rttTextStream) { + try { + if (mConnected) { + if (rttTextStream == null) { + mConnectionService.respondToRttUpgradeRequest(mConnectionId, + null, null, null /*Session.Info*/); + } else { + mConnectionService.respondToRttUpgradeRequest(mConnectionId, + rttTextStream.getFdFromInCall(), rttTextStream.getFdToInCall(), + null /*Session.Info*/); + } + } + } catch (RemoteException ignored) { + } + } + + /** * Obtain the {@code RemoteConnection}s with which this {@code RemoteConnection} may be * successfully asked to create a conference with. * @@ -1411,6 +1502,47 @@ public final class RemoteConnection { } } + /** @hide */ + void onRttInitiationSuccess() { + for (CallbackRecord record : mCallbackRecords) { + final RemoteConnection connection = this; + final Callback callback = record.getCallback(); + record.getHandler().post( + () -> callback.onRttInitiationSuccess(connection)); + } + } + + /** @hide */ + void onRttInitiationFailure(int reason) { + for (CallbackRecord record : mCallbackRecords) { + final RemoteConnection connection = this; + final Callback callback = record.getCallback(); + record.getHandler().post( + () -> callback.onRttInitiationFailure(connection, reason)); + } + } + + /** @hide */ + void onRttSessionRemotelyTerminated() { + for (CallbackRecord record : mCallbackRecords) { + final RemoteConnection connection = this; + final Callback callback = record.getCallback(); + record.getHandler().post( + () -> callback.onRttSessionRemotelyTerminated(connection)); + } + } + + /** @hide */ + void onRemoteRttRequest() { + for (CallbackRecord record : mCallbackRecords) { + final RemoteConnection connection = this; + final Callback callback = record.getCallback(); + record.getHandler().post( + () -> callback.onRemoteRttRequest(connection)); + } + } + + /** /** * Create a RemoteConnection represents a failure, and which will be in * {@link Connection#STATE_DISCONNECTED}. Attempting to use it for anything will almost diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index 60a40f5261dd..ffba93a3edf8 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -405,6 +405,50 @@ final class RemoteConnectionService { extras); } } + + @Override + public void onRttInitiationSuccess(String callId, Session.Info sessionInfo) + throws RemoteException { + if (hasConnection(callId)) { + findConnectionForAction(callId, "onRttInitiationSuccess") + .onRttInitiationSuccess(); + } else { + Log.w(this, "onRttInitiationSuccess called on a remote conference"); + } + } + + @Override + public void onRttInitiationFailure(String callId, int reason, Session.Info sessionInfo) + throws RemoteException { + if (hasConnection(callId)) { + findConnectionForAction(callId, "onRttInitiationFailure") + .onRttInitiationFailure(reason); + } else { + Log.w(this, "onRttInitiationFailure called on a remote conference"); + } + } + + @Override + public void onRttSessionRemotelyTerminated(String callId, Session.Info sessionInfo) + throws RemoteException { + if (hasConnection(callId)) { + findConnectionForAction(callId, "onRttSessionRemotelyTerminated") + .onRttSessionRemotelyTerminated(); + } else { + Log.w(this, "onRttSessionRemotelyTerminated called on a remote conference"); + } + } + + @Override + public void onRemoteRttRequest(String callId, Session.Info sessionInfo) + throws RemoteException { + if (hasConnection(callId)) { + findConnectionForAction(callId, "onRemoteRttRequest") + .onRemoteRttRequest(); + } else { + Log.w(this, "onRemoteRttRequest called on a remote conference"); + } + } }; private final ConnectionServiceAdapterServant mServant = diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index 20feba78f5c9..114949ee284a 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -17,6 +17,7 @@ package com.android.internal.telecom; import android.os.Bundle; +import android.os.ParcelFileDescriptor; import android.telecom.CallAudioState; import android.telecom.ConnectionRequest; import android.telecom.Logging.Session; @@ -89,4 +90,12 @@ oneway interface IConnectionService { void sendCallEvent(String callId, String event, in Bundle extras, in Session.Info sessionInfo); void onExtrasChanged(String callId, in Bundle extras, in Session.Info sessionInfo); + + void startRtt(String callId, in ParcelFileDescriptor fromInCall, + in ParcelFileDescriptor toInCall, in Session.Info sessionInfo); + + void stopRtt(String callId, in Session.Info sessionInfo); + + void respondToRttUpgradeRequest(String callId, in ParcelFileDescriptor fromInCall, + in ParcelFileDescriptor toInCall, in Session.Info sessionInfo); } diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl index b58f8bc7a0aa..ac9da2ef9df4 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl @@ -106,4 +106,12 @@ oneway interface IConnectionServiceAdapter { void onConnectionEvent(String callId, String event, in Bundle extras, in Session.Info sessionInfo); + + void onRttInitiationSuccess(String callId, in Session.Info sessionInfo); + + void onRttInitiationFailure(String callId, int reason, in Session.Info sessionInfo); + + void onRttSessionRemotelyTerminated(String callId, in Session.Info sessionInfo); + + void onRemoteRttRequest(String callId, in Session.Info sessionInfo); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl index 47c3e6cfc3d5..73fa29af2ca4 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl @@ -70,11 +70,11 @@ oneway interface IInCallAdapter { void removeExtras(String callId, in List<String> keys); - void sendRttRequest(); + void sendRttRequest(String callId); - void respondToRttRequest(int id, boolean accept); + void respondToRttRequest(String callId, int id, boolean accept); - void stopRtt(); + void stopRtt(String callId); - void setRttMode(int mode); + void setRttMode(String callId, int mode); } diff --git a/telecomm/java/com/android/internal/telecom/IInCallService.aidl b/telecomm/java/com/android/internal/telecom/IInCallService.aidl index 1f92e0c42443..e8cf8e975444 100644 --- a/telecomm/java/com/android/internal/telecom/IInCallService.aidl +++ b/telecomm/java/com/android/internal/telecom/IInCallService.aidl @@ -52,4 +52,6 @@ oneway interface IInCallService { void onConnectionEvent(String callId, String event, in Bundle extras); void onRttUpgradeRequest(String callId, int id); + + void onRttInitiationFailure(String callId, int reason); } |